Skip to main content

Extends

Observando nuestro pipeline podemos ver que el build ni siquiera fue utilizado para hacer las pruebas que queremos. Cuanto antes detectemos el error, mejor. Estamos perdiendo tiempo con ese build previo. ¿Cómo podríamos mejorarlo? Vamos a crear un stage anterior llamado check, aunque también podríamos usar el predeterminado .pre.

before_script, script y after_script

El orden de ejecución en un job de GitLab CI es:

  1. before_script (global o del job)
  2. script
  3. after_script (si existe)

Después de esto, si el job tiene éxito, guarda los artifacts (si están definidos)

before_script y after_script pueden definirse, pero no es obligatorio. Si se define...

  • En default: → afecta a todos los jobs
  • O individualmente por job

Si el before_script falla, el script no se ejecuta, pero si el script falla el after_script todavía se ejecuta (para limpieza, logs, notificaciones, etc).

Sabiendo esto y con la información que tenemos ya podemos mejorar nuestro pipeline. Vamos a aplicar el concepto de extends y plantillas para simplificar.

default:
tags:
- general
# Los jobs ahora tendrán esta imagen por defecto eliminando una línea en cada uno
# También es una imagen más pequeña.
image: node:22-alpine

stages:
- check # Nuevo stage anterior
- build
- test # Está aquí pero no se usará, solo para mostrar que no bloquea el pipeline si un stage está definido pero no utilizado

.check: # Plantilla para stage check solo con lo que será estándar para todos
stage: check
before_script:
- npm ci
artifacts:
when: always
expire_in: "3 months"

unit-test:
extends: .check
script:
- npm test
artifacts: # Ahora solo ponemos los reports y eliminamos otras cosas
reports:
junit: reports/junit.xml

lint-test:
extends: .check
script:
- npm run lint
artifacts:
reports:
codequality: gl-codequality.json

vulnerability-test:
extends: .check
script:
- npm audit --audit-level=high --json > vulnerability-report.json
artifacts:
paths:
- vulnerability-report.json

build:
stage: build
script:
- node --version
- npm --version
- npm ci
- npm run build
artifacts:
when: on_success
expire_in: "1 hour"
paths:
- build/

Antes con la imagen slim teníamos este tiempo y esta secuencia.

alt text

Ahora tenemos estos tiempos y esta secuencia. Extends y plantillas solo mejoran la visibilidad del código, no el rendimiento. Lo que mejoró el tiempo fue la imagen más pequeña.

alt text

Un detalle importante. Extends en realidad es una lista. Podemos extender más de una plantilla como si fuera una combinación entre ellas.

jobx:
extends: [.check, .other]

Si .check y .other definen lo mismo, .other prevalecerá porque fue el último en escribir. Es una lista ordenada.

Ahora es el momento de definir cuándo se ejecutará este pipeline porque se está ejecutando siempre. Si una persona está desarrollando, el código aún no está terminado correctamente y necesita hacer un push a su rama, no necesitamos que el pipeline se ejecute. Vamos a iniciar este concepto, pero entenderemos mejor después sobre esto.

En uno de los jobs podemos tener una rule que definirá cuándo un job debe o no debe ejecutarse.

ej:

jobX:
...
script:
...
rules:
- if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main"'
when: always

Vamos a introducir sobre variables y rules enseguida. Esa variable CI_MERGE_REQUEST_TARGET_BRANCH_NAME es una variable de GitLab y existen varias. La regla anterior dice que el pipeline debe ejecutarse siempre cuando sea un merge request dirigido a main. Podríamos poner esto en todos nuestros jobs, pero vamos a aprovechar y hacer un extends de dos plantillas al mismo tiempo.

default:
tags:
- general
image: node:22-alpine

stages:
- check
- build

.check: # Plantilla para stage check
stage: check
before_script:
- npm ci
artifacts:
when: always
expire_in: "3 months"

.rules-only-main-mr: # Plantilla para rules general
rules:
- if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "main"'
when: always

unit-test:
extends: # Podemos definir así
- .check
- .rules-only-main-mr
script:
- npm test
artifacts:
reports:
junit: reports/junit.xml

lint-test:
extends: [.check,.rules-only-main-mr] # O así
script:
- npm run lint
artifacts:
reports:
codequality: gl-codequality.json

vulnerability-test:
extends: [.check,.rules-only-main-mr]
script:
- npm audit --audit-level=high --json > vulnerability-report.json
artifacts:
paths:
- vulnerability-report.json

build:
stage: build
extends: [.rules-only-main-mr] # O así, o como vimos antes en caso de un solo extends: .rules-only-main-mr
script:
- node --version
- npm --version
- npm ci
- npm run build
artifacts:
when: on_success
expire_in: "1 hour"
paths:
- build/

Ahora al subir este código no disparará el pipeline. Haz la prueba.

Sin embargo, al crear un merge request tendremos el pipeline disparado y si seguiste las recomendaciones solo si el pipeline pasa es que podremos hacer merge en main.

El resultado...

alt text