Files
wehub-resource-sync 426e9eeabd
Voice Workbench / headless workbench (mocked backends) (push) Has been cancelled
Voice Workbench / real acoustic lane (nightly, provisioned only) (push) Has been cancelled
ci / test (push) Has been cancelled
ci / lint-and-format (push) Has been cancelled
ci / build (push) Has been cancelled
ci / dev-startup (push) Has been cancelled
gitleaks / gitleaks (push) Has been cancelled
Markdown Links / Relative Markdown Links (push) Has been cancelled
Quality (Extended) / Homepage Build (PR smoke) (push) Has been cancelled
Quality (Extended) / Comment-only diff guard (push) Has been cancelled
Quality (Extended) / Format + Type Safety Ratchet (push) Has been cancelled
Quality (Extended) / Develop Gate (secret scan + UI determinism) (push) Has been cancelled
Quality (Extended) / Develop Gate (lint) (push) Has been cancelled
Chat shell gestures / Chat shell gesture + parity e2e (push) Has been cancelled
Cloud Gateway Discord / Test (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Has been cancelled
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Has been cancelled
Build Agent Image / build-and-push (push) Has been cancelled
Dev Smoke / bun run dev onboarding chat (push) Has been cancelled
Dev Smoke / Vite HMR dependency-level smoke (push) Has been cancelled
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Has been cancelled
Publish @elizaos/example-code / check_npm (push) Has been cancelled
Publish @elizaos/example-code / publish_npm (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / verify_version (push) Has been cancelled
Publish @elizaos/plugin-elizacloud / publish_npm (push) Has been cancelled
Sandbox Live Smoke / Sandbox live smoke (push) Has been cancelled
Snap Build & Test / Build Snap (amd64) (push) Has been cancelled
Snap Build & Test / Build Snap (arm64) (push) Has been cancelled
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Has been cancelled
Cloud Gateway Webhook / Test (push) Has been cancelled
Cloud Tests / lint-and-types (push) Has been cancelled
Cloud Tests / unit-tests (push) Has been cancelled
Cloud Tests / integration-tests (push) Has been cancelled
Cloud Tests / e2e-tests (push) Has been cancelled
CodeQL Advanced / Analyze (javascript-typescript) (push) Has been cancelled
Deploy Apps Worker (Product 2) / Determine environment (push) Has been cancelled
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Has been cancelled
Deploy Eliza Provisioning Worker / Determine environment (push) Has been cancelled
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Has been cancelled
Dev Smoke / Classify changed paths (push) Has been cancelled
supply-chain / sbom (push) Has been cancelled
supply-chain / vulnerability-scan (push) Has been cancelled
Build, Push & Deploy to Phala Cloud / build-and-push (push) Has been cancelled
Test Packaging / Validate Packaging Configs (push) Has been cancelled
Test Packaging / Build & Test PyPI Package (push) Has been cancelled
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Has been cancelled
Test Packaging / Pack & Test JS Tarballs (push) Has been cancelled
UI Fixture E2E / ui-fixture-e2e (push) Has been cancelled
UI Fixture E2E / fixture-e2e (push) Has been cancelled
UI Story Gate / story-gate (push) Has been cancelled
vault-ci / test (macos-latest) (push) Has been cancelled
vault-ci / test (ubuntu-latest) (push) Has been cancelled
vault-ci / test (windows-latest) (push) Has been cancelled
vault-ci / app-core wiring tests (push) Has been cancelled
verify-patches / verify patches/CHECKSUMS.sha256 (push) Has been cancelled
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Has been cancelled
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Has been cancelled
Voice Benchmark Smoke / voice bench smoke summary (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/app-core test bun run --cwd packages/elizaos test bun run --cwd packages/cloud/shared test], app-and-cli) (push) Has been cancelled
Windows CI / windows ([bun run --cwd packages/scenario-runner test bun run --cwd packages/vault test bun run --cwd packages/security test bun run --cwd plugins/plugin-coding-tools test], framework-packages) (push) Has been cancelled
Windows CI / windows ([bun run --cwd plugins/plugin-elizacloud test bun run --cwd plugins/plugin-discord test bun run --cwd plugins/plugin-anthropic test bun run --cwd plugins/plugin-openai test bun run --cwd plugins/plugin-app-control test bun run --cwd plugins/pl… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run build --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/agent --concurrency=4 node packages/scripts/run-bash-linux-only.mjs scripts/verify-riscv64-buildpaths.sh node packages/scripts/run… (push) Has been cancelled
Windows CI / windows ([node packages/scripts/run-turbo.mjs run typecheck --filter=@elizaos/core --filter=@elizaos/shared --filter=@elizaos/cloud-shared --concurrency=4 bun run --cwd packages/core test bun run --cwd packages/shared test], core-runtime, 75) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:43:05 +08:00

218 lines
5.5 KiB
JavaScript

#!/usr/bin/env node
/**
* Testing skip inventory auditor for Feed.
* It scans source files for skipped tests and reports undocumented unconditional skips as tracked test debt.
*/
import { readdirSync, readFileSync, statSync } from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
const rootDir = path.resolve(
path.dirname(fileURLToPath(import.meta.url)),
"..",
);
const SKIP_PATTERN =
/\b(?:test|it|describe)\.skip(?:If)?\s*\(|\.skipIf\s*\(|\btest\.skip\s*\(|\bdescribe\.skip\b/g;
const SOURCE_EXTENSIONS = new Set([
".ts",
".tsx",
".js",
".jsx",
".mjs",
".cjs",
]);
const IGNORED_DIRS = new Set([
".git",
".next",
".turbo",
".vercel",
"build",
"coverage",
"dist",
"node_modules",
"playwright-report",
"storybook-static",
"test-results",
]);
function parseArgs(argv) {
const args = {
format: "text",
failOnUndocumentedUnconditional: false,
};
for (const arg of argv) {
if (arg === "--format=json") args.format = "json";
else if (arg === "--format=text") args.format = "text";
else if (arg === "--fail-on-undocumented-unconditional") {
args.failOnUndocumentedUnconditional = true;
} else if (arg === "--help" || arg === "-h") {
printHelp();
process.exit(0);
} else {
throw new Error(`Unknown argument: ${arg}`);
}
}
return args;
}
function printHelp() {
console.log(`Usage: bun run scripts/testing-skip-inventory.mjs [options]
Options:
--format=text|json Output format (default: text)
--fail-on-undocumented-unconditional Exit 1 when a bare unconditional skip lacks nearby rationale
`);
}
function* walk(dir) {
for (const entry of readdirSync(dir, { withFileTypes: true })) {
if (IGNORED_DIRS.has(entry.name)) continue;
const fullPath = path.join(dir, entry.name);
if (entry.isDirectory()) {
yield* walk(fullPath);
continue;
}
if (entry.isFile() && SOURCE_EXTENSIONS.has(path.extname(entry.name))) {
yield fullPath;
}
}
}
function hasQuotedReason(line) {
return /test\.skip\s*\([^,\n]+,\s*["'`]/.test(line);
}
function contextFor(lines, lineIndex) {
const start = Math.max(0, lineIndex - 6);
const end = Math.min(lines.length, lineIndex + 4);
return lines.slice(start, end).join("\n");
}
function classifySkip(line, context) {
const haystack = `${line}\n${context}`.toLowerCase();
if (hasQuotedReason(line)) return "documented-inline";
if (
/skip:\s|skipping|broken|pre-existing|unrelated|todo|fixme/.test(haystack)
) {
return "documented-nearby";
}
if (
/server.*(healthy|available)|healthy|base_url|playwright_base_url/.test(
haystack,
)
) {
return "server-gated";
}
if (
/live.?llm|api.?key|openai|anthropic|groq|elizacloud|model key/.test(
haystack,
)
) {
return "live-llm-gated";
}
if (/database|postgres|db\b|direct_database_url/.test(haystack)) {
return "database-gated";
}
if (/auth|session|api key|registration|login|wallet/.test(haystack)) {
return "auth-or-session-gated";
}
if (/seed|snapshot|metamask|onchain|settlement|nft/.test(haystack)) {
return "seed-or-external-state-gated";
}
if (/strict|local dev|optional/.test(haystack)) {
return "local-optional";
}
if (
/\bif\s*\(|\belse\s*\{|\?\s*describe\.skip|\?\s*test\.skip/.test(context)
) {
return "conditional-undocumented";
}
return "undocumented-unconditional";
}
function inventoryFile(filePath) {
const text = readFileSync(filePath, "utf8");
const lines = text.split(/\r?\n/);
const findings = [];
for (const [lineIndex, line] of lines.entries()) {
if (/^\s*(?:\/\/|\*|\/\*)/.test(line)) continue;
SKIP_PATTERN.lastIndex = 0;
if (!SKIP_PATTERN.test(line)) continue;
const context = contextFor(lines, lineIndex);
findings.push({
file: path.relative(rootDir, filePath),
line: lineIndex + 1,
marker: line.trim(),
category: classifySkip(line, context),
});
}
return findings;
}
function buildReport() {
const findings = [];
for (const filePath of walk(rootDir)) {
if (statSync(filePath).size === 0) continue;
findings.push(...inventoryFile(filePath));
}
findings.sort((a, b) =>
a.file === b.file ? a.line - b.line : a.file.localeCompare(b.file),
);
const categories = {};
const files = new Set();
for (const finding of findings) {
files.add(finding.file);
categories[finding.category] = (categories[finding.category] ?? 0) + 1;
}
return {
root: "packages/feed",
summary: {
skipMarkers: findings.length,
files: files.size,
categories,
},
findings,
};
}
function printText(report) {
console.log("# Feed skip inventory");
console.log(`skip markers: ${report.summary.skipMarkers}`);
console.log(`files: ${report.summary.files}`);
console.log("");
console.log("categories:");
for (const [category, count] of Object.entries(report.summary.categories)) {
console.log(`- ${category}: ${count}`);
}
console.log("");
console.log("findings:");
for (const finding of report.findings) {
console.log(
`- ${finding.category} ${finding.file}:${finding.line} ${finding.marker}`,
);
}
}
const args = parseArgs(process.argv.slice(2));
const report = buildReport();
if (args.format === "json") {
console.log(JSON.stringify(report, null, 2));
} else {
printText(report);
}
if (
args.failOnUndocumentedUnconditional &&
(report.summary.categories["undocumented-unconditional"] ?? 0) > 0
) {
process.exitCode = 1;
}