From 5b72ffaa7313d041fe095a84b3856c2860ef82b5 Mon Sep 17 00:00:00 2001 From: TomD4vs Date: Tue, 28 Jul 2026 15:37:47 -0400 Subject: [PATCH 1/2] feat: pipeline de CD publicando a imagem no ghcr --- .github/workflows/ci.yml | 102 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 101 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5bb773e..4f8d377 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: CI +name: CI/CD on: push: @@ -6,7 +6,10 @@ on: jobs: build-and-test: + name: CI - build e testes runs-on: ubuntu-latest + permissions: + contents: read steps: - name: Checkout do código @@ -54,3 +57,100 @@ jobs: - name: Derrubar a stack if: always() run: docker compose down -v + + publish: + name: CD - publicar imagem no GHCR + runs-on: ubuntu-latest + needs: build-and-test + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + permissions: + contents: read + packages: write + + steps: + - name: Checkout do código + uses: actions/checkout@v4 + + - name: Definir o nome da imagem em minúsculas + id: img + run: echo "name=ghcr.io/${GITHUB_REPOSITORY,,}" >> "$GITHUB_OUTPUT" + + - name: Configurar o Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login no GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Montar as tags e labels da imagem + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ steps.img.outputs.name }} + tags: | + type=raw,value=latest + type=sha,format=short + + - name: Build e push da imagem + id: build + uses: docker/build-push-action@v6 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + + - name: Smoke test da imagem que acabou de ser publicada + env: + IMAGE: ${{ steps.img.outputs.name }} + DIGEST: ${{ steps.build.outputs.digest }} + run: | + echo "Baixando $IMAGE@$DIGEST do registry..." + docker run -d --name deploy-check -p 3000:3000 "$IMAGE@$DIGEST" + for i in $(seq 1 20); do + if curl -sf http://localhost:3000/items > /dev/null; then + echo "A imagem publicada subiu e respondeu OK" + docker rm -f deploy-check + exit 0 + fi + echo "tentativa $i..." + sleep 3 + done + echo "A imagem publicada nao respondeu a tempo" + docker logs deploy-check + docker rm -f deploy-check + exit 1 + + - name: Resumo da entrega + if: success() + env: + IMAGE: ${{ steps.img.outputs.name }} + DIGEST: ${{ steps.build.outputs.digest }} + TAGS: ${{ steps.meta.outputs.tags }} + run: | + { + echo "### Imagem publicada no GHCR" + echo "" + echo "| campo | valor |" + echo "| --- | --- |" + echo "| imagem | \`$IMAGE\` |" + echo "| digest | \`$DIGEST\` |" + echo "| commit | \`$GITHUB_SHA\` |" + echo "" + echo "Tags publicadas:" + echo "" + echo '```' + echo "$TAGS" + echo '```' + echo "" + echo "Para rodar localmente:" + echo "" + echo '```bash' + echo "docker run -d -p 3000:3000 $IMAGE:latest" + echo '```' + } >> "$GITHUB_STEP_SUMMARY" From 323f37311cb2f23c50efd5c33aad9fe9c4362343 Mon Sep 17 00:00:00 2001 From: TomD4vs Date: Tue, 28 Jul 2026 15:44:27 -0400 Subject: [PATCH 2/2] docs: secao de entrega continua (CD) --- README.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/README.md b/README.md index 006af34..e72d5d8 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,38 @@ Porque o Docker tem um DNS interno na rede todo-net que resolve o nome do servi ![ci log](docs/imagens/10.1-ci-log.png) +## 7.1 Entrega Contínua (CD) — extra + +**Arquivo do workflow:** `.github/workflows/ci.yml`, job `publish` **Gatilho:** push na branch `main`, e somente se o job de CI (`build-and-test`) tiver passado — `needs: build-and-test` **Destino:** GitHub Container Registry (`ghcr.io/tomd4vs/project-docker`) + +**O que o pipeline de CD faz:** + +1. Autentica no `ghcr.io` usando o `GITHUB_TOKEN` do próprio repositório (nenhum secret manual) +2. Gera as tags da imagem: `latest` e `sha-`, para rastrear qual commit gerou qual imagem +3. Builda e faz push da imagem para o registry, com cache de layers entre execuções +4. Baixa de volta do registry a imagem recém-publicada e sobe ela — se não responder no `/items`, o deploy falha +5. Publica um resumo da entrega com o digest da imagem + +**Por que o CD só roda na main e depois do CI?** O `needs: build-and-test` transforma o CI em portão: enquanto os testes não passam, o job de publicação nem começa, então imagem quebrada nunca chega ao registry. O `if: github.ref == 'refs/heads/main'` garante que branches de trabalho e Pull Requests rodem só a validação, sem publicar nada — foi exatamente o caso do PR da seção 7. + +**Diferença entre CI e CD aqui:** o CI valida o código num ambiente descartável e joga tudo fora no final (`docker compose down -v`). O CD pega o mesmo código já aprovado, empacota num artefato versionado e imutável (imagem identificada por digest) e entrega esse artefato num registry, de onde qualquer ambiente pode consumir. + +**Print 11 — pipeline completo: CI verde seguido do CD** + + + +**Print 11.1 — log do job de publicação + resumo com o digest** + + + +**Print 11.2 — imagem publicada no GHCR com as tags** + + + +**Print 11.3 — `docker pull` + `docker run` da imagem publicada, rodando na máquina local** + + + ## 8. Dificuldades e aprendizados Minha principal dificuldade foi na primeira configuração do ambiente, pois não tinha trabalhado com a ferramenta. Repeti o processo em outros dois computadores, ganhei prática e, na terceira vez, consegui instalar as ferramentas de forma simples e prática. O aprendizado foi ótimo: já apliquei parte do que vi em projetos em que estou trabalhando e ainda aproveitei as dicas do professor sobre instalação e configurações para Ubuntu Server. @@ -140,3 +172,4 @@ Minha principal dificuldade foi na primeira configuração do ambiente, pois nã - [x] CI verde - [x] PR com CI vermelho documentado - [x] Todos os 9 prints no README +- [ ] CD publicando a imagem no registry (extra)