mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 23:45:18 +00:00
ci-pr.yml e ci.yml deixam de ter jobs irmãos: 1 job 'checks' com steps em série (guards → lint → format → typecheck → knip → cycles → unit → int → build → e2e). Step vermelho interrompe o job, o run falha e o slot é liberado — sem API de cancel (Forgejo 9.0.3 não tem), sem watchdog, sem upgrade do Forgejo. Skips do ci-scope.mjs viram step id 'scope'; e2e em 1 processo com PLAYWRIGHT_WORKERS=4 (substitui 2 shards × 2 workers); 2 services Postgres por run com portas host derivadas do run_id (runs concorrentes não colidem); contexto 'CI (PR) / checks' preservado (job id checks — contrato do automerger OPS61); deploy OPS53 gated em needs checks. Plumbing morto removido (e2eShardConfig/e2e_shards). Docs: AGENT-OPS, TESTING.md, changelog. Impl: docs/plans/ops62-ci-fail-fast-forgejo-impl.md (a intenção watchdog+upgrade fica como histórico do gate).
68 lines
1.8 KiB
JavaScript
68 lines
1.8 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* ci-scope — single classifier for PR step-level skips. Prints JSON:
|
|
* { base, code, build, test, e2e } where each of code/build/test/e2e is the
|
|
* classify* / selectE2eSpecs result. Used by the `scope` step (id: scope) in
|
|
* ci-pr.yml — its outputs drive `if:` on the heavy steps.
|
|
*
|
|
* Base ref: $GITHUB_BASE_REF (PR target) or origin/main locally.
|
|
*/
|
|
import { execFileSync } from 'node:child_process'
|
|
|
|
import { E2E_AFFECTED_MANIFEST } from './lib/e2e-affected-manifest.mjs'
|
|
import {
|
|
classifyBuildScope,
|
|
classifyStaticScope,
|
|
classifyTestScope,
|
|
selectE2eSpecs,
|
|
} from './lib/test-affected-core.mjs'
|
|
|
|
const base = `origin/${process.env.GITHUB_BASE_REF ?? 'main'}`
|
|
|
|
let mergeBase
|
|
try {
|
|
mergeBase = execFileSync('git', ['merge-base', 'HEAD', base], { encoding: 'utf8' }).trim()
|
|
} catch {
|
|
const full = {
|
|
mode: 'full',
|
|
reason: `no merge-base with ${base} (shallow clone?)`,
|
|
}
|
|
console.log(
|
|
JSON.stringify({
|
|
base,
|
|
code: { mode: 'code', reason: full.reason },
|
|
build: { mode: 'build', reason: full.reason },
|
|
test: { ...full },
|
|
e2e: { mode: 'full', specs: [], reason: full.reason, unmapped: [] },
|
|
}),
|
|
)
|
|
process.exit(0)
|
|
}
|
|
|
|
const raw = execFileSync('git', ['diff', '--name-status', `${mergeBase}...HEAD`], {
|
|
encoding: 'utf8',
|
|
})
|
|
const files = raw
|
|
.split('\n')
|
|
.filter(Boolean)
|
|
.map((line) => {
|
|
const [status, path] = line.split('\t')
|
|
return { status, path }
|
|
})
|
|
|
|
const e2e = selectE2eSpecs(files, E2E_AFFECTED_MANIFEST)
|
|
if (e2e.unmapped.length > 0) {
|
|
console.error(
|
|
`[ci-scope] src/ paths with no e2e manifest mapping:\n ${e2e.unmapped.join('\n ')}`,
|
|
)
|
|
}
|
|
|
|
console.log(
|
|
JSON.stringify({
|
|
base,
|
|
code: classifyStaticScope(files),
|
|
build: classifyBuildScope(files),
|
|
test: classifyTestScope(files),
|
|
e2e,
|
|
}),
|
|
)
|