mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-16 13:03:31 +08:00
Pull requests need a deterministic way to show changed areas, required checks, missing-test signals, and CLI-core risk before review. This adds a path-based policy gate, local impact reporting, PR triage labels/comments, and reusable check scripts so reviewers can evaluate blast radius without trusting contributor claims. Constraint: CLI core should remain effectively frozen unless a maintainer explicitly overrides it. Constraint: Default PR checks must be safe for external forks and avoid live model/provider calls. Rejected: Run live provider tests on every PR | secrets, cost, network, and vendor instability would make the gate noisy and unsafe. Rejected: Use Dosu as the merge gate | AI review is useful for risk explanation, but deterministic Actions must own blocking checks. Confidence: high Scope-risk: moderate Directive: Keep real model/provider smoke tests in maintainer-controlled workflows; do not make them required for untrusted PRs. Tested: bun run check:impact Tested: bun run check:policy Tested: ruby YAML parse for PR workflows Tested: git diff --check Tested: bun run check:native Tested: npm run docs:build Tested: bun run scripts/pr/run-server-tests.ts Tested: bun run check:adapters Tested: bun run check:desktop Not-tested: GitHub-hosted pull_request_target label/comment execution before opening this PR
61 lines
1.5 KiB
TypeScript
61 lines
1.5 KiB
TypeScript
#!/usr/bin/env bun
|
|
|
|
import { readdirSync, statSync } from 'node:fs'
|
|
import { join, relative, sep } from 'node:path'
|
|
|
|
const root = process.cwd()
|
|
const roots = ['src/server', 'src/tools', 'src/utils']
|
|
const excludedFiles = new Set([
|
|
// These suites are not stable enough for the default PR gate yet. Keep them
|
|
// out of CI until they are fixed or moved to a maintainer-only workflow.
|
|
'src/server/__tests__/cron-scheduler.test.ts',
|
|
'src/server/__tests__/providers-real.test.ts',
|
|
'src/server/__tests__/tasks.test.ts',
|
|
'src/server/__tests__/e2e/business-flow.test.ts',
|
|
'src/server/__tests__/e2e/full-flow.test.ts',
|
|
])
|
|
|
|
function normalize(path: string) {
|
|
return relative(root, path).split(sep).join('/')
|
|
}
|
|
|
|
function walk(path: string, files: string[]) {
|
|
const stat = statSync(path)
|
|
|
|
if (stat.isDirectory()) {
|
|
for (const entry of readdirSync(path)) {
|
|
walk(join(path, entry), files)
|
|
}
|
|
return
|
|
}
|
|
|
|
if (!stat.isFile()) {
|
|
return
|
|
}
|
|
|
|
const normalized = normalize(path)
|
|
if (normalized.endsWith('.test.ts') && !excludedFiles.has(normalized)) {
|
|
files.push(normalized)
|
|
}
|
|
}
|
|
|
|
const testFiles: string[] = []
|
|
for (const testRoot of roots) {
|
|
walk(join(root, testRoot), testFiles)
|
|
}
|
|
|
|
testFiles.sort()
|
|
|
|
if (testFiles.length === 0) {
|
|
console.log('No server-side test files found.')
|
|
process.exit(0)
|
|
}
|
|
|
|
const proc = Bun.spawn(['bun', 'test', ...testFiles], {
|
|
cwd: root,
|
|
stdout: 'inherit',
|
|
stderr: 'inherit',
|
|
})
|
|
|
|
process.exit(await proc.exited)
|