ci: reuse the published image when its sources are unchanged
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:
1 parent
a5c587155b
commit
111a81776c
2 files changed
+60
-13
No files matched your search
@@ -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 }}"
|
||||
Reference in new issue
Block a user