OPS61 — contratos de merge/flip do Forgejo: labels com PAT + gate do rollup checks + branch protection real #67

Merged
fsolla merged 4 commits from OPS61-forgejo-contracts-de-merge-flip-quebrados-labels-nao-f into main 2026-08-18 21:32:24 +00:00
Owner

O que é

OPS61 — contratos de merge/flip do Forgejo quebrados: labels não flipam e branch protection de main não existe no servidor.

S1 — labels não flipam (GITHUB_TOKEN 403)

  • issue-done-on-main-merge.yml / plan-issue-ready-on-main-merge.yml: env: FORGEJO_API_TOKEN (o GITHUB_TOKEN nativo 403 em escrita de Issues — o flip Closes #N → done+in-prod quebrava em silêncio).
  • Fork guard (head.repo.full_name == github.repository) nos dois: PR de fork mergeada faz checkout do script do fork rodando com o token do repo (RCE — mesma classe do guard do agent-pr-ready-automerge).
  • forgejo-issue-transition.mjs: falha de flip agora exit 1 — o job vermelha em vez de mentir (skip silencioso da era 403).

S3 — branch protection de main não existia + safety net com 3 bloqueios

  • GET /branch_protections retornava []: o pnpm configure:branch-protection era passo humano pendente do OPS50 e nunca rodou (docs diziam "aplicado").
  • O valor checks do script nunca casaria os contextos reais do Forgejo: a regra casa por glob contra CI (PR) / checks (pull_request) (o sufixo (evento) faz parte do contexto). Corrigido para CI (PR) / checks*, script idempotente (GET → POST/PATCH/no-op) com verificação pós-aplicação e dry-run honesto.
  • waitForChecks (2b, achado ao vivo na própria entrega): o CLI nunca auto-mergeou nada — todo merge Forgejo até aqui foi manual (merged_by do dono), inclusive a PR #52 com CI vermelho (narrativa de "raça" da intenção corrigida). Três bloqueios independentes, todos corrigidos:
    1. pending.length === 0 insatisfazível — o Forgejo posta o status do próprio job do safety net como pending durante o run inteiro; o gate novo espera o rollup CI (PR) / checks presente+verde (único contexto que só existe com a cascata inteira assentada) e ignora o próprio contexto.
    2. Merge POST com 409 PushRejected — o merge faz um push para main e o hook pre-receive do Forgejo rejeita quando o usuário do token não tem write no repo; o GITHUB_TOKEN nativo age como o usuário sistema do Actions (o mesmo que 403 em Issues). agent-pr-ready-automerge.yml agora injeta FORGEJO_API_TOKEN.
    3. mergeable === false prematuro — só conta como conflito após a cascata assentar (a regra recém-aplicada derruba o mergeable enquanto a CI roda).
  • Timeouts: CLI 30→45 min, workflow 40→55 min.
  • A regra no servidor é o gate real para todo mundo: o merge POST é bloqueado com 405 enquanto o contexto exigido não estiver verde — inclusive merges manuais via API.
  • Docs honestas (AGENT-OPS, agent-pr-workflow.mdc, CUTOVER-MAIN-ONLY, README).

Testes

  • forgejoApi.unit.spec.ts: rollup não-posto continua poll, rollup failure lança, próprio status do safety net não bloqueia, mergeable pré-settle; fixtures existentes atualizados para o contexto real.
  • branchProtection.unit.spec.ts (nova): create/update/noop + glob casa o contexto observado.
  • Gate local: lint/format/typecheck/knip/cycles/unit(2348)/int(791) verdes.

Validação ao vivo: a regra foi criada e verificada no servidor (re-run = no-op); esta PR Closes #53 mergeou pelo novo gate do rollup com a regra aplicada e o PAT no merge, e o issue-done flipou a #53 com o PAT.

Closes #53

## O que é OPS61 — contratos de merge/flip do Forgejo quebrados: labels não flipam e branch protection de main não existe no servidor. ### S1 — labels não flipam (GITHUB_TOKEN 403) - `issue-done-on-main-merge.yml` / `plan-issue-ready-on-main-merge.yml`: `env: FORGEJO_API_TOKEN` (o `GITHUB_TOKEN` nativo 403 em escrita de Issues — o flip `Closes #N → done+in-prod` quebrava em silêncio). - **Fork guard** (`head.repo.full_name == github.repository`) nos dois: PR de fork mergeada faz checkout do script do fork rodando com o token do repo (RCE — mesma classe do guard do `agent-pr-ready-automerge`). - `forgejo-issue-transition.mjs`: falha de flip agora **exit 1** — o job vermelha em vez de mentir (skip silencioso da era 403). ### S3 — branch protection de main não existia + safety net com 3 bloqueios - `GET /branch_protections` retornava `[]`: o `pnpm configure:branch-protection` era passo humano pendente do OPS50 e nunca rodou (docs diziam "aplicado"). - O valor `checks` do script **nunca casaria** os contextos reais do Forgejo: a regra casa por **glob** contra `CI (PR) / checks (pull_request)` (o sufixo ` (evento)` faz parte do contexto). Corrigido para `CI (PR) / checks*`, script idempotente (GET → POST/PATCH/no-op) com verificação pós-aplicação e dry-run honesto. - `waitForChecks` (2b, achado ao vivo na própria entrega): o CLI **nunca auto-mergeou nada** — todo merge Forgejo até aqui foi manual (`merged_by` do dono), inclusive a PR #52 com CI vermelho (narrativa de "raça" da intenção corrigida). Três bloqueios independentes, todos corrigidos: 1. **`pending.length === 0` insatisfazível** — o Forgejo posta o status do próprio job do safety net como `pending` durante o run inteiro; o gate novo espera o rollup `CI (PR) / checks` presente+verde (único contexto que só existe com a cascata inteira assentada) e ignora o próprio contexto. 2. **Merge POST com 409 PushRejected** — o merge faz um push para `main` e o hook pre-receive do Forgejo rejeita quando o usuário do token não tem write no repo; o `GITHUB_TOKEN` nativo age como o usuário sistema do Actions (o mesmo que 403 em Issues). `agent-pr-ready-automerge.yml` agora injeta `FORGEJO_API_TOKEN`. 3. **`mergeable === false` prematuro** — só conta como conflito após a cascata assentar (a regra recém-aplicada derruba o mergeable enquanto a CI roda). - Timeouts: CLI 30→45 min, workflow 40→55 min. - A regra no servidor é o gate real para todo mundo: o merge POST é bloqueado com 405 enquanto o contexto exigido não estiver verde — inclusive merges manuais via API. - Docs honestas (AGENT-OPS, agent-pr-workflow.mdc, CUTOVER-MAIN-ONLY, README). ## Testes - `forgejoApi.unit.spec.ts`: rollup não-posto continua poll, rollup failure lança, próprio status do safety net não bloqueia, mergeable pré-settle; fixtures existentes atualizados para o contexto real. - `branchProtection.unit.spec.ts` (nova): create/update/noop + glob casa o contexto observado. - Gate local: lint/format/typecheck/knip/cycles/unit(2348)/int(791) verdes. **Validação ao vivo:** a regra foi criada e verificada no servidor (re-run = no-op); esta PR `Closes #53` mergeou pelo novo gate do rollup com a regra aplicada e o PAT no merge, e o `issue-done` flipou a #53 com o PAT. Closes #53
fsolla added 1 commit 2026-08-18 19:44:40 +00:00
ops(OPS61): flip de issues pós-merge com PAT + gate do rollup checks + branch protection real no Forgejo
Some checks failed
CI (PR) / scope (pull_request) Successful in 33s
CI (PR) / lint (pull_request) Successful in 43s
CI (PR) / format (pull_request) Successful in 54s
CI (PR) / docs-guards (pull_request) Successful in 8s
CI (PR) / plans-only-closes (pull_request) Successful in 7s
CI (PR) / typecheck (pull_request) Successful in 34s
CI (PR) / knip (pull_request) Successful in 33s
CI (PR) / cycles (pull_request) Successful in 32s
CI (PR) / unit (pull_request) Successful in 58s
CI (PR) / int (pull_request) Successful in 2m5s
CI (PR) / build (pull_request) Has been skipped
CI (PR) / e2e (1) (pull_request) Has been skipped
CI (PR) / e2e (2) (pull_request) Has been skipped
CI (PR) / checks (pull_request) Successful in 2s
PR Ready + auto-merge / ready-automerge (pull_request) Failing after 31m47s
f077546599
- issue-done/plan-issue-ready: env FORGEJO_API_TOKEN (GITHUB_TOKEN 403 em
  Issues) + fork guard (checkout de fork roda script do fork com o PAT — RCE)
- forgejo-issue-transition: falha de flip vira exit 1 (job vermelho, nunca
  skip silencioso)
- waitForChecks: exige o rollup CI (PR) / checks presente+verde (raça PR #52:
  snapshot com jobs não-agendados parecia verde); mergeable=false só conta
  como conflito após a cascata assentar; timeouts 30→45min (CLI) e 40→55min
  (workflow)
- configure-branch-protection: contexto real CI (PR) / checks* (Forgejo casa
  por glob contra 'CI (PR) / checks (pull_request)'; literal 'checks' nunca
  casaria), idempotente GET→POST/PATCH, verificação pós-aplicação; decisão
  pura em scripts/lib/branch-protection.mjs
- docs honestas (AGENT-OPS, agent-pr-workflow.mdc, CUTOVER-MAIN-ONLY, README)
- testes: raça do rollup/rollup failure/mergeable pré-settle +
  branchProtection create/update/noop + glob real
fsolla added 1 commit 2026-08-18 20:07:14 +00:00
fix(OPS61): gate do waitForChecks sem o pending do próprio job — achado ao vivo PR #67
Some checks failed
Agent pool supervisor / tick (pull_request) Has been skipped
Main merge flips claimed issues to done + in-prod / issue-done (pull_request) Has been skipped
Promote plan-issue Related on main merge / plan-issue-ready (pull_request) Has been skipped
CI (PR) / scope (pull_request) Successful in 31s
CI (PR) / lint (pull_request) Successful in 41s
CI (PR) / docs-guards (pull_request) Successful in 8s
CI (PR) / plans-only-closes (pull_request) Successful in 7s
CI (PR) / format (pull_request) Successful in 50s
CI (PR) / typecheck (pull_request) Successful in 31s
CI (PR) / knip (pull_request) Successful in 30s
CI (PR) / cycles (pull_request) Successful in 30s
CI (PR) / unit (pull_request) Successful in 47s
CI (PR) / int (pull_request) Successful in 1m48s
CI (PR) / build (pull_request) Has been skipped
CI (PR) / e2e (1) (pull_request) Has been skipped
CI (PR) / e2e (2) (pull_request) Has been skipped
CI (PR) / checks (pull_request) Successful in 1s
PR Ready + auto-merge / ready-automerge (pull_request) Failing after 7m58s
404ac7ffe0
O Forgejo posta o status do próprio job do safety net como pending durante o
run inteiro: o gate antigo (pending.length === 0) era insatisfazível e o CLI
nunca auto-mergeou nada — todo merge Forgejo até aqui foi manual (merged_by
do dono), inclusive a PR #52 com CI vermelho (narrativa da 'raça' corrigida).
O gate é: rollup CI (PR) / checks presente+verde (cascata inteira assentou),
ignorando o contexto do próprio workflow; mergeable false só após assentar.
fsolla closed this pull request 2026-08-18 20:31:18 +00:00
fsolla reopened this pull request 2026-08-18 20:31:21 +00:00
fsolla force-pushed OPS61-forgejo-contracts-de-merge-flip-quebrados-labels-nao-f from 404ac7ffe0 to e34a964bff 2026-08-18 20:49:39 +00:00 Compare
fsolla added 1 commit 2026-08-18 21:10:54 +00:00
fix(OPS61): merge do safety net com FORGEJO_API_TOKEN — 409 PushRejected do hook pre-receive
Some checks are pending
CI (PR) / scope (pull_request) Successful in 35s
CI (PR) / lint (pull_request) Successful in 45s
CI (PR) / docs-guards (pull_request) Successful in 8s
CI (PR) / plans-only-closes (pull_request) Successful in 7s
CI (PR) / format (pull_request) Successful in 54s
CI (PR) / typecheck (pull_request) Successful in 31s
CI (PR) / knip (pull_request) Successful in 32s
CI (PR) / cycles (pull_request) Successful in 32s
CI (PR) / unit (pull_request) Successful in 55s
CI (PR) / int (pull_request) Successful in 2m46s
CI (PR) / build (pull_request) Has been skipped
CI (PR) / e2e (1) (pull_request) Has been skipped
CI (PR) / e2e (2) (pull_request) Has been skipped
CI (PR) / checks (pull_request) Successful in 1s
CI / deploy homeserver (teqo-1313) (push) Blocked by required conditions
CI / static (push) Waiting to run
CI / int (push) Waiting to run
CI / build (push) Waiting to run
CI / e2e (1) (push) Waiting to run
CI / e2e (2) (push) Waiting to run
CI / checks (push) Blocked by required conditions
PR Ready + auto-merge / ready-automerge (pull_request) Successful in 21m31s
Main merge flips claimed issues to done + in-prod / issue-done (pull_request) Successful in 12s
Promote plan-issue Related on main merge / plan-issue-ready (pull_request) Has been skipped
Agent pool supervisor / tick (pull_request) Successful in 28s
4f7de670f5
O merge POST faz um push para main; o hook pre-receive do Forgejo rejeita o
push quando o usuário do token não tem write no repo — o GITHUB_TOKEN nativo
age como o usuário sistema do Actions. Por isso nenhum auto-merge funcionou
(o CLI morria no 409; runs 'success' eram leituras de PR já mergeada
manualmente). O workflow do safety net agora injeta o mesmo PAT dos pós-merge.
fsolla merged commit 4f7de670f5 into main 2026-08-18 21:32:24 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: fsolla/teqo#67
No description provided.