Runbook do ciclo de lançamento
Fluxo de lançamento completo, dos portões locais, passando pelo GitHub Release assinado, até a publicação no npm.
Este runbook conduz um lançamento vX.Y.Z do apothem de uma árvore de
trabalho limpa até superfícies de distribuição verificadas. O procedimento é
escrito para o mantenedor que maneja gh, git e o shell de nível de
lançamento; ele termina com uma página de Release verificada, um CHANGELOG
registrado e um teste de fumaça da rota de instalação que confirma que cada
superfície voltada ao usuário responde ao comando de instalação canônico.
O modelo de lançamento é aditivo. Cada lançamento adiciona um commit em
main e uma tag vX.Y.Z assinada e anotada; nada recebe force-push e nenhuma
tag, GitHub Release ou versão do npm anterior é removida. Cada lançamento mantém sua tag, seu GitHub Release e sua versão do npm, e todos permanecem publicados: as versões do npm são imutáveis (um name@version
publicado nunca pode ser substituído), e as instalações fixadas dependem das
tags.
O push da tag inicia três fluxos de trabalho. .github/workflows/release.yml
compila, assina, atesta e publica o GitHub Release com seu conjunto completo de
artefatos: sdist, wheel, SBOM CycloneDX, bundles cosign do Sigstore, procedência
SLSA-3 e os arquivos de runtime de cada plataforma. publish-npm.yml publica
@ahmed-g-gad/apothem no npmjs.com por meio da publicação confiável do npm, e
publish-vscode.yml empacota a extensão do VS Code e a publica no Visual Studio
Marketplace. A seção versionada do CHANGELOG entra no commit de lançamento; o operador executa
o teste de fumaça da rota de instalação depois que ambos os fluxos de trabalho
terminam.
1. Pré-requisitos
O mantenedor confirma o seguinte antes de marcar a tag:
-
Árvore de trabalho. Limpa (
git statusnão mostra nada pendente). Todo o trabalho de funcionalidades do lançamento está emmain. -
CI em verde. No
mainmais recente,gh run list --branch=main --limit=1 --json conclusion --jq '.[0].conclusion'retornasuccess. -
Ferramentas.
gh(GitHub CLI) versão 2.40 ou posterior autenticado emahmed-g-gad;git2.40 ou posterior com a subchave de assinatura GPG carregada; o vínculo de publicador confiável do npm para@ahmed-g-gad/apothemestá ativo (verificado conforme o runbook de configuração da conta de publicador). -
Âncoras de versão alinhadas. A string de versão declarada em
pyproject.tomlcorresponde à tag planejada sem o prefixov(a §2.1 a define, junto com todas as outras âncoras). Verifique:grep '^version' pyproject.tomlSaída esperada (para um lançamento
vX.Y.Z; os marcadores de posição representam a tag do lançamento em andamento):version = "X.Y.Z" -
Entradas do CHANGELOG preparadas. Os itens do lançamento ficam em
## [Unreleased], nos cabeçalhos do Keep-a-Changelog; a §2.1 os transforma na seção de versão datada no commit em que a tag é aplicada.
2. Marcar a tag e disparar
2.1 Redigir o commit de lançamento
A versão fica em mais de uma dúzia de arquivos, então não os edite à mão. Um único comando altera todos eles:
git checkout main
git pull --ff-only origin main
python scripts/release/bump_version.py X.Y.Zbump_version.py atualiza todas as âncoras de versão juntas:
-
Todos os manifestos de empacotamento, extensão, plugin e marketplace, além do arquivo de citação (versão e data de lançamento). A lista completa:
pyproject.toml package.json site/package.json site/package-lock.json (the project entries only) vscode-extension/package.json gemini-extension.json qwen-extension.json .claude-plugin/marketplace.json (top level and metadata) plugins/apothem/plugin.json plugins/apothem/.codex-plugin/plugin.json CITATION.cff -
CHANGELOG.md: as entradas de[Unreleased]se tornam uma seção## [X.Y.Z]datada,[Unreleased]passa a comparar a partir devX.Y.Z, e um link[X.Y.Z]é adicionado. -
SECURITY.md: uma nova versão menor ganha uma linhaX.Y.xsuportada. Se as versões menores mais antigas continuam listadas é decisão sua; o script exibe um lembrete.
Em seguida, ele regenera as árvores derivadas: o pacote do plugin do Claude
Code, os goldens de diff de comportamento e as páginas de referência e de
changelog da documentação. Passe --dry-run para listar as mudanças primeiro,
--date YYYY-MM-DD para definir a data de lançamento (padrão: hoje em UTC), ou
--no-regen para pular a regeneração. O script recusa uma versão malformada ou
um downgrade, e executá-lo novamente com a versão atual apenas realinha âncoras
dispersas.
Revise o diff e depois faça o commit:
git add -A
git commit -S -m "chore(release): cut vX.Y.Z"
git push origin mainO sinalizador -S assina o commit com a chave GPG. O push dispara a matriz de
CI padrão (lint, test, build); aguarde o verde antes de marcar a tag.
A verificação de prontidão da §2.4 também exige CodeQL e Conformity em verde no
commit de lançamento. Os dois só são executados quando os caminhos próprios de
cada um mudam, e um commit de lançamento normalmente não altera nenhum deles;
por isso, inicie-os depois que o commit de lançamento for o último commit de
main, e então confirme que cada execução identifica esse commit:
gh workflow run codeql.yml --ref main
gh workflow run conformity.yml --ref main
gh run list --workflow codeql.yml --commit "$(git rev-parse HEAD)" --limit 1
gh run list --workflow conformity.yml --commit "$(git rev-parse HEAD)" --limit 1Aguarde os dois terminarem com sucesso antes de marcar a tag, e não envie mais
nada para main até que o lançamento esteja publicado: um push posterior afasta
main do commit de lançamento, e o CI cancela a execução que ainda estiver em
andamento na mesma branch.
2.2 Assinar e enviar a tag
git tag -a -s vX.Y.Z -m "vX.Y.Z"
git push origin vX.Y.ZA combinação -a -s produz uma tag anotada e assinada com GPG. O push dispara
.github/workflows/release.yml, que compila, assina, atesta e publica.
2.3 Confirmar que o fluxo de trabalho de lançamento foi concluído
gh run watch $(gh run list --workflow=release.yml --limit=1 --json databaseId --jq '.[0].databaseId')O fluxo de trabalho executa a compilação (sdist + wheel, depois um SBOM
CycloneDX dessas distribuições gravado ao lado delas), a assinatura cosign sem
chave, a geração e a verificação da procedência SLSA-3, as compilações dos
arquivos de plataforma (darwin / linux / windows), a assinatura dos arquivos com
um manifesto SHA256SUMS agregado e a publicação final do GitHub Release. O
mantenedor examina o log do job publish GitHub Release em busca das
confirmações de upload dos ativos.
O job publish GitHub Release é executado no ambiente release, que exige a
aprovação do mantenedor; por isso, a execução aguarda ali assim que os jobs
anteriores passam. Aprove-a na página da execução (Review deployments,
revisar implantações), ou pelo shell:
run_id=$(gh run list --workflow=release.yml --limit=1 --json databaseId --jq '.[0].databaseId')
env_id=$(gh api repos/ahmed-g-gad/apothem/environments/release --jq .id)
gh api -X POST "repos/ahmed-g-gad/apothem/actions/runs/${run_id}/pending_deployments" \
-F "environment_ids[]=${env_id}" -f state=approved -f comment="vX.Y.Z"O push da tag também inicia os fluxos de trabalho do npm e da extensão do VS Code. Os jobs de publicação deles ficam aguardando essa mesma aprovação até a §2.4.
2.4 Confirmar a publicação no npm
O push da tag também executa publish-npm.yml ao lado de release.yml. O fluxo de trabalho do npm não espera pelo fluxo de trabalho de lançamento; a aprovação do ambiente release é o portão. Quando o fluxo de trabalho de lançamento da §2.3 tiver terminado, confirme a prontidão. A verificação lê os lançamentos, as execuções de fluxos de trabalho e o SBOM publicado; por isso, prepare duas entradas antes:
GH_TOKEN. O script se recusa a rodar sem ele, mesmo quando oghjá está autenticado. Use um token de acesso pessoal de granularidade fina limitado aahmed-g-gad/apothem, com Actions: Read (execuções de fluxos de trabalho) e Contents: Read (lançamentos). A verificação não grava nada, por isso nenhuma permissão de escrita é necessária. Um token obtido comgh auth tokencarrega todos os escopos do login; prefira, portanto, o token de granularidade fina.- O SBOM publicado. A verificação lê
dist/release-assets/sbom.cdx.json, o arquivo CycloneDX que o lançamento anexa. Baixe a cópia que o lançamento publicou, em vez de um build local.
read -rs GH_TOKEN && export GH_TOKEN
mkdir -p dist/release-assets
gh release download vX.Y.Z --repo ahmed-g-gad/apothem \
--pattern sbom.cdx.json --dir dist/release-assets --clobber
bash scripts/release/check-release-ready.sh vX.Y.ZA verificação falha quando o lançamento é um rascunho ou um pré-lançamento, quando um fluxo de trabalho exigido para o commit da tag não está verde, quando o SBOM está ausente, quando ele descreve outra versão ou quando omite um pacote incorporado. A mensagem de falha informa a causa.
Quando a verificação passar, aprove a execução Publish npm que está
aguardando, do mesmo modo que na §2.3 (o ID da execução vem de
gh run list --workflow=publish-npm.yml). O fluxo de trabalho publica
@ahmed-g-gad/[email protected] no npmjs.com por meio da publicação confiável do npm
(OIDC); nenhum token de registro é armazenado no repositório. Aprove também a
execução Publish VS Code Extension que está aguardando. Ela empacota
apothem.vsix e o publica no Visual Studio Marketplace como
ahmed-g-gad.apothem-vscode. A etapa de publicação roda somente enquanto a variável
do repositório VSCODE_MARKETPLACE_READY for true e uma credencial estiver
configurada: a variável VSCE_AUTH=oidc (Trusted Publishing do Marketplace, sem
segredo armazenado), as variáveis VSCE_AUTH=entra, AZURE_CLIENT_ID e
AZURE_TENANT_ID (um token de curta duração do Microsoft Entra ID, sem segredo
armazenado), ou o segredo VSCE_PAT. Sem nenhuma delas, a execução empacota a
extensão e pula a publicação. A credencial é uma chave seletora, não uma nova
tentativa: uma publicação com falha em uma rota não recorre a outra por conta
própria. A configuração de cada rota está em
Publicação no Marketplace com Trusted Publishing
(preferida) e
Publicação no Marketplace com Microsoft Entra ID
abaixo.
Para publicar novamente após uma execução com falha, despache o fluxo de
trabalho para a mesma tag (gh workflow run publish-npm.yml --field tag=vX.Y.Z).
Ele pula a publicação quando a versão já está no registro, porque as versões do
npm são imutáveis.
Publicação no Marketplace com Trusted Publishing
O Trusted Publishing permite que o Marketplace aceite diretamente o token OIDC
do GitHub deste repositório: vsce publish --oidc troca o token do job de
publicação por uma credencial de curta duração do Marketplace. Não há segredo
armazenado nem recurso do Azure, por isso esta é a rota preferida. A rota do
Entra abaixo e o segredo VSCE_PAT permanecem como alternativas que o operador
seleciona.
-
Use uma versão do vsce que dê suporte a ela. Nesta rota, o job de publicação verifica a versão do vsce travada em
tools/vsceantes de publicar e para com um erro que nomeia a versão mínima quando a trava é mais antiga. O Dependabot propõe atualizações do vsce para esse lockfile; faça o merge daquela que alcança a versão mínima antes de trocar de rota. -
Crie a política. Entre como Owner do publicador, abra
https://marketplace.visualstudio.com/manage/publishers/ahmed-g-gade adicione uma política em Trusted Publishing:- Nome da política: qualquer nome, como
apothem-release - Proprietário do repositório:
Ahmed-G-Gad - Repositório:
apothem - Fluxo de trabalho:
publish-vscode.yml - Ambiente:
release
Os nomes dos campos são os que o guia de publicação do VS Code lista, na sua seção sobre publicação com GitHub Actions e Trusted Publishing (
https://code.visualstudio.com/api/working-with-extensions/publishing-extension). Não confirmado: se todo publicador já vê a aba Trusted Publishing. Se o seu não vir, use a rota do Entra. - Nome da política: qualquer nome, como
-
Troque a rota. Mantenha
VSCODE_MARKETPLACE_READYdefinida comotruee defina o seletor. Defina-o quando nenhuma tag estiver aguardando, porque o próximo push de tag publica por esta rota.gh variable set VSCE_AUTH --body oidc -
Publique. O próximo push de tag, ou um despacho para uma tag existente, publica por meio do Trusted Publishing. Esta rota não tem execução de teste (dry run): a primeira publicação é a verificação, e um despacho com
dry_runapenas avisa que nada foi verificado. -
Recorra à alternativa se falhar. Exclua o seletor e despache novamente para a mesma tag; com o segredo
VSCE_PATdefinido, a rota do token publica. Uma publicação com falha não publicou nada, então a mesma tag pode ser despachada novamente.gh variable delete VSCE_AUTH
Publicação no Marketplace com Microsoft Entra ID
A rota do Entra substitui o token de acesso pessoal armazenado por um token de
curta duração. publish-vscode.yml pede ao GitHub um token OIDC, a action
Azure/login o troca por um login do Entra por meio de uma credencial
federada, e vsce publish --azure-credential publica com o token resultante.
Não existe nenhum segredo de cliente. O segredo VSCE_PAT permanece como uma
alternativa que o operador seleciona; o fluxo de trabalho nunca muda para ele
por conta própria.
A versão do vsce fixada em tools/vsce dá suporte a esta rota. Ela exige um
tenant do Entra, um registro de aplicativo e a associação ao publicador, o que
o Trusted Publishing acima não exige; use-a quando o Trusted Publishing não
estiver disponível para o publicador.
-
Verifique as pré-condições. Encontre a conta proprietária do publicador
ahmed-g-gad(a aba Members emhttps://marketplace.visualstudio.com/manage/publishers/ahmed-g-gad) e o tenant do Entra em que você pode registrar aplicativos. Não confirmado: se o tenant do proprietário do publicador precisa corresponder ao tenant do aplicativo, e se a organização do Azure DevOpsAhmed-G-Gadprecisa estar conectada ao Entra (dev.azure.com/Ahmed-G-Gad, Organization settings, Microsoft Entra). Nenhuma fonte afirma nenhuma das duas coisas. Se a etapa 5 ou 6 falhar, verifique estes pontos primeiro. -
Registre o aplicativo. Em
https://entra.microsoft.com, abra App registrations e depois New registration. Dê a ele o nomeapothem-vscode-publish, escolha um único tenant e deixe o URI de redirecionamento vazio. Em Overview, copie o Application (client) ID e o Directory (tenant) ID. Não crie nenhum segredo de cliente e não conceda nenhuma permissão de API. A etapa exige direitos de proprietário do aplicativo ou uma função do Entra como Application Administrator. -
Adicione a credencial federada. Nesse aplicativo, abra Certificates & secrets, Federated credentials, Add credential, e escolha o cenário "GitHub Actions deploying Azure resources". Informe a organização
Ahmed-G-Gad, o repositórioapothem, o tipo de entidadeEnvironment, o nome de ambientereleasee o nome de credencialapothem-release. Os campos gerados devem mostrar:issuer: https://token.actions.githubusercontent.com subject: repo:Ahmed-G-Gad/apothem:environment:release audience: api://AzureADTokenExchangeA correspondência é exata e diferencia maiúsculas de minúsculas. Se um login posterior falhar com AADSTS700213 ou AADSTS7002138, compare a credencial com a linha
subject claimqueAzure/logingrava no log do job. AADSTS70021 logo após a criação significa que a credencial ainda não se propagou; aguarde alguns minutos e tente novamente. -
Defina as variáveis do repositório. Enquanto
VSCODE_MARKETPLACE_READYfortrue, a rota do Entra fica ativa assim que as três estiverem definidas; por isso, defina-as quando nenhuma tag de lançamento estiver aguardando aprovação. SemVSCODE_MARKETPLACE_READY=true, nada faz login e a execução pula a publicação.gh variable set AZURE_CLIENT_ID --body "<application-client-id>" gh variable set AZURE_TENANT_ID --body "<directory-tenant-id>" gh variable set VSCE_AUTH --body entraDeixe
VSCODE_MARKETPLACE_READYeVSCE_PATcomo estão. QuandoVSCE_AUTHéentra, masAZURE_CLIENT_IDouAZURE_TENANT_IDestá vazia, o fluxo de trabalho registra um aviso, esteja ou nãoVSCE_PATdefinido, e não usa a rota do Entra. Ele então usa o segredoVSCE_PAT, se estiver definido; sem o segredo, não publica nada e a execução ainda termina em verde, então procure o aviso. -
Faça a execução de teste. Despache o fluxo de trabalho para uma tag de lançamento existente com
dry_rundefinido. Na rota do Entra, ele faz login, imprime o perfil do Azure DevOps e verifica o acesso ao publicador sem publicar. A rota do token não tem execução de teste: se o log mostrarMarketplace credential mode: pat, a execução termina em verde com um aviso e não verificou nada. Aprove a execução do ambientereleaseque está aguardando.gh workflow run publish-vscode.yml --ref main -f tag=vX.Y.Z -f dry_run=trueEsperado:
Marketplace credential mode: entra, uma linhasubject claimigual ao subject da etapa 3, e oide odisplayNamedo perfil impressos pela primeira etapa da execução de teste. Espera-se que a etapa de verificação falhe com um 403 até a etapa 6. Não confirmado: que um login sem uma assinatura do Azure produza um token para o Marketplace por meio da CLI do Azure. Esta execução é o primeiro teste disso. Se falhar aqui, registre em vez disso uma identidade gerenciada atribuída pelo usuário em uma assinatura, que é a rota que a Microsoft documenta. -
Adicione o aplicativo ao publicador. Na aba Members da etapa 1, entre como Owner do publicador e adicione um membro usando o
iddo perfil da etapa 5, com a função Contributor. Não confirmado: o rótulo do campo da caixa de diálogo, e se ela aceita o id antes de o aplicativo ser membro de uma organização do Azure DevOps. Como regra geral, o Azure DevOps adiciona identidades de aplicativo por organização. Se a caixa de diálogo rejeitar o id, adicione a entidade de serviço à organizaçãoAhmed-G-Gad(Organization settings, Users, usando o Object ID do Enterprise application) e tente novamente. Também não confirmado: se o perfil existe antes da primeira chamada da identidade ao Azure DevOps. -
Repita a execução de teste. A etapa de verificação agora é bem-sucedida com "verification succeeded for the publisher"; suas mensagens ainda falam em Personal Access Token, porque o token do Entra percorre o mesmo caminho. A verificação comprova a associação ao publicador (Creator, Owner, Contributor ou Reader), não os direitos de publicação. Não confirmado: que Contributor baste para publicar uma atualização. A descrição de funções da Microsoft diz que basta, e nenhuma fonte mostra uma publicação com ela, então a primeira publicação real é a prova.
-
Publique um lançamento. Marque a tag como na §2.2 e aprove a execução. A etapa
Publish to Visual Studio Marketplace (Entra ID)é executada, o cabeçalho de ambiente dela lista apenasAZURE_TENANT_ID, a etapa alternativa do token é pulada, e o vsce imprimeDONE Published ahmed-g-gad.apothem-vscode. A galeria do Marketplace lista a nova versão após cerca de quatro minutos. -
Decida sobre o token. Mantenha
VSCE_PATaté a primeira publicação bem-sucedida pelo Entra e depois exclua o segredo se nenhuma alternativa for desejada. Depois que ele não existir mais, uma variável do Entra excluída ou vazia deixa a execução em verde sem publicação: com um aviso quandoVSCE_AUTHainda éentra, e apenas com o aviso de pulo quando não é. Leia as anotações da execução após cada tag. Para manter uma alternativa além da aposentadoria dos tokens de acesso pessoal globais, crie um token com escopo de organização paraAhmed-G-Gadcom o escopo personalizado Marketplace Manage e a validade mais curta que você aceitar, e armazene-o comoVSCE_PAT. Não confirmado: os rótulos do portal nesta etapa vêm da memória, não de uma fonte primária; a Microsoft chama os tokens com escopo de organização de solução temporária e pode deixar de aceitá-los; e as páginas da Microsoft divergem sobre a data de aposentadoria dos tokens globais. -
Recorra ao token. Exclua o seletor e despache novamente; depois, aprove a execução. Uma publicação com falha pelo Entra não publicou nada, então a mesma tag pode ser despachada novamente; verifique antes a página do Marketplace, porque uma versão que chegou lá não pode ser publicada duas vezes.
gh variable delete VSCE_AUTH gh workflow run publish-vscode.yml --ref main -f tag=vX.Y.Z
Quando a publicação pelo Entra falhar, leia o log da etapa:
- Uma mensagem que começa com "Can not acquire a Microsoft Entra ID access
token" significa que o login ou a cadeia de credenciais falhou. Verifique
primeiro a etapa
Sign in to Microsoft Entra IDe a credencial federada. Se o login estiver em verde, removaAZURE_TENANT_IDdoenvda etapa do vsce no fluxo de trabalho; o próprio fluxo de trabalho de lançamento de extensão do GitHub não o exporta. - "InvalidAccessException" ou "not allowed" significa que a identidade do token
não é membro do publicador. Compare o
iddo perfil da execução de teste com a aba Members. - Um 403 da etapa de verificação da execução de teste significa que o aplicativo ainda não tem função.
Três limites se aplicam a esta rota:
id-token: writeé concedido a todo o job de publicação, de modo que qualquer etapa dele pode solicitar um token OIDC, também no modo token. O subject do token está vinculado ao ambienterelease, que exige a aprovação de um revisor.- O ambiente
releasenão tem política de branch ou de tag de implantação, de modo que qualquer ref que um mantenedor aprove pode obter o token com o subject do ambiente. Restringi-lo a tagsv*.*.*exige verificar antes o querelease.ymlepublish-npm.ymldespacham. - Uma renomeação ou transferência do repositório muda o formato do subject OIDC
e quebra silenciosamente a credencial federada. Copie novamente o subject do
log do
Azure/loginpara a credencial após qualquer renomeação.
2.5 Atualizar a fixação do digest dos templates
Depois que a tag existir, defina _LATEST_RELEASE e _LATEST_RELEASE_DIGESTS
em tests/unit/test_template_digests.py com o novo lançamento e o digest
SHA-256 de cada template de texto simples tal como esse lançamento o entregou
(git show vX.Y.Z:<template path> | sha256sum). Faça isso na próxima mudança
em main e adicione o digest anterior a earlier_digests da entrada do
manifesto quando o template tiver mudado. O job de CI release-preflight faz
checkout de cada tag, por isso falha com os nomes das tags até que a fixação
seja atualizada.
3. Superfícies de distribuição
Cada superfície tem um comando de verificação que responde "o lançamento chegou aqui?":
| # | Superfície | Artefato | Verificação |
|---|---|---|---|
| 1 | GitHub Release (distribuições Python) | apothem-X.Y.Z.tar.gz (sdist) + apothem-X.Y.Z-py3-none-any.whl | gh release view vX.Y.Z --json assets --jq '.assets[].name' inclui ambos os nomes de arquivo |
| 2 | GitHub Release (SBOM) | sbom.cdx.json + sbom.cdx.json.cosign.bundle | a lista de ativos inclui ambos; o metadata.component.purl do SBOM é pkg:pypi/[email protected] e seus componentes incluem todos os pacotes de src/apothem/_vendor/vendor.txt |
| 3 | GitHub Release (assinaturas) | um <asset>.cosign.bundle por sdist, wheel, SBOM, extensão do VS Code, arquivo de plataforma e SHA256SUMS (os lançamentos anteriores nomeiam os bundles dos arquivos e de SHA256SUMS como <asset>.sig) | cosign verify-blob com a identidade exata da §5.5 sai com 0 |
| 4 | GitHub Release (procedência) | provenance.intoto.jsonl | bash scripts/release/verify-provenance.sh <download-dir> sai com 0 (§5.5) |
| 5 | GitHub Release (arquivos de plataforma) | apothem-vX.Y.Z-darwin.tar.gz, apothem-vX.Y.Z-linux.tar.gz, apothem-vX.Y.Z-windows.zip | a lista de ativos inclui cada arquivo mais SHA256SUMS. Os arquivos darwin e linux são os mesmos bytes sob dois nomes (o runtime é neutro em relação à plataforma; --platform apenas escolhe entre tar.gz e zip), de modo que suas linhas em SHA256SUMS mostram o mesmo digest duas vezes |
| 6 | GitHub Release (extensão do VS Code) | apothem.vsix + apothem.vsix.cosign.bundle | a lista de ativos inclui ambos; code --install-extension apothem.vsix a instala. Os lançamentos anteriores ao empacotamento da extensão pelo fluxo de trabalho de lançamento não trazem nenhum dos dois |
| 7 | npmjs.com | @ahmed-g-gad/[email protected] | npm view @ahmed-g-gad/apothem version retorna X.Y.Z; npx @ahmed-g-gad/[email protected] --version imprime Apothem, version X.Y.Z |
| 8 | Pages (instaladores de script) | install.sh / install.ps1 no site de documentação | curl -fsSL https://apothem.ahmedgad.com/install.sh | head -n 1 retorna o cabeçalho do script |
| 9 | Visual Studio Marketplace | ahmed-g-gad.apothem-vscode versão X.Y.Z | a página da extensão no Marketplace lista X.Y.Z; code --install-extension ahmed-g-gad.apothem-vscode a instala |
O GitHub Release é a superfície canônica de artefatos; o pacote do npm e os instaladores de script são as rotas de instalação sobrepostas a ele. A publicação no npm é executada ao lado do fluxo de trabalho de lançamento, no mesmo push da tag.
4. Disciplina do CHANGELOG
O CHANGELOG.md carrega uma seção por lançamento sob a convenção
Keep-a-Changelog. A edição do CHANGELOG no commit de lançamento:
- Confirma que a seção de versão usa o cabeçalho
## [X.Y.Z] - YYYY-MM-DD(um hífen;bump_version.pyo escreve, eextract_release_notes.pycorresponde ao prefixo## [X.Y.Z]). - Confirma que os cabeçalhos padrão — Added, Changed, Deprecated, Removed, Fixed, Security — são usados onde aplicável. Cabeçalhos vazios são removidos do arquivo renderizado.
- Captura capacidades, não implementação. Apenas linguagem de domínio; sem referências internas ao plano; sem hashes de commit; sem identificadores de plano ou de fase.
Uma seção do CHANGELOG que passou pela revisão do mantenedor serve como âncora das notas de lançamento para a narrativa do anúncio.
5. Teste de fumaça da rota de instalação
Depois que ambos os estágios forem concluídos, o mantenedor executa o teste de fumaça. O teste de fumaça é a verificação canônica de que os comandos de instalação voltados ao usuário respondem.
5.1 Plugin do Claude Code
/plugin marketplace add ahmed-g-gad/apothem
/plugin install apothem@apothemEsperado: o plugin é instalado e os comandos apothem ficam disponíveis dentro
do Claude Code.
5.2 Node.js (npx)
npx @ahmed-g-gad/[email protected] --versionSaída esperada: Apothem, version X.Y.Z.
5.3 Instalador de script de um único passo (POSIX)
O instalador grava o lançador apothem em ~/.local/bin, ou no diretório indicado por APOTHEM_BIN_DIR quando essa variável está definida. A verificação abaixo precisa que esse diretório esteja no PATH. Quando não está, o instalador imprime a linha export PATH a ser adicionada. Enquanto esse diretório não estiver no PATH, o shell não encontra apothem, e a verificação falha. Se o instalador não conseguir colocar o lançador no lugar, ele imprime um aviso e nenhuma linha export PATH. Em um host que ainda não tem a chave de assinatura do mantenedor, a primeira linha abaixo a importa; sem ela, o instalador para.
curl -fsSL https://github.com/ahmed-g-gad.gpg | gpg --import
curl -fsSL https://apothem.ahmedgad.com/install.sh | sh
apothem --versionSaída esperada: Apothem, version X.Y.Z.
5.4 Instalador de script de um único passo (Windows)
A primeira linha importa a chave de assinatura do mantenedor pelo próprio bash do Git, cujo chaveiro gpg é o que o git verify-tag lê.
& "$env:ProgramFiles\Git\bin\bash.exe" -c 'curl -fsSL https://github.com/ahmed-g-gad.gpg | gpg --import'
irm https://apothem.ahmedgad.com/install.ps1 | iex
apothem --versionSaída esperada: Apothem, version X.Y.Z.
5.5 Verificação de artefatos (evidência da cadeia de suprimentos)
Baixe todos os ativos para um diretório vazio e depois verifique. A identidade
do certificado é o fluxo de trabalho de lançamento nesta tag exata. As
verificações de identidade diferenciam maiúsculas de minúsculas, e os
certificados trazem o proprietário como o GitHub o informa, Ahmed-G-Gad, de
modo que um proprietário em minúsculas falha.
mkdir release-vX.Y.Z && cd release-vX.Y.Z
gh release download vX.Y.Z --repo ahmed-g-gad/apothem
cosign verify-blob \
--bundle apothem-X.Y.Z-py3-none-any.whl.cosign.bundle \
--certificate-identity https://github.com/Ahmed-G-Gad/apothem/.github/workflows/release.yml@refs/tags/vX.Y.Z \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
apothem-X.Y.Z-py3-none-any.whl
slsa-verifier verify-artifact \
--provenance-path provenance.intoto.jsonl \
--source-uri github.com/Ahmed-G-Gad/apothem \
--source-tag vX.Y.Z \
apothem-X.Y.Z-py3-none-any.whl apothem-X.Y.Z.tar.gz
bash ../scripts/release/verify-provenance.sh .Esperado: Verified OK, PASSED: SLSA verification passed e
verify-provenance: chain OK (3 of 3 layers verified). O script verifica
SHA256SUMS, cada bundle de assinatura e a procedência em uma única execução;
ele deriva a tag do nome do wheel (--tag vX.Y.Z a substitui).
O teste de fumaça produz uma linha de PASS / FAIL por superfície; registre as linhas no log de lançamento do mantenedor.
6. Recuperação de falhas
O fluxo de trabalho de lançamento tem modos de falha documentados para o motor de lançamento e o publicador do npm:
| Falha | Diagnóstico | Recuperação |
|---|---|---|
| Push da tag rejeitado (falha de assinatura) | git push origin vX.Y.Z retorna error: failed to push some refs com uma mensagem relacionada a GPG | Verifique se a subchave GPG está carregada (gpg --list-secret-keys --keyid-format=long); marque a tag novamente, localmente, com -s depois de corrigir o chaveiro; envie novamente |
A compilação do lançamento para em Check the plugin version changed with the plugin | O log do job de compilação nomeia o plugin e a tag anterior; nenhum ativo foi compilado ou publicado | O pacote do plugin mudou desde o lançamento anterior, mas sua versão não. Exclua a tag (git push --delete origin vX.Y.Z, git tag -d vX.Y.Z), execute python scripts/release/bump_version.py X.Y.Z, faça o commit e então assine e envie a tag novamente (§2.2). A mesma verificação é executada em todo pull request como uma anotação de aviso, então isso normalmente aparece antes de marcar a tag |
Um job de release.yml falha em um único estágio | gh run view <run-id> --log nomeia o job que falhou (build, que também grava o SBOM / sign / provenance / archive / publish) | Execute novamente apenas o job que falhou via gh run rerun <run-id> --failed; se a falha se repetir, corrija a entrada do job na origem antes de marcar a tag novamente |
| A verificação da procedência SLSA falha | O job verify SLSA provenance artifact sai com código diferente de zero | Inspecione o artefato de procedência em busca de incompatibilidade de digest do sujeito; recompile a partir da mesma tag — a procedência se vincula aos digests exatos dos artefatos, então qualquer regeneração de artefatos exige uma reexecução completa do fluxo de trabalho |
| Publicação no npmjs.com rejeitada | O job do npm sai com código diferente de zero durante npm publish; um 404 do registro durante PUT é uma incompatibilidade de autorização / publicador confiável, não prova de que o código do pacote está ausente | Verifique se o npm Trusted Publishing para @ahmed-g-gad/apothem nomeia o proprietário ahmed-g-gad, o repositório apothem, o fluxo de trabalho publish-npm.yml e a ação permitida npm publish; confirme que o job é executado com a versão do Node e o piso OIDC da CLI do npm fixados no fluxo de trabalho |
| Tag visível, mas ativos ausentes | gh release view vX.Y.Z retorna um lançamento vazio | Execute novamente o job de publicação do fluxo de trabalho de lançamento; ele edita o lançamento existente e reenvia todos os ativos. Exclua a tag e marque-a novamente somente quando nada da tag tiver chegado aos usuários (nenhum ativo, nenhuma versão do npm); caso contrário, corrija para frente com o próximo lançamento de patch (runbook de recuperação de lançamento §2) |
Se um ciclo de recuperação não conseguir fazer uma superfície chegar ao destino em um único passe de diagnóstico, a superfície é registrada como uma falha conhecida nas notas de lançamento, com um link para a issue aberta; os usuários a jusante são direcionados às superfícies que funcionam enquanto a quebrada é corrigida em um lançamento de patch.
7. Referências cruzadas
- Configuração do publicador. O runbook de configuração da conta de publicador estabelece o vínculo de publicador confiável do npm e os pré-requisitos do lado do GitHub que este runbook pressupõe.
- Fluxo de recuperação. O runbook de recuperação de lançamento segue o mesmo modelo aditivo: ele recupera uma tag ou um estágio de publicador com falha, estágio por estágio, e faz a reversão lançando a correção como uma nova versão de patch, nunca excluindo ou redirecionando uma tag, um lançamento ou uma versão do npm publicados.
- Habilitação do Pages. O fluxo de trabalho
publish-static-site.ymlvalida e implanta o site do projeto no domínio personalizado; o runbook de habilitação do Pages (site/content/docs/runbooks/pages-enablement.mdx) é o procedimento anterior que estabeleceu o domínio personalizado em primeiro lugar. - Política de versionamento.
site/content/docs/governance/release-engineering-policy.mdxcontém a política de SemVer + assinatura + descontinuação que este runbook respeita.