iara-pwa/scripts/pr.mjs

78 lines
2.9 KiB
JavaScript

/**
* `bun run pr` — cria PR para `main` no GitHub (Ready, nunca draft) e,
* opcionalmente, arma o auto-merge nativo. Equivalente local do
* `gh pr create` + `gh pr merge --auto --rebase` do fluxo do teqo, sem
* depender do `gh` (plain Node zero-dep sobre a REST/GraphQL do GitHub).
*
* bun run pr -- --head <branch> [--title "…"] [--body "…"] [--automerge]
*
* Defaults: head = branch atual, base = main, title = primeiro commit, body vazio.
* Com `--automerge`, o PR nasce com o auto-merge armado (GraphQL, rebase) —
* o servidor mergea quando o required check `checks` ficar verde (sem poll
* local; a semântica "cria e mergea quando os checks passarem" é preservada
* pela garantia do servidor). `--draft` foi REMOVIDO — PR nunca draft é regra
* do repo (estrutural, como no teqo OPS71).
*/
import { execFileSync } from 'node:child_process'
import { dieWithLabel } from './lib/cli.mjs'
import { createApi } from './lib/github-api.mjs'
import { loadProjectEnv } from './lib/load-project-env.mjs'
loadProjectEnv()
const api = createApi({})
const die = dieWithLabel('pr')
const parseArgs = (argv, flagsWithValue) => {
const flags = {}
const positional = []
for (let index = 0; index < argv.length; index += 1) {
const arg = argv[index]
if (arg.startsWith('--')) {
const name = arg.slice(2)
if (flagsWithValue.has(name)) {
const next = argv[index + 1]
flags[name] = typeof next === 'string' && next.startsWith('--') ? undefined : next
index += 1
} else {
flags[name] = true
}
} else {
positional.push(arg)
}
}
return { flags, positional }
}
const currentBranch = () =>
execFileSync('git', ['branch', '--show-current'], { encoding: 'utf8' }).trim()
const firstCommitSubject = () =>
execFileSync('git', ['log', '-1', '--format=%s'], { encoding: 'utf8' }).trim()
const { flags, positional } = parseArgs(process.argv.slice(2), new Set(['head', 'title', 'body']))
const head = flags.head ?? positional[0] ?? currentBranch()
if (!head) die('Não consegui detectar a branch atual (detached?) — use --head <branch>.')
if (head === 'main') die('PR para main não faz sentido a partir de main.')
if (flags.draft) die('`--draft` foi removido — PR da Iara é sempre Ready (regra do repo).')
const title = flags.title ?? firstCommitSubject()
const body = flags.body ?? ''
console.log(`[pr] criando PR ${head} → main: ${title}`)
const pr = await api.createPullRequest({ head, base: 'main', title, body })
console.log(`[pr] PR #${pr.number} criado (Ready): ${pr.htmlUrl}`)
if (flags.automerge) {
try {
console.log(`[pr] armando auto-merge do PR #${pr.number} (rebase)…`)
await api.enableAutoMerge(pr.nodeId)
console.log(
`[pr] auto-merge armado — o GitHub mergea quando o required check "checks" ficar verde`,
)
} catch (error) {
console.error(`[pr] falhou ao armar auto-merge: ${error instanceof Error ? error.message : error}`)
process.exit(1)
}
}