name: CI # Documentação e configuração de ferramenta não mudam nada que a suíte teste. # Na main não roda por push: o release.yml é quem a chama, e só quando a imagem # precisa ser reconstruída; rodar nos dois repetiria a mesma suíte no mesmo commit. # Sem gatilho de pull_request: o push da branch já valida o mesmo commit, e os # dois juntos rodariam tudo duas vezes (o repositório não recebe PR de fork). # # A imagem é construída aqui uma única vez, em arm64 (a arquitetura do servidor), # testada e publicada como inputs-. Ao fazer o merge, o release encontra # essa tag e só aplica os nomes novos, sem rodar nem construir nada de novo. on: push: branches-ignore: [main] paths-ignore: ['**.md', 'LICENSE', '.claude/**', '.superset/**', '.wolf/**', 'scripts/release-notes.sh'] workflow_call: permissions: contents: read concurrency: group: ci-${{ github.ref }} cancel-in-progress: true jobs: verificar: name: Lint e auditorias runs-on: ubuntu-latest timeout-minutes: 15 env: # O Puppeteer só é usado em scripts locais (slides, capturas); não precisa do Chrome na CI. PUPPETEER_SKIP_DOWNLOAD: "true" NEXT_TELEMETRY_DISABLED: "1" steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 22 cache: npm - run: npm ci # eslint + auditoria do design system (tokens, contraste AAA) + auditoria de páginas - run: npm run check # Trivy roda pela imagem oficial: o trivy-action clona o repositório do Trivy # do mesmo servidor do workflow, que aqui é o Gitea, e não o GitHub. # O workspace do job é um volume que o daemon não enxerga, então os arquivos # entram no container com `docker cp` em vez de `-v`. seguranca: name: Trivy (dependências e segredos) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Repositório run: | cid=$(docker create --network host -v trivy-cache:/root/.cache/ -w /src aquasec/trivy:0.70.0 \ fs --scanners vuln,secret,misconfig --severity HIGH,CRITICAL --exit-code 1 .) docker cp . "$cid:/src" docker start -a "$cid" status=$(docker inspect -f '{{.State.ExitCode}}' "$cid") docker rm "$cid" >/dev/null exit "$status" # Só começa depois das verificações baratas: um lint quebrado não gasta um # build de imagem. Roda no runner arm64, o mesmo tipo do servidor, então o # que é escaneado e testado é a imagem que vai ao ar. imagem: name: Imagem Docker (linux/arm64) needs: [verificar, seguranca] runs-on: ubuntu-24.04-arm env: REGISTRY: git.lucasrguerra.dev.br steps: - uses: actions/checkout@v4 # Conteúdo já publicado (re-push, tag num commit já validado): nada a fazer. - id: plano run: scripts/plano-imagem.sh "$REGISTRY" "${{ gitea.repository }}" >> "$GITHUB_OUTPUT" - if: ${{ steps.plano.outputs.reuse != 'true' }} uses: docker/login-action@v4 with: registry: ${{ env.REGISTRY }} username: ${{ gitea.actor }} password: ${{ secrets.REGISTRY_TOKEN }} # `docker build` simples, no daemon persistente do runner: as camadas e os # cache mounts do Dockerfile (npm e compilação do Next) sobrevivem entre # execuções. Um buildx criaria um BuildKit novo, e vazio, a cada job. - name: Build if: ${{ steps.plano.outputs.reuse != 'true' }} run: docker build -t espdocs:ci . - name: Trivy na imagem if: ${{ steps.plano.outputs.reuse != 'true' }} run: | docker run --rm --network host -v trivy-cache:/root/.cache/ -e DOCKER_HOST=tcp://127.0.0.1:2375 aquasec/trivy:0.70.0 \ image --severity HIGH,CRITICAL --exit-code 1 espdocs:ci - name: A imagem sobe e responde if: ${{ steps.plano.outputs.reuse != 'true' }} run: | docker run -d --name espdocs-ci --network host -e PORT=3999 espdocs:ci for i in $(seq 1 30); do curl -fsS http://127.0.0.1:3999/ >/dev/null && ok=1 && break sleep 2 done docker logs espdocs-ci | tail -5 docker rm -f espdocs-ci >/dev/null test "${ok:-0}" = 1 # Passou em tudo: publica a mesma imagem que foi testada, sem reconstruir. - name: Publica inputs- if: ${{ steps.plano.outputs.reuse != 'true' }} run: | tag="${{ steps.plano.outputs.image }}:inputs-${{ steps.plano.outputs.inputs }}" docker tag espdocs:ci "$tag" docker push "$tag"