SetValue.NETSetValue.NET

GatsbyJS en GitHub Pages con Azure DevOps

May 17, 2020

Generic badge

Siguiendo con el anterior post en el que construíamos un sitio estático con GatsbyJS, nos enfrentamos a desplegar el resultado de esta web en un nuevo sitio de GitHub Pages.

Para desplegar la aplicación, utilizaremos Azure DevOps, creando dos pipelines, uno para la integración continua (CI Continuous Integration) y otro para la entrega continua (CD Continuous Delivery).

Configurando el repositorio

El primer paso que debemos realizar es preparar el repositorio para activar y configurar GitHub Pages.

Creamos un nuevo branch llamado gh-pages en el repositorio donde tenemos el sitio estático hecho con GatsbyJS.

New branch

Configuramos GitHub Pages en este repositorio desde la pestaña de settings.

GitHub Pages Settings

Nota: Si tienes un Custom Domain ya agregado, GitHub Pages te sirve todos los sitios web desde el dominio que has configurado

Por último, necesitaremos configurar un PAT (Personal access token) con permisos sobre repo.

Create a new PAT

Almacenamos el token en un lugar seguro para utilizarlo más adelante.

New PAT

Azure DevOps

En Azure DevOps debemos crear dos pipelines, el primero hará la build de la solución y generará un artefacto, el segundo utilizará este artefacto y lo publicará en la rama gh-pages del repositorio en el que estamos trabajando.

Pipeline

Dentro del Team Project, en el menú seleccionamos el ítem Pipelines.

Pipeline

Creamos un nuevo pipeline y elegimos como origen GitHub.

Connect Pipeline

Seleccionamos el repositorio que queremos publicar como sitio estático.

Select Pipeline

Al escoger el repositorio, deberemos configurar en GitHub el acceso que va a tener Azure Pipelines sobre nuestro repositorio. Tenemos dos opciones, dejar que tenga acceso a todos los repositorios, o dejar que sólo tenga acceso a los repositorios que seleccionemos.

Setup Azure Pipelines

Tras aprobar el acceso al repositorio, volvemos al pipeline, y lo configuramos para que utilice Node.js.

Configure Pipeline

En el último paso nos encontramos con un fichero YAML, con el nombre preestablecido de azure-pipelines.yml y que se almacenará en el repositorio de GitHub.

Este fichero, viene por defecto con un trigger que se desencadenará cuando se consoliden cambios en master, además realiza la instalación de Node.js, ejecuta la instalación de los paquetes npm y la compilación de la solución.

# Node.js
# Build a general Node.js project with npm.
# Add steps that analyze code, save build artifacts, deploy, and more:
# https://docs.microsoft.com/azure/devops/pipelines/languages/javascript

trigger:
- master

pool:
  vmImage: 'ubuntu-latest'

steps:
- task: NodeTool@0
  inputs:
    versionSpec: '10.x'
  displayName: 'Install Node.js'

- script: |
    npm install
    npm run build
  displayName: 'npm install and build'

Actualizamos el código YAML que viene por defecto, modificando los pasos de la operativa para que instale el Gatsby-CLI, y con yarn instale las dependencias y haga la build de la solución.

# Build a GatsbyJS solution with npm and yarn.

trigger:
- master

pool:
  vmImage: 'ubuntu-latest'

steps:
- task: NodeTool@0
  inputs:
    versionSpec: '10.x'
  displayName: 'Install Node.js'

- script: |
    npm install -g gatsby-cli
  displayName: 'Install Gatsby-CLI'

- script: |
    yarn install
  displayName: 'Install dependencies'

- script: |
    yarn build
  displayName: 'Build'

En el lateral derecho, tenemos la posibilidad de utilizar el asistente, el cual nos permitirá cargar nuevos pasos dentro del YAML para completar el pipeline.

Pipeline Assistant

Agregamos dos pasos nuevos, el primero realizará la copia de los ficheros generados en la build. El segundo paso la publicación del resultado como artefacto.

Para la copia de los ficheros, agregamos la tarea de copia e indicamos que debe copiar los ficheros que se generan en la carpeta public al Build Artifact Staging Directory.

- task: CopyFiles@2
  inputs:
    sourceFolder: "public"
    contents: "**"
    targetFolder: "$(Build.ArtifactStagingDirectory)"
    cleanTargetFolder: true
  displayName: "Copy built site"
  condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))

Tras la copia de ficheros, publicamos el resultado en el Staging Artifact Directory.

- task: PublishBuildArtifacts@1
  inputs:
    PathtoPublish: "$(Build.ArtifactStagingDirectory)"
    ArtifactName: "drop"
    publishLocation: "Container"
  condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
  displayName: "Publish Build Artifacts"

Al finalizar las modificaciones, salvamos, establecemos el mensaje de commit y automáticamente se lanzará un pipeline que generará los ficheros estáticos necesarios para un sitio web de GitHub Pages.

Pipeline Saven and run

Una vez lanzado el pipeline, vemos el estado de la ejecución, y tenemos la posibilidad de ver los cambios o cancelar el propio pipeline.

Pipeline Run

Si pulsamos en el Job, podemos acceder al estado de la ejecución del pipeline y ver cómo va avanzando.

Pipeline Log

Tras ejecutarse el pipeline, si no ha habido ningún error tendremos un tick verde en el resultado del Job, e internamente, en los logs, todas las operaciones estarán Ok y habrá un artefacto generado.

Pipeline Log

Release

Accedemos al ítem Release, dentro del menú Pipelines.

Release Menu

Creamos una nueva Release Pipeline.

New Release Pipeline

En pantalla se nos mostrará un workflow para configurar nuestro Release Pipeline, por defecto Azure DevOps nos ofrece plantillas predefinidas con diversa funcionalidad para facilitar esta tarea. En nuestro caso, seleccionamos una plantilla vacía.

Select Template

Establecemos un nombre al Stage, y vamos al bloque Artifacts, dónde configuraremos el artefacto resultante de la pipeline que hemos creado en el punto anterior.

Select Artifact

Después de agregarlo, configuramos el trigger que desencadenará la Release Pipeline, pulsando en el símbolo del rayo del artefacto e indicamos la entrega continua con cada build que se produzca.

Continuous deployment trigger

En el bloque de Stages, accedemos al Stage que tenemos y pulsamos sobre el resumen de 1 job, 0 task.

Tasks Stage

En el job del agente agregamos una nueva tarea del tipo Publish to GitHub Pages y configuramos la tarea.

Task Configuration

En primer lugar debemos establecer el origen de los documentos, en el apartado Documentation Source, examinamos y establecemos el resultado del artefacto

Task Configuration Source

Una vez seleccionado el directorio, agregamos el wildcard /** para que publique el contenido de la carpeta del artefacto y no la carpeta en sí, así evitaremos que la publicación agregue a nuestro sitio un subdirectorio con el nombre del drop.

A continuación completamos el resto de campos requeridos con las siguientes variables:

Name Value
Documentation Source $(System.DefaultWorkingDirectory)/DemoGatsbyJS/drop/**
GitHub Username $(UserName)
GitHub Email Address $(UserEmail)
GitHub Personal Access Token $(PAT)
Repository Name $(Repository)
Branch Name gh-pages
Commit Message Azure DevOps: Automated Release $(Release.ReleaseId)

Task Configuration

En la pestaña de Variables, agregamos las variables que estamos utilizando en la tarea, y el PAT lo marcamos como variable de tipo Secret.

Task Variables

Establecemos un nombre al Release Pipeline, pinchando sobre el nombre actual, guardamos y pulsamos en Create release.

Create Release

Accedemos a la Release creada, y una vez completado el proceso, si todo ha ido Ok, se mostrará un Succeeded en el Stage.

Release Completed

Si vamos al resultado del Stage, podemos ver que, como con las Pipeline, se puede visualizar los logs de lo que ha sucedido durante el proceso.

Release Log

Finalmente en el navegador, si entramos al sitio estático de GitHub Pages, visualizaremos algo como esto.

GitHub Pages

Buy Me A Coffee