fix: split github contracts from script check

This commit is contained in:
Codex
2026-06-10 14:36:00 +00:00
parent 420a9a9e85
commit 4ee3a67089
12 changed files with 233 additions and 94 deletions
+51 -10
View File
@@ -19,6 +19,7 @@ const syntaxFiles = [
"scripts/platform-infra-sub2api-codex-routing-contract-test.ts",
"scripts/platform-infra-sub2api-codex-temp-unsched-contract-test.ts",
"scripts/platform-infra-sub2api-http-upstream-contract-test.ts",
"scripts/check-gh-contract-scope-contract-test.ts",
"scripts/src/playwright-cli.ts",
"scripts/src/check.ts",
"scripts/src/artifact-registry.ts",
@@ -86,6 +87,7 @@ export interface CheckOptions {
compose: boolean;
logs: boolean;
recoveryGuardrails: boolean;
ghContracts: boolean;
rust: boolean;
}
@@ -97,6 +99,7 @@ const defaultCheckOptions: CheckOptions = {
compose: false,
logs: false,
recoveryGuardrails: false,
ghContracts: false,
rust: false,
};
@@ -105,15 +108,16 @@ export function checkHelp(): Record<string, unknown> {
ok: true,
command: "check",
usage: [
"bun scripts/cli.ts check [--syntax-only|--full|--files|--scripts-typecheck|--components|--compose|--logs|--recovery-guardrails|--rust]",
"bun scripts/cli.ts check [--syntax-only|--full|--files|--scripts-typecheck|--gh-contracts|--components|--compose|--logs|--recovery-guardrails|--rust]",
"bun scripts/cli.ts check recovery-guardrails",
],
defaultMode: "syntax/config only; Rust is never compiled on the master server by default",
options: [
{ name: "--syntax-only|--basic", description: "Run only config validation, Bun version and TypeScript syntax transpile." },
{ name: "--full", description: "Enable all local checks except Rust compilation." },
{ name: "--full", description: "Enable all non-Rust checks, including explicit GitHub CLI contracts." },
{ name: "--files", description: "Verify required entrypoint files, including backend-core Cargo files." },
{ name: "--scripts-typecheck", description: "Run scripts TypeScript typecheck." },
{ name: "--gh-contracts", description: "Run slower GitHub CLI contract tests; intentionally separate from generic scripts typecheck." },
{ name: "--components", description: "Run component TypeScript typecheck." },
{ name: "--compose", description: "Render Docker Compose config." },
{ name: "--logs", description: "Check unified log rotation policy." },
@@ -143,10 +147,13 @@ export function parseCheckOptions(args: string[]): CheckOptions {
options.compose = true;
options.logs = true;
options.recoveryGuardrails = true;
options.ghContracts = true;
} else if (arg === "--files") {
options.files = true;
} else if (arg === "--scripts-typecheck") {
options.scriptsTypecheck = true;
} else if (arg === "--gh-contracts") {
options.ghContracts = true;
} else if (arg === "--components") {
options.components = true;
} else if (arg === "--compose") {
@@ -171,13 +178,29 @@ function fileItem(path: string): CheckItem {
return { name: `file:${path}`, ok: existsSync(absolute), detail: absolute };
}
function emitCheckProgress(detail: Record<string, unknown>): void {
console.error(JSON.stringify({ event: "unidesk.check.progress", ...detail }));
}
function commandItem(name: string, command: string[], timeoutMs = 30_000, env: NodeJS.ProcessEnv = process.env): CheckItem {
const startedAt = Date.now();
emitCheckProgress({ phase: "started", name, command, timeoutMs });
const result = runCommand(command, repoRoot, { timeoutMs, env });
const durationMs = Date.now() - startedAt;
emitCheckProgress({
phase: result.exitCode === 0 ? "succeeded" : "failed",
name,
durationMs,
exitCode: result.exitCode,
signal: result.signal,
timedOut: result.timedOut,
});
return {
name,
ok: result.exitCode === 0,
detail: {
command,
durationMs,
exitCode: result.exitCode,
signal: result.signal,
timedOut: result.timedOut,
@@ -312,7 +335,7 @@ export function runRecoveryGuardrailsCheck(config: UniDeskConfig): ReturnType<ty
return compactD601RecoveryGuardrails(runD601RecoveryGuardrails(config));
}
export function runChecks(config: UniDeskConfig, options: CheckOptions = defaultCheckOptions): { ok: boolean; mode: string; options: CheckOptions; items: CheckItem[] } {
export function runChecks(config: UniDeskConfig, options: CheckOptions = defaultCheckOptions): { ok: boolean; mode: string; options: CheckOptions; summary: { total: number; passed: number; failed: number; failedItems: string[] }; items: CheckItem[] } {
const items: CheckItem[] = [
{ name: "config:validated", ok: true, detail: { project: config.project.name, runtime: config.runtime } },
commandItem("bun:version", ["bun", "--version"]),
@@ -382,6 +405,7 @@ export function runChecks(config: UniDeskConfig, options: CheckOptions = default
fileItem("scripts/deploy-artifact-matrix-contract-test.ts"),
fileItem("scripts/decision-center-desired-state-contract-test.ts"),
fileItem("scripts/code-queue-prompt-observation-test.ts"),
fileItem("scripts/check-gh-contract-scope-contract-test.ts"),
fileItem("scripts/gh-cli-issue-guard-contract-test.ts"),
fileItem("scripts/gh-cli-pr-files-contract-test.ts"),
fileItem("scripts/gh-cli-pr-contract-test.ts"),
@@ -449,9 +473,7 @@ export function runChecks(config: UniDeskConfig, options: CheckOptions = default
items.push(commandItem("artifact-registry:direct-compose-dry-run-matrix", ["bun", "scripts/artifact-consumer-dry-run-matrix-test.ts"], 30_000));
items.push(commandItem("schedule:cli-contract", ["bun", "scripts/schedule-cli-contract-test.ts"], 30_000));
items.push(commandItem("server:cleanup-plan-contract", ["bun", "scripts/server-cleanup-plan-contract-test.ts"], 30_000));
items.push(commandItem("gh:issue-guard-contract", ["bun", "scripts/gh-cli-issue-guard-contract-test.ts"], 30_000));
items.push(commandItem("gh:pr-files-contract", ["bun", "scripts/gh-cli-pr-files-contract-test.ts"], 30_000));
items.push(commandItem("gh:pr-contract", ["bun", "scripts/gh-cli-pr-contract-test.ts"], 30_000));
items.push(commandItem("check:gh-contract-scope-contract", ["bun", "scripts/check-gh-contract-scope-contract-test.ts"], 30_000));
items.push(commandItem("playwright:cli-wrapper-contract", ["bun", "scripts/playwright-cli-contract-test.ts"], 30_000));
items.push(commandItem("platform-infra:sub2api-codex-local-config-contract", ["bun", "scripts/platform-infra-sub2api-codex-local-config-contract-test.ts"], 30_000));
items.push(commandItem("platform-infra:sub2api-codex-routing-contract", ["bun", "scripts/platform-infra-sub2api-codex-routing-contract-test.ts"], 30_000));
@@ -494,9 +516,7 @@ export function runChecks(config: UniDeskConfig, options: CheckOptions = default
items.push(skippedItem("artifact-registry:direct-compose-dry-run-matrix", "main-server direct artifact consumer dry-run matrix is opt-in with script checks", "--scripts-typecheck or --full"));
items.push(skippedItem("schedule:cli-contract", "Schedule CLI contract is opt-in with script checks", "--scripts-typecheck or --full"));
items.push(skippedItem("server:cleanup-plan-contract", "Server cleanup dry-run contract is opt-in with script checks", "--scripts-typecheck or --full"));
items.push(skippedItem("gh:issue-guard-contract", "GitHub issue CLI contract is opt-in with script checks", "--scripts-typecheck or --full"));
items.push(skippedItem("gh:pr-files-contract", "GitHub PR files/stat contract is opt-in with script checks", "--scripts-typecheck or --full"));
items.push(skippedItem("gh:pr-contract", "GitHub PR CLI contract is opt-in with script checks", "--scripts-typecheck or --full"));
items.push(skippedItem("check:gh-contract-scope-contract", "Check option scope contract is opt-in with script checks", "--scripts-typecheck or --full"));
items.push(skippedItem("playwright:cli-wrapper-contract", "Playwright wrapper/headless/session contract is opt-in with script checks", "--scripts-typecheck or --full"));
items.push(skippedItem("auth-broker:p0-contract", "Auth Broker P0 skeleton and CLI adapter contract is opt-in with script checks", "--scripts-typecheck or --full"));
items.push(skippedItem("d601:recovery-guardrails-contract", "D601 recovery guardrails fixture contract is opt-in with script checks", "--scripts-typecheck or --full"));
@@ -507,6 +527,15 @@ export function runChecks(config: UniDeskConfig, options: CheckOptions = default
} else {
items.push(skippedItem("logs:unified-hourly-rotation", "policy scan is opt-in", "--logs or --full"));
}
if (options.ghContracts) {
items.push(commandItem("gh:issue-guard-contract", ["bun", "scripts/gh-cli-issue-guard-contract-test.ts"], 30_000));
items.push(commandItem("gh:pr-files-contract", ["bun", "scripts/gh-cli-pr-files-contract-test.ts"], 30_000));
items.push(commandItem("gh:pr-contract", ["bun", "scripts/gh-cli-pr-contract-test.ts"], 30_000));
} else {
items.push(skippedItem("gh:issue-guard-contract", "GitHub issue CLI contract is opt-in because it can be slower than generic scripts typecheck", "--gh-contracts or --full"));
items.push(skippedItem("gh:pr-files-contract", "GitHub PR files/stat contract is opt-in because it can be slower than generic scripts typecheck", "--gh-contracts or --full"));
items.push(skippedItem("gh:pr-contract", "GitHub PR CLI contract is opt-in because it can be slower than generic scripts typecheck", "--gh-contracts or --full"));
}
if (options.recoveryGuardrails) {
const recovery = runRecoveryGuardrailsCheck(config);
items.push({
@@ -545,5 +574,17 @@ export function runChecks(config: UniDeskConfig, options: CheckOptions = default
} else {
items.push(skippedItem("rust:backend-core", "Rust check/build must run through an approved native k3s CI artifact publication, not on the master server or CD runtime target", "--rust inside native k3s CI with UNIDESK_NATIVE_K3S_RUST_CHECK=1"));
}
return { ok: items.every((item) => item.ok), mode: options.full ? "full" : "basic", options, items };
const failedItems = items.filter((item) => !item.ok).map((item) => item.name);
return {
ok: failedItems.length === 0,
mode: options.full ? "full" : "basic",
options,
summary: {
total: items.length,
passed: items.length - failedItems.length,
failed: failedItems.length,
failedItems,
},
items,
};
}