teqo-backup/scripts/github-pr-automerge.mjs
Francisco Solla 02c1e4f36b feat(OPS71): Fase 2 — remover arquivos do fluxo Forgejo (workflows/scripts/specs) pós-validação do GitHub Actions
14 arquivos removidos: .forgejo/workflows/* (6), forgejo-pr-automerge.mjs,
forgejo-dispatch.mjs, ci-classify-production.mjs, lib/dockerignore.mjs,
lib/branch-protection.mjs + 3 specs órfãs. Consumidores ajustados:
test-affected-core (HIGH_RISK_EXACT), ciSkipInvariants (re-ancorado no
deploy.yml dispatch-only — deploy nunca automático), comentários com
referência morta (gate-ci, github-pr-automerge, agent-pr-ready-automerge).
Docs: AGENTS.md, runbook (rollback via git history), README (era GitHub).
Tracker intocado (forgejo-api/agent-*/issue-transition ficam).
2026-08-20 00:20:10 +00:00

69 lines
2.6 KiB
JavaScript

/**
* Plain-Node CLI (no pnpm) — GitHub PR safety net: mark `cursor/*` drafts
* ready and arm GitHub's native auto-merge (rebase). Runs in
* .github/workflows/agent-pr-ready-automerge.yml with the built-in
* GITHUB_TOKEN (permissions: contents+pull-requests write).
*
* Unlike the Forgejo-era automerger (removed in OPS71 Fase 2), there is NO
* poll loop: `enablePullRequestAutoMerge` is server-side — GitHub only merges
* when every required check (incl. `CI (PR) / checks`) is green and the PR is
* mergeable. The OPS64 "never trust the rollup" pin is structural here: a
* single sequential job posts one honest check-run, and the server enforces
* it. Draft policy (OPS57) preserved: only `cursor/*` heads are marked
* ready — any other draft is the actor's veto (skip, exit 0).
*
* Idempotent: already merged / closed / non-main base → no-op success.
* A GraphQL error (e.g. repo auto-merge disabled, PR in conflict) exits 1 so
* the job goes red and the situation is visible.
*
* node scripts/github-pr-automerge.mjs --pr <N>
*/
import { createApi } from './lib/github-api.mjs'
import { decideAutomergeAction } from './lib/github-pr-flow.mjs'
const parseArgs = (argv) => {
const flags = {}
for (let index = 2; index < argv.length; index += 1) {
const arg = argv[index]
if (arg.startsWith('--')) {
const name = arg.slice(2)
const next = argv[index + 1]
flags[name] = typeof next === 'string' && !next.startsWith('--') ? next : true
if (typeof next === 'string' && !next.startsWith('--')) index += 1
}
}
return flags
}
const flags = parseArgs(process.argv)
const prNumber = Number(flags.pr)
if (!Number.isInteger(prNumber) || prNumber <= 0) {
console.error('Usage: node scripts/github-pr-automerge.mjs --pr <N>')
process.exit(1)
}
const api = createApi({})
try {
const pr = await api.getPullRequest(prNumber)
const verdict = decideAutomergeAction(pr)
if (verdict.action === 'skip') {
console.log(`[github-pr-automerge] PR #${prNumber}: skip (${verdict.reason})`)
process.exit(0)
}
if (verdict.action === 'mark-ready') {
console.log(`[github-pr-automerge] PR #${prNumber} é draft cursor/* — marcando Ready`)
await api.markPullRequestReady(prNumber)
}
console.log(`[github-pr-automerge] PR #${prNumber}: armando auto-merge (rebase)`)
await api.enableAutoMerge(pr.nodeId)
console.log(
`[github-pr-automerge] PR #${prNumber}: auto-merge armado — o GitHub mergea quando o required check "CI (PR) / checks" fica verde`,
)
} catch (error) {
console.error(`[github-pr-automerge] falhou: ${error instanceof Error ? error.message : error}`)
process.exit(1)
}