GitHub Actions ganha lockfile para travar o código executado no CI

Uma linha como uses: actions/checkout@v6 parece indicar exatamente qual código será executado pelo GitHub Actions. Ela não indica. v6 é uma tag, e tags podem passar a apontar para outro commit depois que o workflow foi revisado.

O GitHub anunciou em 14 de outubro o preview público dos workflow dependency lockfiles. A ideia é conhecida por quem já usa package-lock.json ou composer.lock: manter uma referência legível na configuração, mas registrar em outro arquivo a versão exata que deve ser usada.

O problema escondido atrás do @v3

Actions são blocos de código executados dentro de um workflow. Elas podem baixar dependências, compilar a aplicação, publicar um pacote ou fazer deploy. Dependendo das permissões configuradas, também podem receber segredos e usar o GITHUB_TOKEN do job.

steps:
  - uses: actions/checkout@v6
  - uses: octo-org/deploy-action@v3

Esse YAML fixa uma versão reconhecível para humanos, mas a resolução acontece quando o workflow roda. Se a tag v3 for movida, uma execução futura pode baixar outro commit sem que nenhuma linha tenha mudado no repositório consumidor. O mesmo risco existe ao apontar diretamente para uma branch como main.

Até agora, a recomendação mais segura do próprio GitHub era usar o SHA completo do commit. Isso torna a referência imutável, mas deixa o workflow menos legível e não resolve sozinho as dependências usadas internamente por uma Action composta.

O que o actions.lock registra

O novo arquivo fica em .github/workflows/actions.lock. Ele relaciona cada workflow adotado às suas dependências e registra, para cada referência, o commit resolvido. Também guarda os identificadores numéricos do proprietário e do repositório de origem.

  • ref: a referência escrita no workflow, como v3.1.0;
  • commit: o commit exato que será executado;
  • owner_id e repo_id: a identidade numérica da origem, usada para detectar se o nome passou a representar outro repositório.

Depois que um workflow entra no lockfile, todas as dependências externas dele precisam estar registradas. Na execução, o GitHub usa o commit travado mesmo que a tag ou a branch tenha mudado. A checagem de políticas de Actions também passa a considerar esse commit.

A cobertura inclui Actions transitivas e chamadas a workflows reutilizáveis. Existe uma divisão importante: o repositório chamador trava a referência do workflow reutilizável, enquanto as dependências internas dele são responsabilidade do lockfile existente no repositório onde esse workflow foi definido.

A adoção começa pela extensão do GitHub CLI

O arquivo não deve ser escrito à mão. O GitHub fornece a extensão gh-actions-lock para examinar os workflows, resolver as referências e gerar as entradas necessárias.

gh extension install github/gh-actions-lock
gh actions-lock

Executado na raiz do repositório, o segundo comando examina os arquivos em .github/workflows/. Também é possível passar o caminho de um único workflow e fazer a adoção aos poucos. A ferramenta pode tornar referências amplas mais específicas no YAML, então a revisão precisa considerar o diff completo, não apenas o arquivo de lock.

Quando uma Action é adicionada ou removida, o comando deve ser executado novamente. Para equipes que usam atualizações de versão do Dependabot no ecossistema github-actions, o bot passa a atualizar a entrada correspondente do lockfile no mesmo pull request. Ele mantém workflows já adotados, mas não coloca novos workflows sob o lock automaticamente.

Uma tag movida deixa de ser uma atualização silenciosa

Há uma diferença útil entre atualizar uma dependência e simplesmente resolver de novo tudo o que estiver escrito como @v3. Em uma execução normal da ferramenta, referências móveis continuam confiando no commit já registrado. Se uma tag passou a apontar para outro lugar, é preciso examinar a mudança antes de aceitar o novo destino.

O comando gh actions-lock --relock tenta resolver novamente as referências. Quando detecta uma tag movida, ainda exige uma decisão adicional com --accept-moved. Esse atrito é proposital: uma alteração que antes poderia chegar escondida na próxima execução passa a aparecer como uma mudança revisável.

Lockfile não transforma dependência ruim em dependência segura

O mecanismo garante identidade e repetibilidade. Ele não analisa o comportamento do código. Se a equipe travar um commit malicioso, vulnerável ou excessivamente permissivo, o lockfile apenas fará esse mesmo código continuar rodando de forma previsível.

A revisão da origem, das permissões do GITHUB_TOKEN, dos segredos entregues ao job e das mudanças propostas continua necessária. Também é preciso manter uma rotina de atualização: dependência imutável demais pode preservar uma vulnerabilidade já corrigida.

Como o recurso ainda está em preview público, formato, comandos e limitações podem mudar. Mesmo assim, ele resolve uma lacuna concreta: permite que o workflow continue dizendo “use a versão 3” para quem lê, enquanto a plataforma executa exatamente o commit que passou pela revisão.

Fontes