Runbook — fábrica de imagens de CI rodando sozinha¶
Como deixar a fábrica de imagens de CI
(ci-images/ + .forgejo/workflows/ci-images.yml) autônoma: o workflow builda e
empurra as imagens no schedule/push sem bootstrap manual. Três peças de infra, uma vez.
Quando usar¶
Uma vez, ao ligar a fábrica (e ao trocar de servidor/runner). Sem isto, o workflow roda
mas falha no build ou no push — e o container: dos apps não resolve.
Pré-requisitos¶
- Acesso ao host do
act_runner(editarconfig.yaml,/etc/docker/daemon.json). - Admin no Forgejo da org (criar token de pacote, secrets/vars da org).
- O runner e o Forgejo na mesma rede Docker (para o push interno).
Passos¶
1. Runner consegue buildar imagem (daemon do Docker)¶
O job precisa de um daemon Docker para o docker build/push. Depende de como
o runner foi montado — confira o compose do act_runner:
- Runner com DinD (o caso da xadm: serviço
dinddocker:dindexpondotcp://…:2375, runner comDOCKER_HOST=tcp://dind:2375): nada a fazer no runner — oci-images.ymljá aponta odockerdo job pro daemon do DinD derivando o gateway default do container de job (DOCKER_HOST="tcp://$(ip route | awk '/default/{print $3}'):2375"). O nomedind(rede do Coolify) não resolve dentro do DinD; o gateway é a rota certa pro daemon que escuta em0.0.0.0:2375. - Runner com socket do host (sem DinD): aí sim, no
config.yamldoact_runner, montar o socket nos jobs:e reiniciar o runner.container: options: "-v /var/run/docker.sock:/var/run/docker.sock" valid_volumes: [/var/run/docker.sock]
Pegadinha (jun/2026): o job tem o docker CLI (apt), mas sem daemon o build dá
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Não é falta do CLI — é o CLI sem destino. Com DinD, o destino é o gateway (acima).
2. Push pelo endereço interno (dribla o Traefik / 499)¶
O push da imagem (Flutter é multi-GB) pelo HTTPS público estoura o respondingTimeout
do Traefik → 499. Empurrar pelo hostname interno do Forgejo (mesma rede Docker)
evita o proxy. Como é HTTP interno, o daemon do host precisa confiar nele —
/etc/docker/daemon.json:
{ "insecure-registries": ["forgejo:3000"] }
(troque forgejo:3000 pelo service-name:porta reais do Forgejo na rede). Reiniciar o
Docker. Os apps continuam puxando de fonte.xadm.biz/xadm/... — é o mesmo backend, o
host no tag é só rota; o push interno e o pull público apontam para o mesmo pacote.
Alternativa (sem
insecure-registries): manter o push público e afrouxar o Traefik —entryPoints.https.transport.respondingTimeouts.{read,write,idle}Timeout=1800sno proxy do Coolify. HTTPS "correto", mas push lento e timeout tem que ser generoso.
3. Token e variáveis na org (Forgejo)¶
- Token: Forgejo → Settings → Applications → novo token com escopo
write:package. - Na organização xadm do Forgejo, cadastrar:
- secret
REGISTRY_TOKEN= o token; secretREGISTRY_USER= o usuário dono do token; - variable
CI_REGISTRY_HOST=forgejo:3000(o interno do passo 2);CI_REGISTRY_OWNER=xadm.
(A fábrica não lê o bucket — a fonte das versões é a ci-images/matriz-baseline.json,
não os app.json; correção 2026-06-25 na decisão 0003.
Logo, DOCS_S3_* não são necessários aqui.)
Adotar uma versão de stack nova¶
A fábrica builda só o que está na ci-images/matriz-baseline.json. Para um app
usar ci-java:<v>/ci-flutter:<v> nova:
- adicione a versão à
matriz-baseline.jsone dê push (tocaci-images/→ a fábrica builda e empurra a imagem); - confirme a imagem no registry (Packages da org);
- só então o app aponta o
container:e declara otoolchainnoapp.json.
Inverter a ordem (app aponta antes da imagem existir) = pull falha / deadlock de bootstrap — foi o que travou o 1º app Flutter version-pinned.
Gate que enforça a ordem (2026-07-04). A baseline é publicada em
https://docs.xadm.biz/toolchain/matriz-baseline.json. No repo do app, o pré-flight do/xadm-releasebloqueia (e o/xadm-docs3b avisa cedo) se otoolchaindoapp.json/.fvmrcnão estiver na baseline — pega a versão não homologada antes da tag/deploy, não mais comomanifest unknownvermelho no 1º release. Homologar aqui primeiro deixou de ser só convenção.
Verificação¶
- Rodar a fábrica manualmente (
workflow_dispatchdoci-images) ou empurrar uma mudança emci-images/. - O job deve logar a matriz e
pushde cada imagem sem 499. - Conferir no Forgejo (Packages da org) que
ci-base,ci-java:<v>,ci-flutter:<v>aparecem. - Num app, o
container:da stack passa a resolver e o gate roda semapt/git-clone.
Reversão¶
Remover o socket do config.yaml do runner (e insecure-registries, se incomodar) volta ao
estado anterior — a fábrica para de publicar, mas nada quebra além disso. As imagens já
empurradas seguem no registry.