top of page

Mil execuções de build por mês — e nenhuma delas custa nada ⚙️

Foto do escritor: Marcel Dütscher
Marcel Dütscher
26 de jul.
4 min de leitura

Primeiro, uma correção. A primeira versão deste artigo afirmava que nossos minutos de build do GitHub tinham acabado e que isso nos forçou a migrar para uma conta Pro. Isso estava errado, de um jeito que uma olhada na documentação teria esclarecido: para repositórios públicos, os minutos de build do GitHub são gratuitos. Artefatos e caches também. Nosso repositório é público desde o fim de maio — então nunca pagamos por um minuto e nunca vamos pagar. Em vez de consertar o texto em silêncio, preferimos reescrevê-lo e contar o que as medições realmente mostraram. Isso acaba sendo muito mais interessante que a versão errada.


Primeiro o palpite, depois o olhar. O gatilho foi uma noite em que um pull request pronto estava no navegador e nenhuma verificação disparava. Nenhum tique verde, só silêncio. Fomos pela explicação óbvia — “cota esgotada” — e assinamos uma conta Pro. Depois disso tudo voltou a rodar, o que parecia confirmar a teoria. Não confirmava: o silêncio tinha outra causa (um pull request que o GitHub não consegue mesclar de forma limpa com a branch principal naquele momento não dispara nenhuma verificação). Desde então consultamos os dados de cobrança de cada execução. A resposta, para cada execução e cada sistema operacional: tempo cobrável = 0 milissegundos. Apoiar uma plataforma com uma assinatura é perfeitamente legítimo — mas, como explicação para este repositório, não se sustenta.


O que é verdade: a engrenagem cresceu. Cada pull request liga uma fabriquinha: o servidor inteiro é compilado e sua suíte de testes roda, o linter e a análise de código dão uma olhada, o CodeQL caça brechas de segurança e são geradas imagens Docker do servidor de jogo, do portal, do WorldHost e do backend de IA. Um release acrescenta builds do cliente para Windows, Linux e macOS, além da versão WebGL para o jogo no navegador. Desde o fim de maio isso soma 1.723 execuções de build, 1.092 delas só em julho — em 131 pull requests integrados em quatro semanas. E sim, o aumento recente tem mesmo a ver com a IA 😉: o projeto é desenvolvido 100% com ajuda de IA e, com a assinatura maior, simplesmente acontece mais coisa em paralelo. Só que a moeda não é dinheiro — é tempo de espera.


Para onde vai o tempo de espera. Medido ao longo de oito dias: a execução normal de verificações (CI) 379 minutos, a análise de segurança do CodeQL 230, os builds de release 126, o resto são trocados. Um único release custa cerca de 110 minutos de computação, divididos entre WebGL (31,6), a imagem Docker (19,4), macOS (13,7), Linux (13,7), o grande portão de testes (12,1), Windows (10,9) e empacotamento (7,2). Esse é o tempo entre “pronto” e “instalável para vocês”.


E agora o que realmente é escasso: o cache. Para que um build não comece do zero toda vez, o GitHub guarda resultados intermediários — e para isso você tem 10 GB por repositório, não importa o quão público seja. O nosso guarda hoje 5,3 GB em 63 entradas. O problema é a distribuição: cerca de dois terços são camadas intermediárias do Docker, reenviadas a cada execução — e elas expulsam justamente o que mais ajudaria. Esse é o verdadeiro gargalo, e nenhuma assinatura do mundo compra a saída dele.


A melhor descoberta foi um bug de verdade. Ao compilar, o Unity cria uma pasta intermediária enorme (Library) cujo reaproveitamento economiza minutos. A medição revelou: para Windows, Linux e macOS essa pasta nunca era salva — os builds tentavam restaurá-la direitinho, mas ninguém nunca a escrevia. E o build do Windows era o único com uma chave de cache sem marcador de plataforma. O resultado: ele baixava 1,7 GB de estado intermediário do WebGL, que o Unity então descartava obedientemente antes de reimportar tudo. O log mostra em preto e branco: 257 segundos de importação de assets em vez de 85 no caso quente. São quase nove minutos perdidos por release — porque faltava uma palavra numa chave.


O que mais apareceu. Nossa suíte de testes roda três vezes por commit entregue (no pull request, depois da mesclagem e de novo no release). O CodeQL verifica três linguagens em cada pull request, embora nem seja uma verificação obrigatória. Falta completamente um cache para os pacotes do .NET. Um emulador de arquiteturas de processador estrangeiras é configurado embora só compilemos para uma. E 7,4 GB de artefatos de build antigos ficam por aí com a retenção padrão de 90 dias. Nada disso é dramático — juntos, são um bom pedaço de vida útil.


A lição é a mesma que nosso servidor nos ensinou. Naquela época medimos que metade da memória ocupada nem ia para o jogo, mas para o Docker e o monitoramento. Desta vez foi ainda mais constrangedor: supusemos uma fatura que nunca existiu e pagamos antes de olhar. Meça, não chute — pelo visto, essa frase só vale até você tê-la realmente internalizado. O trabalho de limpeza está planejado, mas ainda não foi feito; quando rodar, contamos o que ele nos rendeu. 🚀

Posts recentes

Ver tudo

Comentários


Não é mais possível comentar esta publicação. Contate o proprietário do site para mais informações.
bottom of page