Drop the pull_request trigger (the branch push already validates the commit), drop the second npm run build from the lint job (the image build compiles it), and build the image on arm64 after the cheap checks pass. The CI publishes it as inputs-<hash>, so the merge to main only re-tags it. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
127 lines
5.0 KiB
YAML
127 lines
5.0 KiB
YAML
name: Release
|
|
|
|
# Publica a imagem no registro de containers do Gitea depois de um merge em main,
|
|
# e de novo com tag semver quando uma tag v* é enviada. O servidor só faz pull.
|
|
# Precisa do secret de usuário REGISTRY_TOKEN (token do Gitea com write:package).
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
tags: ['v*']
|
|
workflow_dispatch:
|
|
|
|
concurrency:
|
|
group: release
|
|
cancel-in-progress: false
|
|
|
|
env:
|
|
REGISTRY: git.lucasrguerra.dev.br
|
|
|
|
jobs:
|
|
# A imagem só depende dos arquivos que entram no build, não da documentação nem
|
|
# da configuração de ferramentas. O push da branch já a construiu, testou e
|
|
# publicou como inputs-<hash>; quando essa tag existe (o caso normal de um
|
|
# merge, uma tag num commit validado, um merge só de docs), 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
|
|
run: scripts/plano-imagem.sh "$REGISTRY" "${{ gitea.repository }}" >> "$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: [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
|
|
|
|
# Se o ci chamado acima acabou de publicar a imagem (push direto na main),
|
|
# o plano lá de cima está desatualizado: confere de novo antes de construir.
|
|
- id: replano
|
|
run: scripts/plano-imagem.sh "$REGISTRY" "${{ gitea.repository }}" >> "$GITHUB_OUTPUT"
|
|
|
|
- uses: docker/setup-buildx-action@v4
|
|
|
|
- name: Autentica no registro
|
|
uses: docker/login-action@v4
|
|
with:
|
|
registry: ${{ env.REGISTRY }}
|
|
username: ${{ gitea.actor }}
|
|
password: ${{ secrets.REGISTRY_TOKEN }}
|
|
|
|
- name: Metadados
|
|
id: meta
|
|
uses: docker/metadata-action@v6
|
|
with:
|
|
images: ${{ needs.plano.outputs.image }}
|
|
tags: |
|
|
type=semver,pattern={{version}}
|
|
type=semver,pattern={{major}}.{{minor}}
|
|
type=raw,value=latest
|
|
type=sha,format=long
|
|
|
|
- name: Build e push
|
|
if: ${{ steps.replano.outputs.reuse != 'true' }}
|
|
uses: docker/build-push-action@v7
|
|
with:
|
|
context: .
|
|
platforms: linux/arm64
|
|
push: true
|
|
tags: |
|
|
${{ steps.meta.outputs.tags }}
|
|
${{ needs.plano.outputs.image }}:inputs-${{ needs.plano.outputs.inputs }}
|
|
labels: ${{ steps.meta.outputs.labels }}
|
|
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: ${{ steps.replano.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 }}"
|
|
|
|
# Cria a entrada em "Releases" quando a execução é de uma tag v*. Roda depois
|
|
# de publicar a imagem, com as notas da seção do CHANGELOG.md.
|
|
release:
|
|
name: Cria a release no Gitea
|
|
needs: [plano, publicar]
|
|
# Explícito, como o publicar: o ci acima é pulado quando a imagem é
|
|
# reaproveitada, e o success() implícito pularia este job também.
|
|
if: ${{ !cancelled() && needs.publicar.result == 'success' && startsWith(gitea.ref, 'refs/tags/v') }}
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
with:
|
|
fetch-depth: 0
|
|
- name: Release
|
|
env:
|
|
TAG: ${{ gitea.ref_name }}
|
|
TOKEN: ${{ gitea.token }}
|
|
API: ${{ gitea.server_url }}/api/v1/repos/${{ gitea.repository }}
|
|
IMAGE: ${{ needs.plano.outputs.image }}
|
|
run: |
|
|
scripts/release-notes.sh "$TAG" "$IMAGE" > notes.md
|
|
pre=false; case "$TAG" in *-*) pre=true ;; esac
|
|
jq -n --arg tag "$TAG" --arg name "ESPDocs ${TAG#v}" --rawfile body notes.md --argjson pre "$pre" \
|
|
'{tag_name:$tag, name:$name, body:$body, prerelease:$pre}' > release.json
|
|
curl -fsS -X POST "$API/releases" -H "Authorization: token $TOKEN" \
|
|
-H 'Content-Type: application/json' -d @release.json
|