# Automação de releases do GitHub com agentes de IA e aprovação

A automação de releases deve eliminar o trabalho burocrático, não dar a um agente de programação autoridade para distribuir software sempre que ele decidir que está pronto. Um agente pode reunir alterações, calcular uma versão, criar um candidato a release, preparar notas e organizar artefatos. A publicação e o rollback precisam de uma pessoa que examine uma solicitação concreta e aprove aquela ação específica.

Esse limite parece conservador até você precisar corrigir um release que trouxe o binário errado, uma tag movida ou notas que prometiam uma correção que nunca foi entregue. Fazer a chamada à API é fácil. Reverter as consequências normalmente não é.

## Dê ao agente uma bancada de trabalho para releases, não a posse do repositório

Um agente de releases deve ter um conjunto pequeno e explícito de operações, alinhado ao trabalho que você quer que ele faça. Um acesso amplo de escrita ao repositório parece conveniente porque evita o desenho de uma interface. Também permite que uma instrução equivocada transforme uma tarefa de release em exclusão de tags, alteração de branches, edição de workflows ou um anúncio público.

Na automação de releases do GitHub, separo a preparação da distribuição. O agente pode ler metadados do repositório, inspecionar commits em um intervalo aprovado, executar o build, calcular hashes dos artefatos, criar ou atualizar um release em rascunho e enviar artefatos para esse rascunho. Ele não pode publicar um release, excluí-lo, alterar uma tag, modificar configurações do repositório, criar tokens nem chamar um endpoint arbitrário do GitHub.

Escreva as ações permitidas como verbos com entradas fixas. Isso é mais útil do que dizer a um agente para «ter cuidado».

- `inspect_release_range(base_tag, head_sha)` retorna commits e pull requests
- `build_candidate(head_sha)` retorna artefatos e digests SHA-256
- `create_draft(version, target_sha, notes)` retorna um identificador de rascunho
- `upload_asset(draft_id, filename, digest)` envia um arquivo verificado
- `request_publish(draft_id)` cria uma solicitação de aprovação

O verbo final importa. `request_publish` não pode publicar silenciosamente se ninguém responder. Ele deve retornar um estado pendente que o chamador possa exibir e consultar. Um fluxo de release que trata um timeout como consentimento já destruiu o próprio controle.

Evite uma saída de emergência como `github_api(method, path, body)`. As equipes costumam adicioná-la para a operação incomum que não coube no primeiro desenho. Mais cedo ou mais tarde, o agente a usará porque modelos de linguagem preferem o caminho mais curto em uma interface. Cada método de solicitação irrestrito transforma novamente sua autoridade limitada em um token geral do repositório.

A mesma regra vale para o acesso ao shell. Não exponha o `gh` com argumentos arbitrários e chame isso de interface de release. Encapsule as operações específicas que você aceita, valide os argumentos e rejeite todo o resto. Se precisar de uma nova ação no próximo mês, adicione-a de forma deliberada, teste-a e decida onde a confirmação deve ocorrer.

## Um release em rascunho é um objeto de revisão, não um release publicado

Um release em rascunho do GitHub permite montar o registro público sem torná-lo público. Essa distinção dá ao revisor algo concreto para examinar: versão, commit de destino, notas geradas, arquivos anexados, checksums e status de pré-release. Uma mensagem dizendo «pronto para publicar v2.4.0» não é evidência suficiente.

A documentação REST do GitHub distingue a criação de um release com `draft: true` da publicação, feita ao alterar o estado de rascunho. O GitHub também documenta que `make_latest` afeta qual release ele apresenta como o mais recente. Esses campos podem parecer metadados comuns, mas afetam usuários e ferramentas. Trate-os como escolhas de publicação, não como padrões que um agente deve inferir.

Uma solicitação sólida inclui identificadores imutáveis. A string da versão é útil para as pessoas, mas o SHA do commit identifica o código-fonte que você realmente revisou. O digest do artefato identifica o arquivo que você realmente criou. Se a solicitação disser apenas «publique v2.4.0», o revisor terá de reconstruir o release enquanto um agente impaciente espera.

Use um registro de aprovação estruturado como este:

```json
{
  "operation": "publish_release",
  "repository": "acme/widgets",
  "draft_id": "123456",
  "version": "v2.4.0",
  "target_sha": "8b0c5f7c2d6c4e1a9f1a3b0e5e92d7a4c6f80c11",
  "prerelease": false,
  "make_latest": "true",
  "assets": [
    {"name": "widgets-v2.4.0.tar.gz", "sha256": "b3e1..."},
    {"name": "widgets-v2.4.0.tar.gz.sha256", "sha256": "f18a..."}
  ],
  "notes_digest": "c921..."
}
```

A pessoa responsável pela aprovação deve abrir o rascunho e comparar esse registro com o estado do repositório. O digest das notas pode parecer exagero até que alguém edite um rascunho depois da revisão. Você não precisa tratar cada vírgula como imutável, mas precisa saber se a lista de artefatos, o destino ou a classificação do release mudou.

Um rascunho não é inofensivo por padrão. Ele pode ficar visível para usuários com acesso ao repositório e acionar ferramentas internas. Mantenha a criação de rascunhos no conjunto de menor risco apenas se o seu ambiente tratar esse material como revisão. Se os artefatos do rascunho forem enviados para um registro de pacotes ou um espelho de artefatos, exija aprovação antes do upload também.

## Vincule a versão a um commit e os artefatos à versão

A falha mais comum em um release não é um agente malicioso. É um release cuja versão, tag, commit de origem e binário vieram de momentos diferentes em um repositório em movimento.

Um processo limpo escolhe primeiro um SHA de commit imutável. O build é executado a partir desse SHA, não de um nome de branch. O agente registra os digests depois que o build termina. Só então cria uma tag e um rascunho que apontam para o mesmo SHA. Se o processo de release exigir uma tag assinada, a identidade de assinatura deve operar fora do processo do agente, assim como a credencial de publicação.

Não permita que o agente use uma referência mutável como `main` como destino de um release público. Um build pode começar em uma revisão enquanto outro merge avança a branch antes de o agente criar o release. O GitHub resolverá `main` para o destino mais recente se o seu código solicitar isso naquele momento. As notas resultantes podem descrever uma revisão e o artefato pode corresponder a outra.

Verifique a relação antes do pedido de aprovação. Uma verificação local simples pode interromper o processo cedo:

```sh
git fetch --tags origin
git rev-parse "v2.4.0^{}"
git rev-parse HEAD
shasum -a 256 dist/widgets-v2.4.0.tar.gz
```

Os dois primeiros identificadores de objeto devem coincidir depois que a tag existir, e `HEAD` deve ser o SHA revisado se o build foi feito nesse checkout. O comando de checksum produz uma linha neste formato:

```text
b3e1f2...  dist/widgets-v2.4.0.tar.gz
```

Inclua esse digest exato no registro de aprovação. Não peça ao revisor para confiar no nome do arquivo. Um arquivo chamado `widgets-v2.4.0.tar.gz` pode conter um build de depuração, um build antigo ou um binário de outra arquitetura.

A documentação do GitHub Actions alerta que `pull_request_target` é executado no contexto do repositório base e pode expor permissões de escrita ou segredos ao código não confiável de um pull request quando usado sem cuidado. A mesma lição vale para um agente de releases: não crie um artefato distribuível a partir de código não confiável em uma tarefa que pode publicar. Separe a validação não confiável do build controlado que recebe autoridade de release.

O cálculo da versão também precisa de uma regra fixa. Um agente pode propor uma versão com base em commits convencionais ou labels de merges, mas uma proposta não é uma comprovação. Uma pessoa responsável pela manutenção deve decidir como alterações incompatíveis, alterações revertidas e branches de release afetam o versionamento. O versionamento semântico automatizado falha silenciosamente quando o repositório não mantém uma disciplina consistente de commits.

## Notas de release geradas precisam de uma pessoa editora

Um agente pode transformar pull requests mesclados em um primeiro rascunho convincente. Ele não sabe se uma migração merece um alerta, se uma pessoa colaboradora quer receber crédito ou se uma mudança de comportamento quebra um caso de uso que nunca apareceu no título do commit.

Peça que ele produza notas em seções que deixem as incertezas visíveis. Coloque primeiro as mudanças voltadas aos usuários, depois as correções e, por fim, o trabalho interno. Inclua referências aos pull requests e o intervalo de commits usado. Marque as afirmações que vieram da inspeção do código, e não da descrição de uma pessoa responsável pela manutenção. Isso impede que um parágrafo bem escrito esconda uma suposição.

Rejeito a instrução popular «escreva notas de release refinadas a partir do git log». Ela é popular porque produz um documento imediatamente. Está errada porque as mensagens de commit descrevem a intenção de implementação, não necessariamente o comportamento entregue. Um commit chamado «corrigir autenticação» pode reparar um fixture de teste, alterar uma mensagem de erro ou fechar uma falha grave. A nota de release precisa descrever o impacto real para o usuário.

Faça o revisor responder a algumas perguntas simples antes da publicação:

- O commit de destino contém todas as alterações mencionadas aqui?
- Algum pull request removido ou revertido permaneceu no intervalo?
- Os usuários precisam alterar configurações, dados, permissões ou clientes?
- Algum texto de segurança precisa ser revisado pelas pessoas que investigaram o problema?
- Este é um pré-release e o GitHub deve apresentá-lo como o mais recente?

Não entregue um aviso de segurança ao agente para que ele o parafraseie em um release público. O revisor deve decidir o momento da divulgação, as versões afetadas, as soluções alternativas e os créditos. Um agente pode formatar um texto aprovado, mas não deve decidir o que se tornará público.

Mantenha as notas de release e os artefatos do release associados no momento da revisão. Quando o revisor ler «adiciona suporte a ARM», ele deve ver o artefato ARM no rascunho e seu checksum na solicitação de aprovação. Isso captura um tipo de problema constrangedor que revisões separadas da documentação e do build deixam passar.

## A confirmação deve ocorrer no limite irreversível

Uma caixa de confirmação que aparece depois da publicação apenas registra o arrependimento. Coloque o pedido imediatamente antes da operação que altera o estado de distribuição e mostre a solicitação exata que será autorizada.

A pessoa que aprova precisa de contexto suficiente para identificar uma divergência em segundos: repositório, título do rascunho, SHA de destino, nomes e digests dos artefatos, status de pré-release, escolha do release mais recente e processo que está pedindo a aprovação. Não esconda o repositório em um painel de detalhes recolhido. Um release no repositório errado pode causar mais danos que uma nota malformada.

Use uma confirmação específica para estas operações:

- publicar um release em rascunho
- excluir ou retirar um release da publicação
- excluir a tag de um release
- substituir um artefato existente do release
- mudar um release de pré-release para estável ou marcá-lo como o mais recente

A lista é curta de propósito. Pedir permissão para cada leitura e cada hash de artefato ensina as pessoas a aprovar sem olhar. Exigir uma decisão em um limite público ou destrutivo preserva a atenção onde ela pode fazer diferença.

A confirmação deve estar vinculada a um digest da solicitação. Se o agente alterar o rascunho, adicionar um artefato ou mudar `make_latest` depois da aprovação, invalide a aprovação e peça outra. Não reutilize um clique anterior apenas porque a string da versão ainda é a mesma.

A autorização por sessão do Sallyport pode identificar um novo processo do agente antes que ele execute qualquer ação, enquanto seus controles por chamada podem exigir uma aprovação separada para o uso de uma credencial escolhida. Isso se encaixa bem no trabalho de releases: permita que uma execução revisada do agente prepare um rascunho e exija uma decisão por chamada quando ela usar a credencial de publicação.

Não confunda aprovação com autenticação. Uma identidade de assinatura de código ou uma identidade de workload de CI informa qual processo fez o pedido. A confirmação diz que uma pessoa aceitou aquela ação externa específica. Você precisa dos dois registros quando um release dá errado.

## Mantenha as credenciais fora do prompt e do ambiente do agente

Um agente que possui diretamente um token do GitHub pode contornar sua interface de aprovação com um comando curl, um arquivo de workflow modificado ou uma chamada de ferramenta que você esqueceu de restringir. Instruções no prompt não fecham essa brecha.

Armazene a credencial em um componente que execute apenas a operação permitida. O agente envia uma solicitação estruturada. O componente valida o repositório, o verbo, a referência de destino e as restrições dos artefatos, obtém a aprovação necessária, injeta a credencial na solicitação de saída e retorna o resultado. O agente nunca recebe o segredo, nem mesmo como um marcador mascarado.

O Sallyport mantém segredos de API e SSH em seu cofre criptografado e executa a ação HTTP ou SSH diretamente, para que um agente compatível com MCP não precise guardar a credencial. O bloqueio do cofre pelo Sallyport nega as ações enquanto ele estiver bloqueado. Esse é o comportamento desejado em uma máquina sem supervisão, em vez de deixar um token persistindo no ambiente do shell.

Use uma credencial separada para releases. Limite-a aos repositórios onde ela tem uma função e remova as permissões para administrar organizações, gerenciar webhooks, editar configurações do Actions ou escrever em repositórios sem relação. Aplicativos do GitHub costumam se encaixar melhor nesse modelo que o token pessoal de uma pessoa, porque a instalação e as permissões têm uma finalidade mais restrita. A escolha exata depende da configuração do seu repositório, mas um token compartilhado de mantenedor é uma identidade ruim para releases.

Não cole um token em uma instrução do agente, em um arquivo `.env` ou em um artefato de CI. A ofuscação não resolve o problema. Quando um processo consegue ler um segredo, muitas vezes também consegue inseri-lo em um campo de saída, no corpo de um release, em um nome de arquivo ou em uma solicitação para outro serviço. A prevenção começa por nunca entregar o segredo a esse processo.

## Rollback é uma decisão corretiva de release, não um botão de exclusão

Excluir um release do GitHub pode remover uma página, mas não recolhe arquivos já baixados, metadados em cache, tags clonadas, código-fonte espelhado nem uma implantação automatizada que já tenha sido acionada. Um agente de releases que trata a exclusão como um desfazer completo tornará um incidente pior de investigar.

Comece uma solicitação de rollback classificando a falha. Se o artefato estiver quebrado, mas não oferecer perigo, publique um release corrigido com uma nota clara e decida se o release anterior deve ser marcado como pré-release ou retirado da posição de mais recente. Se o artefato contiver um segredo, código malicioso ou uma vulnerabilidade grave, interrompa primeiro a distribuição, revogue as credenciais afetadas, entre em contato com os usuários pelos canais que você administra e preserve as evidências necessárias para a investigação.

Uma pessoa deve aprovar as ações de rollback separadamente da publicação porque as consequências são diferentes. O pedido deve explicar o que mudará e o que continuará visível. «Excluir o release v2.4.0» é vago. «Excluir o registro público e os artefatos do release v2.4.0; a tag v2.4.0 continua no SHA X; os downloads existentes não podem ser recolhidos» informa à pessoa que aprova o que ela está realmente autorizando.

Não permita que um agente exclua uma tag para deixar as notas do release mais organizadas. Outras builds e usuários podem depender das tags. Se precisar substituir uma tag, preserve o SHA antigo no registro do incidente e comunique a alteração. Mover uma tag de versão já publicada torna a verificação posterior muito mais difícil.

O padrão mais seguro é criar uma versão corretiva. Ela gera um caminho de auditoria limpo, permite que as ferramentas seguintes distingam o artefato corrigido e evita fingir que o primeiro release nunca existiu. A exclusão pode fazer sentido quando a publicação foi acidental e ninguém teve tempo razoável de consumi-la, mas isso é uma decisão operacional, não uma tarefa automática de limpeza.

## Um histórico de auditoria deve reconstruir a ação, não a história ao redor dela

Quando alguém pergunta quem publicou uma versão, «foi o agente» não é uma resposta. Você precisa identificar o processo do agente, a pessoa que aprovou a ação, a autoridade da credencial que a executou, os valores da solicitação e a resposta do GitHub.

Registre um evento para a sessão do agente e outro para cada operação de release. O registro da sessão responde quem iniciou a execução e quando ela perdeu autoridade. O registro da ação responde qual operação equivalente a um endpoint ocorreu e com quais valores resolvidos. Mantenha os segredos fora dos dois registros.

Para um evento de publicação, registre pelo menos o repositório, o identificador do rascunho, o identificador do release, a versão, o SHA de destino, a referência de origem fornecida pelo agente, os nomes e digests dos artefatos, as flags do release, o digest das notas, o horário da decisão, a identidade de quem aprovou, a identidade do processo, o código do resultado e o identificador da resposta. Inclua as falhas. Uma solicitação negada é uma evidência de que um limite funcionou.

O Sallyport projeta históricos de sessão e atividade a partir de um log de auditoria criptografado, encadeado por hash e sem possibilidade de leitura pelo sistema que grava. O comando `sp audit verify` verifica a cadeia offline sobre o texto cifrado sem precisar de um segredo do cofre. Essa propriedade é útil para evidências de release porque uma pessoa auditora pode verificar se os registros foram alterados sem receber o material da credencial.

Logs não substituem controles. Um log perfeito que registre um agente publicando o pacote errado fornece um post-mortem organizado e um release ruim. O log cumpre seu papel quando é combinado com ações restritas, identificadores fixos e uma aprovação que não continua válida depois que a solicitação muda.

## Um gate de release deve bloquear quando os fatos mudarem

O gate de release deve rejeitar ambiguidades, em vez de pedir que a pessoa aprovadora compense por elas. Se o destino do rascunho for diferente do SHA revisado, se o digest de um artefato for diferente do manifesto de build, se o rascunho não existir mais ou se a solicitação de release tiver mudado desde a aprovação, interrompa o processo e crie uma nova solicitação.

Esse comportamento pode parecer exigente durante a correria de um release. Ainda assim, custa menos que descobrir se uma tag foi movida entre o build e a publicação ou se um agente enviou um arquivo recriado depois que o revisor verificou o antigo. O trabalho de release se beneficia de um pouco de atrito exatamente neste ponto.

Teste o gate com falhas intencionais antes de confiar nele para um release estável. Peça ao agente para publicar um rascunho com um SHA divergente. Envie um artefato cujos bytes mudem depois do cálculo do checksum. Altere o título de um rascunho depois da aprovação. Tente excluir um release pela interface de preparação. Cada tentativa deve falhar com um registro específico que explique o motivo para a pessoa responsável pela operação.

Depois, estabeleça uma regra operacional fácil de lembrar: o agente prepara um candidato a release identificado, e uma pessoa aprova a alteração pública exata. Se sua automação atual não consegue informar naquele momento o repositório, o commit, os artefatos e o efeito do rollback, ela ainda não está pronta para publicar software sem supervisão.
