Some checks failed
CI (PR) / scope (pull_request) Successful in 33s
CI (PR) / lint (pull_request) Successful in 44s
CI (PR) / docs-guards (pull_request) Successful in 7s
CI (PR) / plans-only-closes (pull_request) Successful in 7s
CI (PR) / format (pull_request) Successful in 55s
CI (PR) / typecheck (pull_request) Successful in 31s
CI (PR) / knip (pull_request) Successful in 36s
CI (PR) / cycles (pull_request) Successful in 39s
CI (PR) / unit (pull_request) Successful in 59s
CI (PR) / int (pull_request) Successful in 2m23s
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) Failing after 1s
PR Ready + auto-merge / ready-automerge (pull_request) Failing after 50m5s
O sintoma primário da Issue (deadlock do waitForChecks no próprio pending) já tinha sido entregue pelo OPS61; o OPS64 fecha o secundário, que estava vivo e medido: o Forgejo 9.0.3 reporta o resultado do ÚLTIMO shard como o resultado do parent de matrix no contexto `needs` (runs 604/607/610: e2e (1) vermelho + e2e (2) verde → checks verde), e o `needs.<job>.results` do GitHub não existe neste runner. Com isso o gate do servidor (branch protection) e o deploy do ci.yml podiam passar com um shard vermelho. O rollup `checks` (ci-pr.yml e ci.yml) agora lê os statuses do commit via API (scripts/ci-rollup-check.mjs + lib pura, zero-dep, plain Node) — a mesma fonte que o waitForChecks confia — filtrando pelo prefixo do workflow, excluindo o próprio contexto e os downstreams legítimos (deploy, pending enquanto o rollup roda), falhando fechado em failure/error/pending/vazio. Fork guard + FORGEJO_API_TOKEN no job checks do ci-pr.yml (sem o guard, fork rodaria o script do head com o PAT — RCE classe OPS61); PRs de fork ficam não-mergeáveis no servidor (hardening). ci.yml usa --allow-empty em workflow_dispatch (evento não posta commit status). Testes: 12 specs do veredito (run 607/716 pinados, próprio pending ignorado, safety net ignorado, deploy ignorado, vazio fail-closed) + waitForChecks lança com rollup verde + shard vermelho. Unit 2360 verdes; gates locais ok.
72 lines
2.6 KiB
JavaScript
72 lines
2.6 KiB
JavaScript
/**
|
|
* Plain-Node CLI (no pnpm) — CI cascade rollup gate for the `checks` jobs of
|
|
* ci-pr.yml and ci.yml (OPS64).
|
|
*
|
|
* Reads the commit statuses of the head sha via the Forgejo API and fails when
|
|
* any of the workflow's own job statuses is failure/error (or the cascade
|
|
* never settles / the read comes back empty). Replaces the old
|
|
* `all(needs...)` jq, whose matrix parent result did not aggregate shards:
|
|
* Forgejo 9.0.3 reports the LAST shard's result, so `checks` could post
|
|
* SUCCESS with an e2e shard red (runs 604/607/610). The `needs.<job>.results`
|
|
* array of GitHub does not exist in this runner.
|
|
*
|
|
* The job still runs only after every cascade job finished (`needs` +
|
|
* `if: always()` in the workflow), so a green verdict means the whole cascade
|
|
* settled green — the commit statuses are the same source waitForChecks
|
|
* trusts for the merge.
|
|
*
|
|
* node scripts/ci-rollup-check.mjs \
|
|
* --sha <head-sha> \
|
|
* --prefix "CI (PR) / " \
|
|
* --own-prefix "CI (PR) / checks" \
|
|
* [--ignore-prefix "CI / deploy"] \
|
|
* [--allow-empty]
|
|
*/
|
|
|
|
import { rollupVerdict } from './lib/ci-rollup-check.mjs'
|
|
import { createApi } from './lib/forgejo-api.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 sha = flags.sha
|
|
const prefix = flags.prefix
|
|
const ownPrefix = flags['own-prefix']
|
|
const ignorePrefixes = [flags['ignore-prefix']].filter(Boolean)
|
|
const allowEmpty = flags['allow-empty'] === true || flags['allow-empty'] === 'true'
|
|
|
|
if (!sha || !prefix || !ownPrefix) {
|
|
console.error(
|
|
'Usage: node scripts/ci-rollup-check.mjs --sha <sha> --prefix <prefix> --own-prefix <own-prefix> [--ignore-prefix <prefix>] [--allow-empty]',
|
|
)
|
|
process.exit(1)
|
|
}
|
|
|
|
const api = createApi({})
|
|
try {
|
|
const statuses = await api.listCommitStatuses(sha)
|
|
const verdict = rollupVerdict(statuses, { prefix, ownPrefix, ignorePrefixes, allowEmpty })
|
|
if (!verdict.ok) {
|
|
console.error(`[ci-rollup-check] ${verdict.reason}`)
|
|
process.exit(1)
|
|
}
|
|
console.log(
|
|
`[ci-rollup-check] ${allowEmpty && statuses.length === 0 ? 'sem statuses (evento sem commit status) — ok' : 'cascata verde'}`,
|
|
)
|
|
process.exit(0)
|
|
} catch (error) {
|
|
console.error(`[ci-rollup-check] falhou: ${error instanceof Error ? error.message : error}`)
|
|
process.exit(1)
|
|
}
|