Release pipeline
Como o tempest-react-sdk é publicado no npm — workflow tag-push automático, com fallback manual.
Visão geral
Local: GitHub Actions:
make release TAG=X.Y.Z
│
▼
┌─────────────────────────┐
│ scripts/release.sh: │
│ 1. branch release/vTAG │
│ 2. npm version TAG │
│ 3. fecha o CHANGELOG │
│ ([Unreleased] → │
│ [TAG] — data) │
│ 4. validate (lint + │
│ format + typecheck │
│ + test + build) │
│ 5. commit + tag local │
│ 6. push branch + tag │──────────► tag push triggers
│ 7. abre PR via gh │ .github/workflows/release-npm.yml
└─────────────────────────┘ │
▼
┌────────────────────────────┐
│ 1. Checkout @ tag │
│ 2. tag == package.json? │
│ 3. Lint + format-check │
│ 4. Typecheck │
│ 5. Tests (vitest) │
│ 6. Build (vite + dts) │
│ 7. Smoke install │
│ 8. npm publish │
│ --provenance │
│ 9. read-back: registry │
│ serve a versão e o │
│ dist-tag latest bate? │
│ 10. GitHub Release da tag │
│ (notas = CHANGELOG, │
│ tarball anexado) │
└────────────────────────────┘
As três superfícies andam juntas: a git tag, a versão no npm e o GitHub
Release. O workflow falha se a tag não descrever a versão do package.json, e
falha se o registry não estiver servindo a versão como latest — então "workflow
verde" significa de fato "publicado e visível".
Tag push é a única forma de publicar. Não há "publish via PR merge" — o merge do release PR é apenas para sincronizar main com package.json + RELEASES.md atualizados.
Comandos
make release TAG=0.1.5
Pipeline completo. Requer working tree limpo + tag inexistente local/remoto.
Bloqueia se CHANGELOG.md não mencionar [TAG] ou [Unreleased] (com prompt para forçar continuação).
make release TAG=0.1.5 DRY_RUN=1
Idêntico, mas para antes do push — você inspeciona a branch e o tag locais antes de continuar manualmente:
git push -u origin release/v0.1.5
git push origin v0.1.5
gh pr create --base main --head release/v0.1.5 --title "chore: release v0.1.5"
make release TAG=0.1.5 SKIP_VALIDATE=1
Pula a validação local (npm ci, lint, format-check, typecheck, test, build, pack dry-run). Use apenas em emergências — o CI vai validar novamente do zero.
make validate
Roda toda a validação local sem fazer release. Equivalente ao bloco de validação do CI.
make publish
Fallback manual. Requer NPM_TOKEN no ~/.npmrc (token com bypass 2FA) ou npm login interativo. Não dispara workflow — publish direto.
npm config set //registry.npmjs.org/:_authToken=npm_xxx... --location=user
npm run build
make publish
Sem token com bypass 2FA, npm exige OTP:
npm publish --access public --otp=123456
make releases
Lista todas as tags v*.*.* ordenadas por versão (mais recentes primeiro).
make releases-md
Regenera RELEASES.md a partir das git tags. Chamado automaticamente pelo scripts/release.sh após criar a tag.
make releases-check
Relatório de sincronia das três superfícies — uma linha por git tag, dizendo se a versão existe no npm e se a tag tem GitHub Release:
TAG NPM RELEASE STATUS
v0.24.0 ok ok sincronizado
v0.23.0 ok FALTA DESSINCRONIZADO
Só leitura, seguro de rodar sempre. Use antes e depois de um release.
make releases-sync / make releases-sync-dry
Cria os GitHub Releases faltantes para tags que já existem (backfill), com as notas vindas da seção correspondente do CHANGELOG.md. Tags que já têm Release são puladas — o script é idempotente e nunca reescreve um Release existente.
make releases-sync-dry # lista o que faria, sem criar nada
make releases-sync # cria de verdade
Necessário porque o publish no npm e a criação do Release passaram a andar juntos só a partir da v0.24.0: as tags anteriores existiam no git e no npm, mas sem Release no GitHub.
Notas de um backfill nunca herdam [Unreleased]
O scripts/changelog.mjs notes <versão> só cai no bloco [Unreleased] quando recebe --allow-unreleased (o que o workflow faz, para o caso de um release cortado antes de datar a seção). No backfill a flag não é passada — assim uma tag antiga nunca recebe as notas do ciclo seguinte; sem seção, o Release sai com um ponteiro para o CHANGELOG.md.
CI workflow (.github/workflows/release-npm.yml)
Disparado por:
push: tags: [v*.*.*]— fluxo principal.make release TAG=Xpush uma tag e o workflow dispara automaticamente.workflow_dispatch— manual viagh workflow run release-npm.yml --ref main. Útil quando o publish de uma tag falhou e você quer re-rodar sem incrementar versão.
Passos do job publish:
- Checkout (
actions/checkout@v5) comfetch-depth: 0. - Node 22 +
registry-url: https://registry.npmjs.org+ cache npm, enpm install -g npm@latest(Trusted Publishing exige npm >= 11.5.1). - Guard de versão — compara a tag (
GITHUB_REF_NAMEsem ov) com oversiondopackage.jsone aborta se divergirem, antes de qualquer publish. Também derivaprerelease(versão com-) para marcar o Release corretamente. Emworkflow_dispatcha tag é derivada dopackage.json. npm ci.- Lint (
npm run lint). - Format check (
npm run format:check). - Typecheck (
npm run typecheck). - Tests (
npm run test:run). - Build (
npm run build). - Smoke install — gera tarball via
npm pack, instala em/tmp/sdk-smokecomreact@^19 react-dom@^19(as demais deps vêm como dependências diretas do pacote), importa o pacote dinamicamente e valida que 20 exports core estão presentes. npm publish --provenance --access publicvia Trusted Publishing (OIDC) — semNPM_TOKEN.id-token: writeé o que permite o attestation de provenance no sigstore.- Read-back do registry — confirma que o npm serve
tempest-react-sdk@<versão>(com até 5 tentativas, porque o registry demora a propagar) e quedist-tags.latestaponta para ela. Falha o job caso contrário: publish que aterrissou em outra tag deixaria de parecer verde. - GitHub Release —
gh release create <tag>com o tarball anexado e as notas extraídas da seção doCHANGELOG.md(scripts/changelog.mjs notes <versão> --allow-unreleased), acrescidas do link para a versão no npm. Se o Release já existe, fazgh release edit+upload --clobberem vez de falhar, então re-rodar o workflow para a mesma tag é seguro. Exigecontents: writeno job.
Segredos necessários no GitHub
Nenhum. O publish usa Trusted Publishing do npm: o npm publish troca a identidade OIDC do GitHub Actions por um token de vida curta, então não existe NPM_TOKEN no repositório. O que precisa estar configurado é um Trusted Publisher em npmjs.com apontando para este repositório + o arquivo release-npm.yml.
O GITHUB_TOKEN (usado para criar o Release) é fornecido automaticamente pelo Actions runtime — só o permissions: contents: write do job precisa estar declarado, e está.
O NPM_TOKEN continua sendo assunto do fallback local
make publish publica da sua máquina e aí sim precisa de token no ~/.npmrc (Classic Automation, ou Granular com "Allow bypass 2FA" marcado). Esse caminho não gera provenance e não cria o GitHub Release — se você usar o fallback, rode make releases-sync depois para o Release não ficar faltando.
Provenance signing
O publish inclui --provenance quando rodado no CI. Isso requer:
permissions: id-token: writeno workflow (já configurado).- npm >= 11.5.1 no runner (o step de upgrade cuida disso).
- Um Trusted Publisher configurado no npmjs.com para este repositório.
O resultado: cada versão publicada carrega um attestation assinado pelo sigstore, ligando o tarball ao commit + workflow run que o produziram. Visível no registry como badge "Verified provenance".
Publish manual local não consegue provenance — não há OIDC provider fora do CI. make publish sempre roda sem --provenance.
Histórico
Veja RELEASES.md (auto-gerado via make releases-md) e CHANGELOG.md (escrito à mão antes de cada release).
Veja também
CHANGELOG.md— registro de mudanças por versãoRELEASES.md— tabela de tags com data e commitMakefile— definição dos alvosscripts/release.sh— script bash do pipeline