Pular para conteúdo

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 (editar config.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 dind docker:dind expondo tcp://…:2375, runner com DOCKER_HOST=tcp://dind:2375): nada a fazer no runner — o ci-images.yml já aponta o docker do job pro daemon do DinD derivando o gateway default do container de job (DOCKER_HOST="tcp://$(ip route | awk '/default/{print $3}'):2375"). O nome dind (rede do Coolify) não resolve dentro do DinD; o gateway é a rota certa pro daemon que escuta em 0.0.0.0:2375.
  • Runner com socket do host (sem DinD): aí sim, no config.yaml do act_runner, montar o socket nos jobs:
    container:
      options: "-v /var/run/docker.sock:/var/run/docker.sock"
      valid_volumes: [/var/run/docker.sock]
    
    e reiniciar o runner.

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 TraefikentryPoints.https.transport.respondingTimeouts.{read,write,idle}Timeout=1800s no 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; secret REGISTRY_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:

  1. adicione a versão à matriz-baseline.json e dê push (toca ci-images/ → a fábrica builda e empurra a imagem);
  2. confirme a imagem no registry (Packages da org);
  3. só então o app aponta o container: e declara o toolchain no app.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-release bloqueia (e o /xadm-docs 3b avisa cedo) se o toolchain do app.json/.fvmrc não estiver na baseline — pega a versão não homologada antes da tag/deploy, não mais como manifest unknown vermelho no 1º release. Homologar aqui primeiro deixou de ser só convenção.

Verificação

  1. Rodar a fábrica manualmente (workflow_dispatch do ci-images) ou empurrar uma mudança em ci-images/.
  2. O job deve logar a matriz e push de cada imagem sem 499.
  3. Conferir no Forgejo (Packages da org) que ci-base, ci-java:<v>, ci-flutter:<v> aparecem.
  4. Num app, o container: da stack passa a resolver e o gate roda sem apt/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.