Eu realmente odeio o GitHub Actions
(xlii.space)- Compartilhamento da experiência frustrante de um desenvolvedor com o GitHub Actions, devido ao loop de feedback lento e ao processo complexo de depuração
- No projeto tmplr, a documentação era gerada com CUE via
build.rs, mas o problema começou quando o build de CI falhou - Entre 4 plataformas, apenas o Linux ARM falhava no build; a causa era o modo como o GitHub Actions esconde binários x86_64 em runners arm64 durante cross builds
- Repetição de um loop de feedback ineficiente, levando 2–3 minutos para testar uma única alteração
- Como solução,
build.rsfoi removido e houve migração para um GNU Makefile, resolvendo o problema ao controlar diretamente a lógica de CI
Contexto do problema
- tmplr é uma ferramenta de scaffolding de arquivos/projetos que usa arquivos de template legíveis e editáveis por humanos
- Em
build.rs, o CUE era usado para gerarREADME.md,CHANGELOG.mde arquivos de versão/ajuda, garantindo consistência - O trabalho em si foi concluído em cerca de 1,5 hora, e o artigo relacionado também já havia sido escrito
- Funcionava normalmente em ambiente local, mas no ambiente de CI do GitHub Actions o build falhou porque o binário do CUE não estava instalado
Causa da falha do build
- Entre 4 plataformas (Linux ARM, macOS ARM, Linux x86_64, macOS x86_64), apenas o Linux ARM apresentava erro de “command not found”
- Causa: o cross build com matrix é fortemente isolado, então o CUE era instalado apenas no host Linux x86_64 e no host macOS ARM
- No macOS, não havia problema para executar binários x86_64
- No Linux x86_64, também não havia problema para executar binários x86_64
- Porém, no GitHub Actions, binários x86_64 são escondidos em runners arm64, tornando sua execução impossível
Loop de feedback ineficiente
- Processo repetido para resolver o problema:
1. Pesquisar formas possíveis de corrigir
2. Alterarci.yml
3. Fazer commit e push (jj squash --ignore-immutable && jj git push)
4. Abrir a aba "Actions"
5. Abrir a execução mais recente
6. Abrir a execução de Linux ARM
7. Esperar alguns segundos
8. Frustrar-se
9. Repetir - 2–3 minutos gastos por alteração individual
- Idealmente, o GitHub poderia oferecer um runner local completo, ou então uma forma de verificar rapidamente o andamento após o push
- Algo como um recurso de "scratch commit": uma maneira de testar várias execuções sem poluir o histórico do Git nem o registro das execuções do Actions
- Porém, atualmente esse tipo de recurso não existe
Solução
- Após repetir o loop por 30 minutos, houve uma pausa
- Foi aplicada uma abordagem já conhecida na internet: "não deixar o GitHub Actions gerenciar a lógica; controlar o script diretamente e fazer com que o Actions apenas o chame"
build.rsfoi removido (foi uma pena, mas algum sacrifício era necessário)- Todo o trabalho de geração foi movido para um GNU Makefile
- Os arquivos gerados foram commitados no repositório, e as mudanças de CI foram revertidas
- Problema resolvido
Conclusão
- O GitHub Actions é a razão pela qual algumas coisas boas deixam de ser possíveis
- Muito tempo é desperdiçado depurando runners ou otimizando o processo de build
- Ainda assim, há vantagens difíceis de obter por outros meios, como builds para macOS
- E, claro, não se conhece outro sistema que seja mais fácil de configurar do que o GitHub Actions
We are all doomed to GitHub Actions. …but at least I dodged the bullet early.
3 comentários
O GitHub Actions deveria fazer apenas setup de ambiente (SO, toolchain de build, …) e executar scripts (
shell, Python,bat,ps1…). Mesmo que o GitHub caia, se o ambiente estiver pronto, deveria ser possível fazer o build em qualquer lugar. Quando vejo os workflows do GitHub Actions hoje em dia, fico pensando se realmente precisa ir atrás e usar até esse tipo de coisa. Há muito tempo atrás (?) o Ansible foi por esse caminho e acabou fracassando.Comentários do Hacker News
O principal problema do GitHub Actions é que o loop de feedback é lento demais
É realmente frustrante ter que dar push e esperar só para confirmar uma falha simples
Acho melhor separar as tarefas de CI em scripts que possam ser executados localmente e usar os recursos do Actions apenas como melhoria incremental
A combinação de
workflow_dispatchegh workflow runtambém é razoável, mas é inconveniente que o segundo não forneça diretamente a URL do workflow executadoFoi bastante bem-sucedido para obter feedback rápido
Se surgir algum problema, dá para depurar em um estado quase idêntico ao ambiente do GitHub Actions
Isso deveria ser um requisito básico de qualquer sistema de CI
No fim, o que importa são recursos como enfileiramento, análise de saída e telemetria do histórico de builds
gh workflow run, para obter a URL eu tinha que consultar de novo a lista de execuções do workflow pela API do GitHubSe houver várias execuções ao mesmo tempo, isso pode dar errado, mas por enquanto tem funcionado mais ou menos bem
Fiz um resumo de dicas de design para CI
Um shell simples deveria bastar
É bom definir alvos de CI no
Makefilee chamá-los de forma simples, comomake ci-testDesde então, gerencio todo o CI com wrappers simples como
make buildSeria bom poder separá-las com marcadores como
BeginStep("Step Name")O problema não é tanto o GitHub Actions em si, mas a automação mal feita construída em cima dele
A lógica deveria ser transformada em scripts numa linguagem como Python, para que também pudesse ser executada localmente
Você precisa modificar o workflow, dar push e esperar toda vez
Eu faço todo o CI dentro de contêineres
A plataforma de CI só executa esse contêiner, então dá para rodar a mesma coisa localmente
As plataformas não gostam dessa abordagem, porque ela quebra o vendor lock-in
Quando falha, dá para entrar por SSH imediatamente para depurar, e também é possível alterar o manifesto e reexecutar sem dar push em uma branch
Mas ele exige self-hosting
A padronização fica mais fácil, mas surge o trade-off de manter essa imagem
Na prática, quase não existe lock-in, mas as pessoas caem em cargo cult de CI/CD
Eu gosto do GitHub Actions
É melhor do que o Travis que eu usava antes e, para projetos OSS, é muito útil como recurso gratuito
Depois que adotei Nix, a reprodutibilidade do ambiente melhorou bastante, e a combinação com o Actions ficou muito melhor
Dá para executar no Actions o mesmo contêiner criado com flake
Projeto de exemplo
Acho que o GitHub Actions deveria ser apenas uma estrutura para chamar scripts bash ou python
O bash tem muitas limitações, Python é mais flexível e também é fácil de executar localmente
O ideal é algo como este artigo, que instala o uv automaticamente e gerencia dependências
É mais complexo que bash, mas no ambiente do Actions isso não traz grande problema de desempenho
O maior problema do Actions é a forma como ele é vendido como algo para combinar workflows
Depurar é quase impossível, e configurar cache é complicado, o que deixa os builds lentos
Por isso, a ideia de executar diretamente em VMs persistentes parece atraente
Sou fundador da Depot
Opero um serviço que oferece runners do GitHub Actions mais rápidos e baratos
Muitas das reclamações que as pessoas sentem refletem de fato a opinião da maioria
O sistema do Actions é estruturalmente ineficiente, e toda semana descobrimos um novo gargalo
Tenho convicção de que existe uma forma melhor, e estamos experimentando isso
Mais detalhes em depot.dev
No fim de semana passado, criei uma ferramenta chamada
gg watch actionEla encontra a action mais recente ou em execução da branch atual
Link no GitHub
gh”Mas havia um bug em que o repositório não aparecia no comando
gg tuiFiquei me perguntando se uma ferramenta como
actajudarianektos/act
Por diferenças de arquitetura, a execução local e a online podem divergir, mas ainda assim parece útil
Havia cerca de 80% de compatibilidade
O SourceHut suporta isso, e é realmente muito conveniente
Parece ser um problema inevitável por causa da estrutura em que é preciso colocar a lógica dentro do YAML.
O texto acima parece ter dado mais ou menos a resposta abaixo, e fico pensando se substituir a parte dos scripts por Dagger não seria justamente a solução correta.
"Não deixe o GitHub Actions gerenciar a lógica; controle os scripts diretamente e faça com que o Actions apenas invoque esses scripts"