From ebd39a8a0a671226d6ca823e262734acb32d09d2 Mon Sep 17 00:00:00 2001 From: Hirley Date: Sat, 29 Aug 2026 15:33:06 -0300 Subject: [PATCH] Desliga o latest=auto do metadata-action MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit O #73 fechou só metade do problema. A regra type=raw do "latest" passou a avaliar enable=false corretamente em push de tag — dá pra ver no log do build da v2.0.1 — e mesmo assim o "latest" continuou sendo publicado. A segunda fonte é o flavor, cujo default é "latest=auto": ele acrescenta a tag sozinho para toda tag semver, por fora das regras de `tags:`. No mesmo log, logo abaixo da regra desligada, aparece "Processing flavor input / latest=auto". Com flavor: latest=false, a única coisa capaz de gerar "latest" passa a ser a regra explícita, que só vale no default branch. Nem a v2.0.0 nem a v2.0.1 sofreram dano: as duas foram marcadas no topo da main, então o "latest" foi reescrito apontando para o mesmo commit. O risco é marcar um commit antigo, que faria o "latest" regredir em silêncio. Comentário e README corrigidos para descrever as duas portas, e não só a primeira — a incompletude anterior é justamente o que fez o conserto parecer pronto. Co-Authored-By: Claude Opus 5 --- .github/workflows/ci.yml | 32 ++++++++++++++++++++++++-------- README.md | 7 ++++++- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2c92bc4..4a985b0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -118,14 +118,20 @@ jobs: # * "latest" — só no topo da main. É uma tag que se move, então # serve pra "me dá a última", nunca pra fixar uma versão. # - # A condição é uma comparação explícita de ref, e não o - # {{is_default_branch}} do metadata-action, porque essa expressão - # também vale TRUE em push de tag (o próprio README da action diz - # que "Git tag is also considered as default branch"). O build da - # v2.0.0 reescreveu o "latest" por causa disso. Não deu problema - # ali, porque a tag saiu do topo da main — mas marcar um commit - # antigo faria o "latest" regredir para uma imagem velha, que é - # exatamente o que não se quer; + # Manter o "latest" fora dos builds de tag exigiu fechar DUAS + # portas, e a segunda só apareceu depois que a primeira foi + # fechada e o "latest" continuou saindo: + # + # 1. a condição desta regra é uma comparação explícita de ref, + # e não o {{is_default_branch}} do metadata-action — essa + # expressão também vale TRUE em push de tag (o README da + # action diz que "Git tag is also considered as default + # branch"); + # 2. o `flavor: latest=false` acima, porque o default + # "latest=auto" acrescenta a tag por fora destas regras. + # + # Marcar um commit antigo com as duas portas abertas faria o + # "latest" regredir para uma imagem velha, em silêncio; # * SHA completo — sempre, em qualquer disparo. É a única tag que # identifica exatamente um commit; # * semver — só em push de tag v*. "2.0.0" fixa a release; "2.0" @@ -138,6 +144,16 @@ jobs: uses: docker/metadata-action@v5 with: images: ghcr.io/${{ github.repository }} + # O default é "latest=auto", que acrescenta "latest" sozinho em + # toda tag semver — por FORA das regras de `tags:` abaixo. Foi o + # que reescreveu o "latest" nos builds da v2.0.0 e da v2.0.1, + # mesmo com a regra type=raw já avaliando enable=false na v2.0.1 + # (dá pra ver no log do job: "type=raw,value=latest,enable=false" + # e, logo abaixo, "Processing flavor input / latest=auto"). + # + # Com latest=false, a única coisa capaz de gerar "latest" passa a + # ser a regra explícita logo abaixo — que só vale no default branch. + flavor: latest=false tags: | type=raw,value=latest,enable=${{ github.ref == format('refs/heads/{0}', github.event.repository.default_branch) }} type=sha,format=long diff --git a/README.md b/README.md index cd86630..50c9d11 100644 --- a/README.md +++ b/README.md @@ -120,7 +120,12 @@ O build é validado automaticamente a cada push/PR pelo CI (ver seção "Integra | `2.0.0` | push de tag `v2.0.0` | fixar a release | | `2.0` | push de tag `v2.0.x` | acompanhar correções dentro do minor | - Build de tag **não** mexe no `latest` — publicar uma release não deve reescrever o que "a última" aponta. Isso exige uma comparação explícita de ref na condição do `latest`, e não o `{{is_default_branch}}` do `metadata-action`: essa expressão também vale `true` em push de tag, e foi assim que o build da v2.0.0 acabou reescrevendo o `latest`. Ali não houve dano, porque a tag saiu do topo da `main`, mas marcar um commit antigo faria o `latest` regredir. + Build de tag **não** mexe no `latest` — publicar uma release não deve reescrever o que "a última" aponta. Isso exigiu fechar duas portas no `metadata-action`, e a segunda só apareceu depois que a primeira foi fechada e o `latest` continuou saindo: + + 1. a condição da regra do `latest` compara o ref com o default branch explicitamente, em vez de usar `{{is_default_branch}}` — essa expressão também vale `true` em push de tag; + 2. `flavor: latest=false`, porque o default `latest=auto` acrescenta a tag por fora das regras de `tags:`, para toda tag semver. + + Os builds da v2.0.0 e da v2.0.1 reescreveram o `latest` por causa disso. Não houve dano em nenhum dos dois, porque as duas tags saíram do topo da `main` e o `latest` já apontava para aquele commit — mas marcar um commit antigo faria o `latest` regredir em silêncio. Também não é gerada tag só de major (`2`) de propósito — num projeto que ainda muda comportamento entre minors, uma tag tão larga prometeria mais estabilidade do que existe.