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/**', '.superpowers/**', '.wolf/**', 'docker-compose*.yaml', '.env.example', 'scripts/release-notes.sh'] schedule: - cron: '0 9 * * 1' # toda segunda: reavalia com a base de vulnerabilidades nova workflow_call: permissions: contents: read concurrency: group: ci-${{ gitea.ref }} cancel-in-progress: true jobs: # Trivy roda pela imagem oficial: o trivy-action clona o repositório do Trivy # do mesmo servidor do workflow, que aqui é o Gitea. O workspace do job não é # visível ao daemon, então os arquivos entram no container com `docker cp`. # O .trivyignore do repositório (DS-0002, documentado) é lido automaticamente. seguranca: name: Trivy (dependências, segredos e configuração) 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" imagem: name: Testes e imagem Docker (linux/arm64) needs: [seguranca] runs-on: ubuntu-24.04-arm timeout-minutes: 40 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" # Vitest dentro do estágio `test` do Dockerfile: ele compila o addon nativo do # LevelDB uma vez, e as camadas ficam no daemon do runner para o build abaixo. - name: Testes (Vitest) if: ${{ steps.plano.outputs.reuse != 'true' }} run: docker build --target test -t craftdock:test . - name: Build if: ${{ steps.plano.outputs.reuse != 'true' }} run: docker build -t craftdock: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 --ignore-unfixed --exit-code 1 craftdock:ci - name: A imagem sobe e responde if: ${{ steps.plano.outputs.reuse != 'true' }} run: scripts/smoke-imagem.sh craftdock:ci # O login fica por último: testes, build, Trivy e smoke não precisam de credencial. - if: ${{ steps.plano.outputs.reuse != 'true' }} uses: docker/login-action@v4 with: registry: ${{ env.REGISTRY }} username: ${{ gitea.actor }} password: ${{ secrets.REGISTRY_TOKEN }} # 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 craftdock:ci "$tag" docker push "$tag"