Skip to main content

Build

A primeira coisa que precisamos é executar o build do nosso projeto e para isso vamos utilizar stages para dividir as etapas. Vale lembrar que a ordem dos stages importam.

Para fazer o build vamos precisar instalar as dependências, assim como fizemos para rodar o projeto, ou seja, tudo na mesma sequência, como se fosse rodar o projeto localmente.

Existem dois métodos de fazer a instalação das dependências.

  • npm install: irá instalar as dependências de acordo com o que esta no em packages.json
  • npm ci: instala as dependências utilizando o arquivo package-lock.json sem fazer nenhuma alteração respeitando exatamente as versões definidas e garante que tenhamos uma compilação replicável. Além disso utilizar o npm ci é mais rápido do que o npm install

No nosso cenário como é um projeto pequeno qualquer coisa funcionaria, mas é bom conhecer as melhores práticas. Então vamos utilizar o npm ci.

default:
tags:
- general

stages:
- build

build:
image: node:22-slim
script:
- node --version
- npm --version
# - npm install # Instalação das dependências
- npm ci # Instalação das dependências irá gerar a pasta node_modules
- npm run build # Irá gerar a pasta build

As pastas que irão ser geradas se perderam ao fim do job, então precisamos salvar o que nos insteressa para uso futuro, por exemplo criar uma imagem docker ou qualquer outra coisa.

A única pasta que iremos utilizar é a pasta build gerada no projeto. A pasta node_modules para esse cenário não é importante.

Artifacts Advanced

Vamos nos aprofundar um pouco mais em artifacts agora antes de continuar. Se não passamos o nome do artefato gerado por esse job ele irá receber o nome default.

  • Podemos passar um arquivo específico ou até mesmo pastas inteiras utilizando paths e podemos utilizar wildcardas para filtrar o que vamos passar.

    ...
    artifacts:
    name: "job1-artifacts-file"
    paths:
    - build/ # pasta toda
    - arquivo # um arquivo específico
    - teste/*xyz/* # tudo dentro da pasta teste, porém só as pastas que terminam com xyz
  • Mas nem sempre queremos passar tudo que esta em uma pasta e não precisamos passar caminho por caminho. Se tem algo expecífico que queremos excluir é possível usando o exclude.

...
artifacts:
paths:
- binaries/ # Toda a pasta bináries
exclude:
- binaries/**/*.o # Mas arquivos terminados em .o não, em qualquer level, por causa do **
  • Podemos definir um tempo para que esse artefato seja eliminado utilizando o expire_in. Se não for definido, o tempo padrão é de 30 dias. Abaixo alguns exemplos com várias opções de como poder utilizar. Podemos usar só minutos se quisermos e colocar 720 minutos ao invés de 12 horas.

    expire_in: 1 week # singular
    expire_in: 2 weeks # plural
    expire_in: 5 days # plural
    expire_in: 1 day # singular
    expire_in: 7 hours # plural
    expire_in: 30 minutes
    expire_in: 1 week 2 hours
    expire_in: 1 day 1 hour 30 minutes # Dia e hora no singular para 1.
    expire_in: 1 month # singular
    expire_in: 2 months # plural
  • Não é possível limitar acesso a um usuário ou grupo desses artefatos. Essa é uma configuração em nível de repositório e não de pipeline.

    ...
    artifacts:
    name: "build-artifacts"
    paths:
    ...
    Valor de whenDescrição
    on_successGera artefatos apenas se o job for bem-sucedido (valor padrão).
    alwaysGera artefatos independentemente do sucesso ou falha do job.
    on_failureGera artefatos somente se o job falhar.
    manualGera artefatos somente quando o job for executado manualmente.
    • always: é Útil para gerar artefatos de diagnóstico (como logs) mesmo quando o job falha.
    • on_failure: Ideal para capturar artefatos que são úteis somente quando o job falha, como logs de erro ou relatórios de falha.

Artefacts Paths vs Artefact Reports

O reports no GitLab CI/CD é uma funcionalidade especial que permite associar artefatos a tipos específicos de relatórios para que o GitLab trate esses arquivos de uma maneira especial, oferecendo funcionalidades adicionais. Isso é particularmente útil quando você quer que o GitLab saiba que determinado artefato tem um significado específico, como relatórios de cobertura de testes, relatórios de segurança ou variáveis de ambiente, e quer que esses arquivos sejam processados e visualizados de uma maneira estruturada. Definimos esses tipos de coisas aqui

  artifacts:
when: on_success # Já é o padrão
expire_in: "1 hour"
paths:
...
reports: # Veremos mais pra frente.
...

A única coisa que eu acho que podemos injetar no nosso pipeline e explorar por agora são variáveis de ambiente que podemos (não precisamos), testar no futuro.

No meio da nossa pipeline vamos gerar uma variável de ambiente que depois será carregada em outro job e vamos testar.

Então para um ponto inicial acho que o pipeline de build podería ser assim.

default:
tags:
- general

stages:
- build

build:
image: node:22-slim
script:
- node --version
- npm --version
- npm ci # Instalação das dependências
- npm run build # Irá gerar a pasta .build
- echo "ACCESS_TOKEN=abc123" > test.env # Um teste somente para o reports
artifacts:
when: on_success # Já é o padrão
expire_in: "1 hour"
paths:
- build/ # A pasta toda sem exclusões
reports:
dotenv: test.env # Dentro dese arquivo temos ACCESS_TOKEN=abc123

Sobre o reports, não estamos carregando uma variável de ambiente neste job, mas futuros jobs que dependem destes artefatos devem vir com a variável ACCESS_TOKEN carregada no terminal. Falaremos mais sobre variáveis depois.

git checkout -b pipe/build  
git add .gitlab-ci.yml
git cm "add build"
git push origin pipe/build

alt text

Se temos um job e stages, o job precisa ter o seu stage definido.

default:
tags:
- general

stages:
- build

build:
stage: build #### <<<<<
image: node:22-slim
script:
- node --version
- npm --version
- npm ci # Instalação das dependências
- npm run build # Irá gerar a pasta .build
- echo "ACCESS_TOKEN=abc123" > .env # Um teste somente para o reports
artifacts:
when: on_success # Já é o padrão
expire_in: "1 hour"
paths:
- build/ # A pasta toda sem exclusões
reports:
dotenv: .env

Refazendo o commit.

git checkout -b pipe/build  
git add .gitlab-ci.yml
git cm "add build"
git push origin pipe/build

alt text

alt text

E aqui todo o processo do build.

Running with gitlab-runner 17.11.0 (0f67ff19)
on general-debian jyvyfkmfg, system ID: r_szdZCOX2meST
Preparing the "docker" executor
00:09
Using Docker executor with image node:22-slim ...
Using locally found image version due to "if-not-present" pull policy
Using docker image sha256:a7bca975c7f3a862dc60f3d8aaa3862fce3208066dd3567f060381b506f38402 for node:22-slim with digest node@sha256:157c7ea6f8c30b630d6f0d892c4f961eab9f878e88f43dd1c00514f95ceded8a ...
Preparing environment
00:01
Running on runner-jyvyfkmfg-project-69186599-concurrent-0 via 1d8224d47375...
Getting source from Git repository
00:02
Fetching changes with git depth set to 20...
Reinitialized existing Git repository in /builds/puziol/learn-gitlab-app/.git/
Created fresh repository.
Checking out 36c04930 as detached HEAD (ref is pipe/build)...
Skipping Git submodules setup
Executing "step_script" stage of the job script
00:14
Using docker image sha256:a7bca975c7f3a862dc60f3d8aaa3862fce3208066dd3567f060381b506f38402 for node:22-slim with digest node@sha256:157c7ea6f8c30b630d6f0d892c4f961eab9f878e88f43dd1c00514f95ceded8a ...
$ node --version # Os nosso primeiros comandos
v22.15.0
$ npm --version
10.9.2
$ npm ci # Instalação dos pacotes
added 440 packages, and audited 441 packages in 10s
152 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
$ npm run build
> [email protected] build
> vite build
vite v6.3.2 building for production...
transforming...
31 modules transformed.
rendering chunks...
computing gzip size... # Veja abaixo as pastas que foram geradas.
build/index.html 0.47 kB │ gzip: 0.30 kB
build/assets/react-CHdo91hT.svg 4.13 kB │ gzip: 2.05 kB
build/assets/index-n_ryQ3BS.css 1.39 kB │ gzip: 0.71 kB
build/assets/index-BcKvuBhg.js 147.40 kB │ gzip: 47.66 kB
✓ built in 1.47s
$ echo "ACCESS_TOKEN=abc123" > .env
Uploading artifacts for successful job
00:04
Uploading artifacts... # Upload do build
build/: found 7 matching artifact files and directories
Uploading artifacts as "archive" to coordinator... 201 Created id=9845340606 responseStatus=201 Created token=eyJraWQiO
Uploading artifacts... # Upload do do .env
.env: found 1 matching artifact files and directories
Uploading artifacts as "dotenv" to coordinator... 201 Created id=9845340606 responseStatus=201 Created token=eyJraWQiO
Cleaning up project directory and file based variables
00:01
Job succeeded

Quando fazemos o download lá na página do pipeline sempre receberemos um arquivo artifact.zip. Isso é por que não declaramos o nome do nosso artefato. Faremos isso mais tarde, quando entendermos de variáveis específicas do gitlab-ci.

  artifacts:
name: artifacts-[job_name]-[commit_sha] # esse seria um bom nome... mas ainda não sabemos como fazer isso, então espere as cenas dos próximo capítulos.

Vale a pena mensionar que vários pipelines podem estar em execução ao mesmo tempo nesse mesmo código e cada um tem seus artefatos específicos.