Integração Contínua (CI/CD)
Como funcionam os pipelines no GitLab para lint, testes, build, release, imagens e documentação.
Integração Contínua (CI/CD)
Este guia explica o pipeline do GitLab: lint → test → build → release → image_create → create-pages. Também lista as variáveis necessárias e como acionar cada etapa.
1) Estrutura geral do pipeline
cache:
paths:
- node_modules
stages:
- lint
- test
- build
- release
- image_create
- create-pages
lint-job:
image: $CI_REGISTRY/ademir/node-custom:latest
stage: lint
script:
- ln -s /ci-modules/backend_node_modules backend/node_modules
- cd backend
- pnpm lint
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
test-job:
image: $CI_REGISTRY/ademir/node-custom:latest
stage: test
script:
- ln -s /ci-modules/backend_node_modules backend/node_modules
- cd backend
- pnpm exec tsc && pnpm exec jest --ci --forceExit --detectOpenHandles --runInBand --silent --verbose=false
variables:
NODE_ENV: testing
DB_SGBD: ${DB_SGBD}
DB_USER: ${DB_USER}
DB_PASSWORD: ${DB_PASSWORD}
DB_HOST: ${DB_HOST}
DB_PORT: ${DB_PORT}
DB_NAME: ${DB_NAME}
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
build-job:
image: $CI_REGISTRY/ademir/node-custom:latest
stage: build
script:
- ln -s /ci-modules/frontend_node_modules frontend/node_modules
- cd frontend
- pnpm run build
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
create_release:
stage: release
image: $CI_REGISTRY/ademir/release-cli
script:
- |
LAST_TAG=$(git tag --sort=-creatordate | sed -n 2p)
if [ -z "$LAST_TAG" ]; then
git log --pretty=format:"%s (%an)" | grep -v "^Merge branch" | sed 's/^/- /' > release_notes.md
else
git log "${LAST_TAG}"..HEAD --pretty=format:"%s (%an)" | grep -v "^Merge branch" | sed 's/^/- /' > release_notes.md
fi
echo "Versão: $CI_COMMIT_TAG" > full_release.md
echo "" >> full_release.md
echo "Mudanças:" >> full_release.md
cat release_notes.md >> full_release.md
release:
tag_name: $CI_COMMIT_TAG
name: "Release $CI_COMMIT_TAG"
description: full_release.md
rules:
- if: '$CI_COMMIT_TAG'
image_create:
stage: image_create
image:
name: $CI_REGISTRY/ademir/buildah
script:
- buildah login -u "$HARBOR_LOGIN" -p "$HARBOR_PASSWORD" "$CI_REGISTRY"
- buildah build --layers --build-arg NEXT_PUBLIC_API_BASE_URL="$NEXT_PUBLIC_API_BASE_URL" --file frontend/Containerfile --tag $CI_REGISTRY/ademir/frontend:$CI_COMMIT_TAG --cache-from=$CI_REGISTRY/ademir/frontend --cache-to=$CI_REGISTRY/ademir/frontend frontend
- buildah push harbor.c3sl.ufpr.br/ademir/frontend:$CI_COMMIT_TAG
- buildah build --layers --file backend/Containerfile --tag harbor.c3sl.ufpr.br/ademir/backend:$CI_COMMIT_TAG --cache-from=$CI_REGISTRY/ademir/backend --cache-to=$CI_REGISTRY/ademir/backend backend
- buildah push harbor.c3sl.ufpr.br/ademir/backend:$CI_COMMIT_TAG
rules:
- if: '$CI_COMMIT_TAG'
# deploy (k8s) — desativado
#deploy:
# stage: deploy
# image: bitnami/kubectl:latest
# script:
# - kubectl --kubeconfig $KUBECONFIG rollout restart deploy ademir -n ademir
# rules:
# - if: '$CI_COMMIT_TAG'
create-pages:
image: hugomods/hugo:ci
variables:
GIT_SUBMODULE_STRATEGY: recursive
before_script:
- cd docs
- npm i -D postcss postcss-cli autoprefixer
script:
- hugo --minify -D -d public
- mv public ..
pages: true
artifacts:
paths:
- public
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
changes:
- docs/**/*
environment: production
Observação: os blocos estão sem linguagem para manter compatibilidade com a diretriz de apenas blocos de código Markdown.
2) Quando cada estágio roda
- lint, test, build → executam em Merge Requests (
rules: if: $CI_PIPELINE_SOURCE == "merge_request_event"). - release e image_create → executam somente em tag (
rules: if: $CI_COMMIT_TAG). - create-pages (Hugo) → executa na branch padrão (ex.:
develop) quando houver mudanças emdocs/.
Disparo prático
- Abrir MR → roda lint, test, build.
- Criar tag (ex.:
v1.2.3) → roda create_release e image_create (gera release e imagens e faz push no registry). - Commits em
docs/na branch padrão → roda create-pages e publica a documentação.
3) Variáveis de ambiente (CI/CD) necessárias
Crie/atualize em Settings → CI/CD → Variables no GitLab:
Backend / Testes
DB_SGBDDB_USERDB_PASSWORDDB_HOSTDB_PORTDB_NAME
Release / Imagens
HARBOR_LOGIN— login no registryHARBOR_PASSWORD— senha/token do registryNEXT_PUBLIC_API_BASE_URL— base URL injetada no build do frontend- (opcional)
CI_REGISTRY,CI_REGISTRY_USER,CI_REGISTRY_PASSWORDse o runner exigir login explícito
Outras
CI_DEFAULT_BRANCH(já fornecida pelo GitLab)KUBECONFIG(se reativar o job de deploy)
Boas práticas: marque variáveis sensíveis como masked e protected; ligue Protect para usar apenas em branches/tags protegidas.
4) Detalhes de cada job
lint-job
- Usa imagem Node custom.
- Cria symlink para
backend/node_modulesapontando para/ci-modules/backend_node_modules(cache aquecido da imagem). - Roda
pnpm lintno diretóriobackend.
test-job
- Mesmo setup de node_modules do
lint-job. - Compila TypeScript (
pnpm exec tsc) e executa testes com Jest/Supertest. - Injeta variáveis de banco para testes.
build-job
- Prepara
frontend/node_modulesvia symlink. - Executa
pnpm run buildemfrontend(Next.js + Tailwind + shadcn).
create_release
- Gera release notes a partir do
git log(desde a última tag) e cria um Release associado à tag atual ($CI_COMMIT_TAG).
image_create
- Autentica no registry (
buildah login). - Frontend: build da imagem passando
NEXT_PUBLIC_API_BASE_URLpor--build-arg; faz push paraharbor.c3sl.ufpr.br/ademir/frontend:$CI_COMMIT_TAG. - Backend: build e push da imagem
harbor.c3sl.ufpr.br/ademir/backend:$CI_COMMIT_TAG. - Usa camadas em cache (
--layers,--cache-from/--cache-to).
create-pages
- Usa imagem do Hugo.
- Instala
postcss,postcss-clieautoprefixerpara o tema. - Gera site (
hugo --minify -D) e publica artefatos para Pages.
5) Fluxos típicos
A) Verificação de MR
- Abrir MR → pipeline executa lint, test, build.
- Corrigir problemas (se houver) → push para a mesma branch reexecuta as etapas.
B) Criar release e imagens
- Marcar uma tag (ex.:
v1.2.3). - Pipeline executa
create_releaseeimage_create. - Conferir release no GitLab e imagens no registry Harbor.
C) Publicar documentação
- Subir commits na branch padrão alterando
docs/. - Pipeline executa
create-pagese publica o site (GitLab Pages).
6) Troubleshooting
- lint/test falhando: rode localmente
pnpm lintepnpm exec jestno diretório correspondente e verifique versões do Node. - Falha no build do frontend: cheque dependências (
pnpm install) e teste pnpm build localmente. - Erro no
image_create: valideHARBOR_LOGIN/HARBOR_PASSWORDe permissão de push no registry. Confirme o nome das imagens e tags. create-pagesnão dispara: confirme a branch padrão e se houve mudanças dentro dedocs/.- Variáveis ausentes: adicione em CI/CD Variables (acessível apenas pra mantainers) e proteja-as quando necessário.
7) Boas práticas
- Mantenha o pipeline rápido (cache eficiente, jobs paralelos quando possível).
- Use tags semânticas (ex.:
vX.Y.Z) para releases. - Centralize secrets apenas no CI/CD; não versionar
.envreais.