CHANGELOG.md in Portuguese, from the project history. The release job builds its notes from the matching section. The new files are excluded from the image hash, so the published image is reused. README points at the Gitea repository. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
138 lines
5.7 KiB
YAML
138 lines
5.7 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. 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|CHANGELOG\.md|scripts\/release-notes\.sh)$/' \
|
|
| 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: [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
|
|
|
|
- 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: ${{ needs.plano.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: ${{ 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 }}"
|
|
|
|
# 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
|