426e9eeabd
Benchmark Bridge Tests / benchmark (bunx @biomejs/biome check packages/lifeops-bench/src, benchmark-lint) (push) Waiting to run
Benchmark Bridge Tests / benchmark (bunx vitest run --config packages/lifeops-bench/vitest.config.ts --root packages/lifeops-bench --passWithNoTests, benchmark-tests) (push) Waiting to run
Build Agent Image / build-and-push (push) Waiting to run
Chat shell gestures / Chat shell gesture + parity e2e (push) Waiting to run
Cloud Gateway Discord / Test (push) Waiting to run
Cloud Gateway Webhook / Test (push) Waiting to run
Cloud Tests / lint-and-types (push) Waiting to run
Cloud Tests / unit-tests (push) Waiting to run
Cloud Tests / integration-tests (push) Waiting to run
Cloud Tests / e2e-tests (push) Blocked by required conditions
CodeQL Advanced / Analyze (javascript-typescript) (push) Waiting to run
Deploy Apps Worker (Product 2) / Determine environment (push) Waiting to run
Deploy Apps Worker (Product 2) / Deploy apps worker to apps-control host (${{ needs.determine-env.outputs.environment }}) (push) Blocked by required conditions
Deploy Eliza Provisioning Worker / Determine environment (push) Waiting to run
Deploy Eliza Provisioning Worker / Deploy worker to Hetzner host (${{ needs.determine-env.outputs.environment }} @ ${{ needs.determine-env.outputs.deployment_sha }}) (push) Blocked by required conditions
Dev Smoke / Classify changed paths (push) Waiting to run
Dev Smoke / bun run dev onboarding chat (push) Blocked by required conditions
Dev Smoke / Vite HMR dependency-level smoke (push) Blocked by required conditions
Electrobun Submodule Guard / electrobun gitlink is fetchable (push) Waiting to run
Publish @elizaos/example-code / check_npm (push) Waiting to run
Publish @elizaos/example-code / publish_npm (push) Blocked by required conditions
Publish @elizaos/plugin-elizacloud / verify_version (push) Waiting to run
Publish @elizaos/plugin-elizacloud / publish_npm (push) Blocked by required conditions
Sandbox Live Smoke / Sandbox live smoke (push) Waiting to run
Snap Build & Test / Build Snap (amd64) (push) Waiting to run
Snap Build & Test / Build Snap (arm64) (push) Waiting to run
supply-chain / sbom (push) Waiting to run
supply-chain / vulnerability-scan (push) Waiting to run
Build, Push & Deploy to Phala Cloud / build-and-push (push) Waiting to run
Test Packaging / Validate Packaging Configs (push) Waiting to run
Test Packaging / PyPI on Python ${{ matrix.python }} (push) Waiting to run
Test Packaging / Pack & Test JS Tarballs (push) Waiting to run
Test Packaging / elizaos CLI global-install smoke (node + bun) (push) Waiting to run
UI Fixture E2E / ui-fixture-e2e (push) Waiting to run
UI Fixture E2E / fixture-e2e (push) Waiting to run
UI Story Gate / story-gate (push) Waiting to run
vault-ci / test (macos-latest) (push) Waiting to run
vault-ci / test (ubuntu-latest) (push) Waiting to run
vault-ci / test (windows-latest) (push) Waiting to run
vault-ci / app-core wiring tests (push) Waiting to run
verify-patches / verify patches/CHECKSUMS.sha256 (push) Waiting to run
Voice Benchmark Smoke / voice-emotion fixture smoke (push) Waiting to run
Voice Benchmark Smoke / voiceagentbench fixture smoke (push) Waiting to run
Voice Benchmark Smoke / voicebench-quality unit smoke (push) Waiting to run
Voice Benchmark Smoke / voicebench TypeScript unit (no audio) (push) Waiting to run
Voice Benchmark Smoke / voice bench smoke summary (push) Blocked by required conditions
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) Waiting to run
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) Waiting to run
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) Waiting to run
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) Waiting to run
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) Waiting to run
Test Packaging / Build & Test PyPI Package (push) Waiting to run
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
209 lines
7.0 KiB
JavaScript
209 lines
7.0 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Per-package testing coverage matrix generator for issue #9943.
|
|
*
|
|
* Walks every workspace package using tracked files from `git ls-files`, counts
|
|
* test/spec files and skipped tests, and records whether the package exposes the
|
|
* `test` script used by the root workspace runner. Emits
|
|
* docs/TESTING_COVERAGE_MATRIX.md.
|
|
*
|
|
* "In CI" is a heuristic: a package is swept by the root runner when it is a
|
|
* workspace member with a `test` script and is not excluded from the root
|
|
* workspace. packages/feed is excluded from the root workspace and runs through
|
|
* its own path-gated feed-test.yml lane instead.
|
|
*
|
|
* Usage:
|
|
* node scripts/testing-coverage-matrix.mjs
|
|
* node scripts/testing-coverage-matrix.mjs --check
|
|
*/
|
|
|
|
import { execFileSync } from "node:child_process";
|
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const REPO_ROOT = path.resolve(
|
|
path.dirname(fileURLToPath(import.meta.url)),
|
|
"..",
|
|
);
|
|
const OUTPUT = path.join(REPO_ROOT, "docs", "TESTING_COVERAGE_MATRIX.md");
|
|
|
|
const TEST_FILE_RE = /\.(test|spec)\.(ts|tsx|js|jsx|mjs|cjs)$/;
|
|
// it.skip / test.skip / describe.skip / xit / xdescribe / .todo / .skipIf(...)
|
|
const SKIP_RE =
|
|
/\b(?:it|test|describe)\.(?:skip|todo)\b|\bx(?:it|describe)\s*\(|\.skipIf\s*\(|\btest\.skip\b/g;
|
|
|
|
function gitFiles() {
|
|
return execFileSync("git", ["ls-files"], {
|
|
cwd: REPO_ROOT,
|
|
encoding: "utf8",
|
|
maxBuffer: 256 * 1024 * 1024,
|
|
})
|
|
.split("\n")
|
|
.filter(Boolean);
|
|
}
|
|
|
|
function readJson(rel) {
|
|
try {
|
|
return JSON.parse(readFileSync(path.join(REPO_ROOT, rel), "utf8"));
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function main() {
|
|
const files = gitFiles();
|
|
|
|
// Every directory that owns a package.json (excluding the repo root) is a
|
|
// package node. Tracked files never include node_modules, so this is clean.
|
|
const packageDirs = files
|
|
.filter((f) => f.endsWith("/package.json") || f === "package.json")
|
|
.map((f) => path.posix.dirname(f))
|
|
.filter((dir) => dir !== ".")
|
|
.sort();
|
|
const packageDirSet = new Set(packageDirs);
|
|
|
|
/** Deepest package dir that is an ancestor of `file` (or null). */
|
|
function ownerPackage(file) {
|
|
let dir = path.posix.dirname(file);
|
|
while (dir !== "." && dir.length > 0) {
|
|
if (packageDirSet.has(dir)) return dir;
|
|
const next = path.posix.dirname(dir);
|
|
if (next === dir) break;
|
|
dir = next;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
const rootPkg = readJson("package.json");
|
|
const workspaceNegations = (rootPkg?.workspaces ?? [])
|
|
.filter((w) => typeof w === "string" && w.startsWith("!"))
|
|
.map((w) => w.slice(1));
|
|
const excludedFromRoot = (dir) =>
|
|
workspaceNegations.some((neg) => dir === neg || dir.startsWith(`${neg}/`));
|
|
|
|
const stats = new Map(
|
|
packageDirs.map((dir) => [
|
|
dir,
|
|
{ dir, name: null, testFiles: 0, skips: 0, hasTestScript: false },
|
|
]),
|
|
);
|
|
|
|
// Per-package package.json metadata.
|
|
for (const dir of packageDirs) {
|
|
const pkg = readJson(`${dir}/package.json`);
|
|
const entry = stats.get(dir);
|
|
entry.name = pkg?.name ?? "(unnamed)";
|
|
entry.hasTestScript = Boolean(pkg?.scripts?.test);
|
|
}
|
|
|
|
// Assign test files to their owning package and count skips.
|
|
for (const file of files) {
|
|
if (!TEST_FILE_RE.test(file)) continue;
|
|
const owner = ownerPackage(file);
|
|
if (!owner) continue;
|
|
const entry = stats.get(owner);
|
|
entry.testFiles += 1;
|
|
try {
|
|
const body = readFileSync(path.join(REPO_ROOT, file), "utf8");
|
|
const matches = body.match(SKIP_RE);
|
|
if (matches) entry.skips += matches.length;
|
|
} catch {
|
|
// Unreadable tracked file (symlink/binary) — skip silently.
|
|
}
|
|
}
|
|
|
|
const rows = [...stats.values()]
|
|
.filter((e) => e.testFiles > 0 || e.hasTestScript)
|
|
.sort((a, b) => a.dir.localeCompare(b.dir));
|
|
|
|
const totals = rows.reduce(
|
|
(acc, r) => {
|
|
acc.testFiles += r.testFiles;
|
|
acc.skips += r.skips;
|
|
acc.withTests += r.testFiles > 0 ? 1 : 0;
|
|
acc.inCi += r.hasTestScript && !excludedFromRoot(r.dir) ? 1 : 0;
|
|
acc.zeroTestWithScript += r.testFiles === 0 && r.hasTestScript ? 1 : 0;
|
|
return acc;
|
|
},
|
|
{ testFiles: 0, skips: 0, withTests: 0, inCi: 0, zeroTestWithScript: 0 },
|
|
);
|
|
|
|
const lines = [];
|
|
lines.push("# Testing coverage matrix");
|
|
lines.push("");
|
|
lines.push(
|
|
"Per-package view of test presence, CI wiring, and skip debt. Generated by " +
|
|
"`node scripts/testing-coverage-matrix.mjs` — do not hand-edit; re-run to refresh.",
|
|
);
|
|
lines.push("");
|
|
lines.push("## Columns");
|
|
lines.push("");
|
|
lines.push(
|
|
"- **Test files** — count of `*.{test,spec}.{ts,tsx,js,jsx,mjs,cjs}` owned by the package (assigned to the deepest enclosing package).",
|
|
);
|
|
lines.push(
|
|
"- **Skips** — count of `it/test/describe.skip`, `.todo`, `x(it|describe)`, and `.skipIf(...)` markers across those files.",
|
|
);
|
|
lines.push(
|
|
"- **`test` script** — package exposes a `test` script (the signal the root runner sweeps on).",
|
|
);
|
|
lines.push(
|
|
"- **In CI (heuristic)** — has a `test` script AND is not excluded from the root workspace. Not a proof of execution; lane-level gating still applies.",
|
|
);
|
|
lines.push("");
|
|
lines.push("## Summary");
|
|
lines.push("");
|
|
lines.push(`- Packages with tests: **${totals.withTests}**`);
|
|
lines.push(
|
|
`- Packages swept by the root runner (heuristic): **${totals.inCi}**`,
|
|
);
|
|
lines.push(`- Total test files: **${totals.testFiles}**`);
|
|
lines.push(`- Total skipped tests: **${totals.skips}**`);
|
|
lines.push(
|
|
`- Packages with a \`test\` script but zero test files: **${totals.zeroTestWithScript}**`,
|
|
);
|
|
lines.push("");
|
|
lines.push(
|
|
"> Known dark corner: `packages/feed` is excluded from the root workspace " +
|
|
"(`!packages/feed`) and runs via its own path-gated `feed-test.yml` lane " +
|
|
"(`test:unit`). Its ~227 skips still need triage (#9943 follow-up).",
|
|
);
|
|
lines.push("");
|
|
lines.push("## Matrix");
|
|
lines.push("");
|
|
lines.push(
|
|
"| Package | Path | Test files | Skips | `test` script | In CI (heuristic) |",
|
|
);
|
|
lines.push("| --- | --- | ---: | ---: | :---: | :---: |");
|
|
for (const r of rows) {
|
|
const inCi = r.hasTestScript && !excludedFromRoot(r.dir);
|
|
lines.push(
|
|
`| ${r.name} | \`${r.dir}\` | ${r.testFiles} | ${r.skips} | ${r.hasTestScript ? "yes" : "no"} | ${inCi ? "yes" : "no"} |`,
|
|
);
|
|
}
|
|
lines.push("");
|
|
|
|
const content = `${lines.join("\n")}`;
|
|
|
|
if (process.argv.includes("--check")) {
|
|
const current = existsSync(OUTPUT) ? readFileSync(OUTPUT, "utf8") : "";
|
|
if (current !== content) {
|
|
console.error(
|
|
"docs/TESTING_COVERAGE_MATRIX.md is stale. Run `node scripts/testing-coverage-matrix.mjs`.",
|
|
);
|
|
process.exit(1);
|
|
}
|
|
console.log("TESTING_COVERAGE_MATRIX.md is up to date.");
|
|
return;
|
|
}
|
|
|
|
writeFileSync(OUTPUT, content);
|
|
console.log(
|
|
`Wrote ${path.relative(REPO_ROOT, OUTPUT)}: ${rows.length} packages, ` +
|
|
`${totals.testFiles} test files, ${totals.skips} skips.`,
|
|
);
|
|
}
|
|
|
|
main();
|