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
218 lines
5.5 KiB
JavaScript
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;
|
|
}
|