13 KiB
| id | depends | serializes | priority | model | |||||
|---|---|---|---|---|---|---|---|---|---|
| OPS71 |
|
P1 | cursor-grok-4.5-high |
CI/PR do Forgejo Actions de volta para o GitHub Actions — tracker de Issues permanece no Forgejo
Status: rascunho Atualizado em: 2026-08-19 Issue: #97 Priority: P1 Model: cursor-grok-4.5-high Impeccable: A — N/A (sem UI) Rascunho UI: N/A — sem UI Appetite: ~2–3 dias eng; um outcome verificável (CI verde no GitHub, tracker vivo no Forgejo, deploy preservado) Responsável: —
Intenção
O Forgejo Runner roda na workstation (Ryzen 7 7800X3D) e está pedindo muito da máquina: a suíte inteira (build + int + e2e) roda localmente a cada PR e na janela de main, disputando CPU com o dev server, o Docker local, o browser e os worktrees paralelos. O OPS65 já tentou mitigar (janela de 30 min + matar o pool), mas o custo por PR continua pesado — e ele cresce com o número de PRs abertos, que é exatamente o que queremos aumentar.
A decisão: migrar o CI de volta para o GitHub Actions (runners hosted,
custo zero na workstation, um runner por PR — PRs avançam em paralelo de
verdade). O tracker de Issues permanece no Forgejo local (git.solla.dev,
já público via Cloudflare — confirmado HTTP 200 hoje): o CI no GitHub fala com
o tracker por API (FORGEJO_API_TOKEN + FORGEJO_API_URL), como os scripts
locais já fazem. Não é voltar ao mundo pré-OPS50 — é um novo meio-termo
deliberado: código/PR/CI no GitHub, Issues/labels no Forgejo.
Mantemos a estrutura de verificações construída nos OPS61/OPS62/OPS64
(job único checks sequencial, guards no início, skips de escopo via
ci-scope.mjs, rollup CI (PR) / checks como gate de merge) — o que muda é o
host onde ela roda. E a política de e2e muda junto (ver OPS72: e2e local
apenas para os testes afetados, não full no CI de PR). O deploy deixa de ser
automático (OPS53/OPS65 viram histórico): vira uma action manual
(workflow_dispatch) que roda todas as verificações full antes de
publicar — ver "Questões em aberto" (questão 1) e o fluxo abaixo.
Persona e fluxo
- Persona / contexto: o dono da máquina (dev/coordenador do repo) rodando dev local, worktrees e múltiplos PRs; os agentes (humanos e pool) que abrem PRs e acompanham o CI até o merge; o coordenador que dispara o deploy quando decide publicar.
- Job principal: cada PR custa ~0 da workstation; o CI roda no GitHub em paralelo para todos os PRs; o merge continua automático e seguro; publicar em produção é uma ação manual com verificação full.
- Fluxo desejado:
- Agente claima Issue no Forgejo (igual hoje — tracker intocado).
- Worktree/branch local;
pnpm pushpara o GitHub; PR aberto no GitHub (Ready, basemain,Closes #N). - GitHub Actions roda o job único
checks(mesma cascata de hoje, com e2e apenas nas áreas afetadas — OPS72) e posta o status no PR. - Merge automático quando o rollup
CI (PR) / checksfica verde (auto-merge nativo ou safety net equivalente). - Pós-merge: Issue flipada para
done/in-prodno Forgejo (workflow GitHub Actions → API do Forgejo);Related #Npromoveblocked→readyno Forgejo. - Deploy manual (workflow_dispatch): rodar verificações full → o job
deployexecutascripts/deploy-homeserver.shno homeserver (runner self-hosted lá, ou via SSH da workstation como fallback — questão 1).
- Anti-goals de produto: NÃO migrar o tracker (Issues/labels/claims ficam no Forgejo); NÃO re-introduzir jobs paralelos com matrix no CI (a estrutura de job único do OPS62 vale no GitHub também); NÃO tocar em schema/migrations de produto; NÃO re-publicar Vercel ou qualquer segundo deploy; deploy NÃO volta a ser automático a cada merge.
Objetivo e aceite
- O CI de PR (
ci-pr.yml) roda no GitHub Actions com a mesma cascata de verificações de hoje (guards → lint → format → typecheck → knip → cycles → unit → int → build → e2e selected/afetado, com skips de escopo), como um job únicochecks. - O deploy vira uma action manual (
workflow_dispatchno GitHub Actions) com dois jobs no mesmo workflow:verify(hostedubuntu-latest, suíte full incl. e2e full) →deploy(needs: [verify],runs-on: [self-hosted, homeserver]— runner do GitHub no homeserver executascripts/deploy-homeserver.shlocalmente, sem SSH). O hosted nunca toca o homeserver; o self-hosted não conta minutos hosted. Sem verificador de main (ci.yml) — só o pre-deploy roda full (decisão do usuário, gate 2026-08-19). - O rollup
CI (PR) / checkscontinua sendo o required check demaine o gate do merge automático (agora no GitHub). - PRs são abertas no GitHub; agentes acompanham o CI até o merge em
main(skills atualizadas — work-issue/agent-work-issue/execution-pipeline, AGENT-OPS, agent-pr-workflow). - As Issues não migram: labels, claims,
pnpm issue/agent:*continuam falando com o Forgejo; flips pós-merge funcionam via API (verificado: o Forgejo é alcançável publicamente). - A workstation não roda mais a suíte de CI; o Forgejo runner é desligado.
- Deploy manual com verificação full preservado (ver questão 1).
- Um repo GitHub sincronizado (histórico atual de
mainpresente — hoje o repo GitHub está parado em 2026-08-13).
Dados (intenção)
- Vou apresentar dados? Não.
- Decisões desbloqueadas: nenhuma KPI nova. (O "custo da workstation" é observável pela própria máquina; não precisa de métrica nova.)
Direção no codebase (hipótese)
- Áreas prováveis:
.github/workflows/(novo):ci-pr.yml(job únicochecks, e2e selected — OPS72),deploy.yml(workflow_dispatchmanual, dois jobs:verifyhosted full →deployruns-on: [self-hosted, homeserver]),agent-pr-ready-automerge.yml(safety net),issue-done-on-main-merge.yml,plan-issue-ready-on-main-merge.yml,archive-cursor-agent.yml. Semci.yml(verificador de main eliminado — decisão do gate).scripts/: adaptarforgejo-pr-automerge.mjs(ou substituir por auto-merge nativo do GitHub / APImerge_when_checks_succeed),forgejo-issue-transition.mjseagent-promote-related-on-merge.mjs(leem o PR — agora do GitHub — e flipam no Forgejo),forgejo-dispatch.mjs→gh workflow run(ou API GitHub), novos helpers GitHub (scripts/lib/);configure-branch-protection.mjs→ proteção no GitHub.scripts/deploy-homeserver.sh— revisar o modo de invocação (runner no homeserver: semssh, execução local; via workstation: SSH mantido) e oTEQO_REPO_URL(hojelocalhost:3000do Forgejo no homeserver — com o código no GitHub, apontar para o GitHub ou manter o espelho local)..agents/skills/**,.agents/rules/agent-pr-workflow.mdc,docs/AGENT-OPS.md,AGENTS.md— o paradigma de PR passa a apontar para o GitHub (PR/CI), tracker Forgejo.
- Precedente a olhar:
docs/plans/ops50-ci-github-para-forgejo.md(o espelho inverso — o que foi migrado para o Forgejo e como),ops62,ops65,ops61(branch protection/contratos de merge),docs/ops/teqo-1313-deploy.md, e o projetoinfra-solla(ver "Nota para o executor"). - Risco de acoplamento: o deploy (OPS53) hoje depende do runner local da
workstation (SSH para o homeserver) e o build de produção não pode sair do
homeserver (migrate no banco de prod antes do build — OPS66, estático na
rede do compose, registry local
localhost:5000). O GitHub hosted não alcança nada disso — por isso o jobdeployroda no runner self-hosted do homeserver (decisão do gate). Oci-classify-production.mjs(gate OPS65) morre com o deploy manual (sem janela automática) — pode ser removido ou reutilizado no dispatch como check informativo de "produção mudou desde o último deploy".
Nota para o executor — projeto infra-solla
Para detalhes do homeserver (stack, registry, tunel, runner, rede, ssh homeserver via tailnet), leia o projeto infra-solla (fora deste repo):
STATE.md e plano-infra-final.md §"Arquitetura de deploy". É a fonte usada
pelo OPS53 para corrigir a premissa de onde rodava o runner, e é onde o
passo manual "instalar o runner self-hosted do GitHub no homeserver" deve ser
registrado/anotado. Não invente topologia: confirme lá (homeserver 8c/16GB,
laptop; ~/stack/docker-compose.yml; registry localhost:5000 com htpasswd;
cloudflared; ssh homeserver pela tailnet) antes de decidir como o runner
self-hosted se instala e como o deploy.yml o alcança.
Dependências
- OPS72 (e2e local afetado + CI de PR sem e2e full) — serializa com este
item (ambos tocam
ci-pr.ymle a skill work-issue); OPS72 declaradepends: [OPS71]para rodar depois e evitar rebase cruzado. Decisão de gate: CI de PR mantém e2e selected (afetado) — confirmado. - #85 (OPS70, gate skipped no schedule do Forgejo) — absorvida: com o deploy manual, o gate de schedule deixa de existir; fechar como superada quando este item mergear.
- #87 (OPS70, guard de importMap) — independente, permanece na fila; o executor dela deve mirar os workflows novos do GitHub.
- #72 (S3-FOLLOWUP, e2e local
--no-depscolide no seedTestUser) — não é duplicada; o OPS72 (e2e local afetado) cita a limitação existente.
Fora de escopo
- Migrar Issues/labels do Forgejo (anti-goal explícito).
- Mudar a estrutura de verificações (job único, guards, skips) — preservada.
- Alterar o
e2e-affected/ci-scopeem si — mecânica já existe; só muda onde/quando roda (OPS72). - Repositório do Forgejo: continua como tracker; se virar mirror read-only de main ou parar de receber push — decisão do impl, mas nunca fecha o tracker.
- Upgrade do Forgejo no homeserver (decisão de infra separada).
Rabbit holes de produto
- Re-engenharia do deploy. O job
deploydependia do runner local; sem decisão, o "preservar deploy" vira um projeto de infra. Corte neste item: uma das opções da questão 1, fechada no gate, sem inventar terceiro caminho. - Reescrever o contrato de merge. Auto-merge do GitHub é nativo, mas o
wait-por-checks/rollup do OPS64 foi calibrado para o Forgejo; portar
errado = merge com CI vermelho. Corte: usar o mecanismo nativo do GitHub
(o rollup
CI (PR) / checksvira o required check lá) e pin unit-testado no script, sem reimplementar semáforos novos. - "Já que estamos no GitHub, migra as Issues também". O usuário foi explícito: tracker fica no Forgejo. Corte: qualquer proposta de migrar o tracker é rejeitada neste item.
Questões em aberto (produto)
- Como fica o deploy? Decisão do usuário (gate 2026-08-19): deploy
manual via
workflow_dispatchno GitHub Actions — não é mais automático a cada merge. O job de deploy roda todas as verificações full antes de publicar. Formato (confirmado): dois jobs no mesmodeploy.yml—verifyno hostedubuntu-latest(suíte full) edeploycomneeds: [verify]rodando em runner self-hosted do GitHub no homeserver (conecta outbound ao GitHub — funciona atrás do Cloudflare tunnel; o job executascripts/deploy-homeserver.shlocalmente, sem SSH; não conta minutos hosted). O build de produção não pode rodar fora do homeserver (migrate pré-build no banco de prod — OPS66, estático na rede do compose, registry locallocalhost:5000) — por isso o hosted só verifica e o self-hosted só build/deploy. Fallbacks registrados (não escolhidos): runner na workstation via SSH (B) ou runbook manual no homeserver (C). - E o ci.yml (verificador de main)? Decidido (gate 2026-08-19):
eliminar — fica só o pre-deploy (
verifydo dispatch manual) como verificação full. Motivo: custo mínimo de Actions; o deploy é deliberado e roda full na hora; se um dia o merge em main quiser rede de regressão, oci.ymlvolta com 1 linha de trigger (sem deploy). - Fatiamento do lote? Opções: A) OPS71 (este, CI+PR+merge+deploy) e
OPS72 (e2e local afetado) separados com
depends; B) um único item com tudo. Recomendação: A — cada um tem outcome verificável sozinho e o OPS72 (skill work-issue + ci-pr sem e2e full) é pequeno. (assumido — validar) - Repo GitHub defasado. Hoje parado em 2026-08-13 (pré-OPS50). Opções: A) re-sincronizar via push do estado local (histórico é ancestral comum — fast-forward limpo); B) import novo (histórico duplicado/PRs antigas órfãs). Recomendação: A. (assumido — validar)
Referências
- GitHub Issue: #97 (OPS71)
- Rascunho UI (gate): N/A
.forgejo/workflows/(a remover após cutover),docs/plans/ops50-ci-github-para-forgejo.md,docs/plans/ops62-ci-fail-fast-forgejo.md,docs/plans/ops65-ci-main-janela-30min-e-matar-pool.md,docs/plans/ops61-forgejo-contratos-merge-labels-e-branch-protection.md,scripts/forgejo-pr-automerge.mjs,scripts/forgejo-issue-transition.mjs,scripts/forgejo-dispatch.mjs,scripts/configure-branch-protection.mjs,scripts/ci-classify-production.mjs,docs/ops/teqo-1313-deploy.md