En el siguiente tutorial vamos a explicar como trabajar con la integración continua de GitLab y con el desarrollo de nuestro tema de Ghost.
Actualmente el tema de ./voidNull está siendo desarrollado directamente por mi desde cero. Mi "laboratorio" consta de un contenedor docker con Ghost donde tengo el tema instalado que es mi repositorio local donde trabajo para hacer los cambios. De esta manera, si hago algún cambio a nivel de CSS o JS se aplican los cambios al momento.
Una cosa que hice es que cuando hiciera pull para subir los cambios al repositorio en GitLab, se ejecutaran unas tareas para importar el tema en el servidor y así tener los últimos cambios creados en desarrollo directamente en producción. Sin tener que descargar el tema y tenerlo que subir de nuevo a Ghost. Todo se hace de forma automática.
Como que en su día monté todo esto para el tema de ./voidNull y no documenté mucho, vamos hacer el proceso con otro tema que tengo entre manos. En este caso, es un fork del tema oficial de Ghost llamado Wave y que es para el podcasting.
El fork está creado en GitHub, pero he clonado una copia en GitLab para configurar la CI directamente y ver que procedimiento debemos de seguir.
El plan
El objetivo es utilizar gulp
para el desarrollo, de esta forma construimos y empaquetamos el tema con diferentes tareas. Aprovechando gulp
, lo que haremos será una tarea más para que se haga el despliegue al servidor, añadir las dependencias necesarias usando yarn
y añadiremos una acción de secuencia de comandos en package.json
para hacer las tareas correspondientes.
Luego tendremos que configurar GitLab-CI para que llame a todas esas tareas, las de construir, empaquetar y desplegar. Muy fácil. 😄
Crear integración en Ghost
Para subir el tema, necesitamos una clave para poder trabajar con la API de Ghost. Para eso necesitamos crear una integración nueva en Ghost. Iremos a Settings - Advanced: Integrations y haremos clic en Add custom integration.
Le pondremos un nombre:
Y podremos añadir una descripción y tendremos los datos que necesitaremos:
Los datos que nos interesan es el Admin API key
y el API URL
para el siguiente paso.
Admin API Key
se genera automáticamente y el API URL
debe de ser el dominio de nuestro Ghost.Configurar variables para GitLab CI
Ahora tendremos que ir a GitLab donde nuestro repositorio e ir a Configuración - CI / CD en el apartado de Variables.
He creado dos variables GHOST_ADMIN_API_KEY
y GHOST_API_URL
:
La primera variable tiene de valor la Admin API keyd
que habíamos visto antes al crear la integración. La segunda variable contiene el dominio completo (con HTTPS) del Ghost en producción.
Añadiendo dependencias
Ghost nos proporciona un SDK de JavaScript que contiene lo suficiente para gestionar la API de Ghost. La API incluye un endpoint que permite cargar temas de paquetes. Esto es lo que utilizaremos para actualizar el tema en producción.
Así que lo instalaremos con Yarn directamente en la ruta de nuestro tema personalizado:
yarn add tryghost/admin-api --dev
Implementando la tarea "deploy"
Para implementar la tarea de deploy, lo haremos usando una tarea de Gulp añadiendo el siguiente código en nuestro gulpfile.js
. Como que en este caso es un fork de un tema oficial de Ghost, ya tendremos este fichero creado con diferentes tareas.
Simplemente deberemos de añadir lo siguiente:
const GhostAdminApi = require('@tryghost/admin-api');
async function deploy(done) {
try {
const url = process.env.GHOST_API_URL;
const admin_api_key = process.env.GHOST_ADMIN_API_KEY;
const themeName = process.env.THEME_NAME || require('./package.json').name;
const zipFile = `dist/${themeName}.zip`;
const api = new GhostAdminApi({
url,
key: admin_api_key,
version: 'v5.0'
});
await api.themes.upload({
file: zipFile
});
console.log(`${zipFile} successfully uploaded.`);
done();
} catch (err) {
console.error(err);
done(err);
}
}
exports.deploy = deploy;
Luego deberemos de añadir la tarea directamente en el package.json
:
/* ... */
"scripts": {
"dev": "gulp",
"test": "gscan .",
"zip": "gulp zip",
"deploy": "gulp deploy" // <= Hay que añadir esto
},
/* ... */
Creando la configuración para GitLab
El siguiente paso será configurar el fichero .gitlab-ci.yml
dentro de nuestro repositorio para así configurar la integración continua con GitLab.
Lo que queremos es que la CI pruebe, compile y luego empaquete siempre que haya cambios en el repositorio. Cuando haga todo eso, entonces quiero que despliegue el tema automáticamente a producción con los nuevos cambios de la rama.
Para todo este proceso hay 3 etapas:
stages:
- .pre
- build
- deploy
install
.pre
es una etapa incorporada que siempre se ejecuta primero. La usaremos para una tarea que llamaremos install. Esta tarea que ejecuta el yarn install y obtiene todas las dependencias para construir, empaquetar y desplegar el tema. Esto creará un directorio llamado node_modules
que va a ser almacenado en caché para siguientes ejecuciones del pipeline.
install:
stage: .pre
script:
- npm install
artifacts: # cache packages for subsequent _steps_ in the same pipelin run
paths:
- node_modules/
expire_in: 30min
cache: # caches packages for subsequent _pipeline_ run
paths:
- node_modules/
build
En esta otra etapa llamaremos la tarea zip
que también viene con el tema. Esto construirá el tema y lo empaquetará como un archivo zip. Este archivo se guardará en GitLab como artefacto que se usará en las tareas posteriores.
Ten en cuenta que esta tarea se ejecutará para todas las ramas y confirmaciones. El paquete estará disponible para su descarga desde la interfaz de usuario de GitLab si es necesario.
build:
stage: build
script:
- npm install
- ./node_modules/gulp/bin/gulp.js zip
artifacts:
expire_in: 1 day
paths:
- dist/
deploy
¡La etapa más divertida!
En esta etapa llamamos la tarea yarn deploy
en el package.json
de antes, que cogerá el archivo zip
que creamos anteriormente por la compilación y lo subirá a Ghost.
No quiero que todos los cambios que haga en cualquier rama se desplieguen a mi blog de producción de inmediato, por lo que este trabajo sólo se ejecutará para los cambios en la rama main
.
deploy:
stage: deploy
script:
- npm install
- ./node_modules/gulp/bin/gulp.js deploy
only:
refs:
- main
Cada vez que hagamos un commit a main
o se haga un merge de una rama a main
, GitLab-CI automáticamente construirá y desplegará el tema en producción. ¡Yuuhuu 🎉!
GitLab-CI al completo:
image: node:16
variables:
THEME_NAME: wavefoss
stages:
- .pre
- build
- deploy
install:
stage: .pre
script:
- npm install
artifacts:
paths:
- node_modules/
expire_in: 30min
cache:
paths:
- node_modules/
build:
stage: build
script:
- npm install
- ls -lat
- ./node_modules/gulp/bin/gulp.js zip
artifacts:
expire_in: 1 day
paths:
- dist/
deploy:
stage: deploy
script:
- npm install
- ./node_modules/gulp/bin/gulp.js deploy
only:
refs:
- main
Ahora subimos todos los cambios que hemos realizado a nuestro repositorio y podremos hacer la comprobación.
Flujo de trabajo
Ahora que tenemos todo preparado veamos como funciona el flujo de trabajo con toda esta nueva configuración.
Cuando hagamos cambios en nuestro tema, podremos crear los commits necesarios para luego hacer un push. Cuando se hace un push se ejecutará automáticamente la tarea build
para construir todo el tema.
Si tras el push vamos a nuestro repositorio en GitLab en el apartado Build - Pipelines podremos ver que se está ejecutando una tarea:
Se encuentra en la primera etapa:
Se irán ejecutando las diferentes etapas:
Cuando finalice, podremos ver las tres etapas en verde:
Y los cambios se habrán publicado en nuestro Ghost directamente. 🥳
Fuente: Wolfgang Rittner Blog
Más sobre ./voidNull
- 📖 Aprende todos sobre los comandos de GNU/Linux en nuestro Diccionario "De la A a la Z: Los comandos de GNU/Linux"
- 💪 ¡Forma parte de la Comunidad de ./voidNull!
- 🤖 Disfruta de todos nuestros Cursos sobre Ansible, Proxmox, Home Assistant entre otros.
- 📩 Mantente actualizado con lo último en GNU/Linux y Software Libre. Recibe nuestra Newsletter mensual.
Comentarios