ci: reuse the published image when its sources are unchanged
Release / Plano (reaproveitar a imagem?) (push) Successful in 3s
Release / ci (push) Skipped
Release / Publica a imagem (linux/arm64) (push) Successful in 16s

The release workflow hashes everything that goes into the image build and skips
CI and the build when the registry already has an image for that hash, so a docs
or tooling change, or a version tag, only re-points the tags. ci.yml no longer
runs on main by push: release.yml calls it when a build is needed, and running
both repeated the same suite on the same commit.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Lucas RayanandClaude Sonnet 5.5 committed 2026-10-30 12:22:46 -03:00
1 parent a5c587155b
commit 111a81776c
2 files changed
+60 -13

No files matched your search

+6 -2
View File
@@ -1,10 +1,14 @@
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.
on:
pull_request:
paths-ignore: ['**.md', 'LICENSE', '.claude/**', '.superset/**']
push:
branches: [main]
# O release.yml roda esta mesma suíte antes de publicar a imagem.
branches-ignore: [main]
paths-ignore: ['**.md', 'LICENSE', '.claude/**', '.superset/**']
workflow_call:
permissions:
+54 -11
View File
@@ -17,24 +17,57 @@ env:
REGISTRY: git.lucasrguerra.dev.br
jobs:
# Nada é publicado sem a suíte completa passar antes.
# A imagem só depende dos arquivos que entram no build, não da documentação nem
# da configuração de ferramentas. Quando já existe no registro uma imagem para
# o mesmo conteúdo (um merge só de docs, uma mudança de workflow, uma tag num
# commit que acabou de ser publicado), não há o que construir: as tags novas
# apontam para o manifesto existente.
plano:
name: Plano (reaproveitar a imagem?)
runs-on: ubuntu-latest
outputs:
inputs: ${{ steps.plano.outputs.inputs }}
reuse: ${{ steps.plano.outputs.reuse }}
image: ${{ steps.plano.outputs.image }}
steps:
- uses: actions/checkout@v4
- id: plano
env:
REPO: ${{ gitea.repository }}
run: |
inputs=$(git ls-tree -r HEAD \
| awk -F'\t' '$2 !~ /^(\.gitea|\.github|\.claude|\.superset|docs)\// && $2 !~ /^(README.*|CLAUDE\.md|DESIGN\.md|LICENSE|\.gitignore)$/' \
| sha256sum | cut -c1-16)
ns="${REPO,,}"
token=$(curl -fsS "https://$REGISTRY/v2/token?service=container_registry&scope=repository:$ns:pull" | jq -r .token)
code=$(curl -s -o /dev/null -w '%{http_code}' -I \
-H "Authorization: Bearer $token" \
-H 'Accept: application/vnd.oci.image.index.v1+json,application/vnd.docker.distribution.manifest.list.v2+json,application/vnd.oci.image.manifest.v1+json' \
"https://$REGISTRY/v2/$ns/manifests/inputs-$inputs")
echo "inputs-$inputs -> HTTP $code"
reuse=false; [ "$code" = 200 ] && reuse=true
echo "inputs=$inputs" >> "$GITHUB_OUTPUT"
echo "reuse=$reuse" >> "$GITHUB_OUTPUT"
echo "image=$REGISTRY/$ns" >> "$GITHUB_OUTPUT"
# Nada é publicado sem a suíte completa passar antes. Pulada quando a imagem é
# reaproveitada: o mesmo conteúdo já passou por ela.
ci:
needs: plano
if: ${{ needs.plano.outputs.reuse != 'true' }}
uses: ./.gitea/workflows/ci.yml
publicar:
name: Publica a imagem (linux/arm64)
needs: ci
needs: [plano, ci]
# ci é pulado, e não bem-sucedido, quando a imagem é reaproveitada.
if: ${{ !cancelled() && needs.plano.result == 'success' && (needs.ci.result == 'success' || needs.plano.outputs.reuse == 'true') }}
# O único runner é arm64 e o servidor de destino (Oracle) também, então a
# imagem é construída nativamente, sem emulação.
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/checkout@v4
- id: nome
run: |
repo='${{ gitea.repository }}'
echo "image=${{ env.REGISTRY }}/${repo,,}" >> "$GITHUB_OUTPUT"
- uses: docker/setup-buildx-action@v4
- name: Autentica no registro
@@ -48,7 +81,7 @@ jobs:
id: meta
uses: docker/metadata-action@v6
with:
images: ${{ steps.nome.outputs.image }}
images: ${{ needs.plano.outputs.image }}
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
@@ -56,12 +89,22 @@ jobs:
type=sha,format=long
- name: Build e push
if: ${{ needs.plano.outputs.reuse != 'true' }}
uses: docker/build-push-action@v7
with:
context: .
platforms: linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
tags: |
${{ steps.meta.outputs.tags }}
${{ needs.plano.outputs.image }}:inputs-${{ needs.plano.outputs.inputs }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=registry,ref=${{ steps.nome.outputs.image }}:buildcache
cache-to: type=registry,ref=${{ steps.nome.outputs.image }}:buildcache,mode=max
cache-from: type=registry,ref=${{ needs.plano.outputs.image }}:buildcache
cache-to: type=registry,ref=${{ needs.plano.outputs.image }}:buildcache,mode=max
# Mesmo manifesto, nomes novos: nenhuma camada é lida nem escrita.
- name: Aplica as tags à imagem existente
if: ${{ needs.plano.outputs.reuse == 'true' }}
run: |
tags=$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< '${{ steps.meta.outputs.json }}')
docker buildx imagetools create $tags "${{ needs.plano.outputs.image }}:inputs-${{ needs.plano.outputs.inputs }}"