Skip to content

Commit bdb547c

Browse files
bloveclaude
andauthored
ci: wire root scripts vitest suites into an Nx test target and CI job (#916)
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent 6861daf commit bdb547c

7 files changed

Lines changed: 119 additions & 1 deletion

File tree

.github/workflows/ci.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ jobs:
3232
cockpit_e2e: ${{ steps.scope.outputs.cockpit_e2e }}
3333
website_e2e: ${{ steps.scope.outputs.website_e2e }}
3434
posthog: ${{ steps.scope.outputs.posthog }}
35+
scripts_tests: ${{ steps.scope.outputs.scripts_tests }}
3536
steps:
3637
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
3738
with:
@@ -77,6 +78,24 @@ jobs:
7778
- name: Validate CI workflow guards
7879
run: node --test scripts/ci-workflow.spec.mjs
7980

81+
scripts-tests:
82+
name: Scripts — generator / proxy vitest suites
83+
needs: ci-scope
84+
if: github.event_name == 'push' || needs.ci-scope.outputs.scripts_tests == 'true'
85+
runs-on: ubuntu-latest
86+
steps:
87+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
88+
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
89+
with:
90+
node-version: 22
91+
cache: npm
92+
- run: npm ci
93+
# Vitest suites for the root deployment/proxy generators (drift checks,
94+
# framework-adapter branching, requirements unions, rate limits). The
95+
# node:test suites in scripts/ run in ci-scope and library instead —
96+
# see scripts/vite.config.mts for the split.
97+
- run: npx nx test scripts
98+
8099
library:
81100
name: Library — lint / test / build
82101
needs: ci-scope
@@ -543,6 +562,7 @@ jobs:
543562
- cockpit-e2e-summary
544563
- website-e2e
545564
- posthog-sync-plan
565+
- scripts-tests
546566
if: ${{ always() && github.event_name == 'pull_request' }}
547567
runs-on: ubuntu-latest
548568
steps:
@@ -561,6 +581,7 @@ jobs:
561581
RESULT_COCKPIT_E2E: ${{ needs.cockpit-e2e-summary.result }}
562582
RESULT_WEBSITE_E2E: ${{ needs.website-e2e.result }}
563583
RESULT_POSTHOG: ${{ needs.posthog-sync-plan.result }}
584+
RESULT_SCRIPTS_TESTS: ${{ needs.scripts-tests.result }}
564585
SCOPE_LIBRARY: ${{ needs.ci-scope.outputs.library }}
565586
SCOPE_ANGULAR_COMPATIBILITY: ${{ needs.ci-scope.outputs.angular_compatibility }}
566587
SCOPE_WEBSITE: ${{ needs.ci-scope.outputs.website }}
@@ -572,6 +593,7 @@ jobs:
572593
SCOPE_COCKPIT_E2E: ${{ needs.ci-scope.outputs.cockpit_e2e }}
573594
SCOPE_WEBSITE_E2E: ${{ needs.ci-scope.outputs.website_e2e }}
574595
SCOPE_POSTHOG: ${{ needs.ci-scope.outputs.posthog }}
596+
SCOPE_SCRIPTS_TESTS: ${{ needs.ci-scope.outputs.scripts_tests }}
575597
run: |
576598
set -euo pipefail
577599
@@ -624,6 +646,7 @@ jobs:
624646
require_scoped "cockpit_e2e" "Cockpit — e2e" "$RESULT_COCKPIT_E2E" "$SCOPE_COCKPIT_E2E"
625647
require_scoped "website_e2e" "Website — e2e" "$RESULT_WEBSITE_E2E" "$SCOPE_WEBSITE_E2E"
626648
require_scoped "posthog" "PostHog — dashboards-as-code drift check" "$RESULT_POSTHOG" "$SCOPE_POSTHOG"
649+
require_scoped "scripts_tests" "Scripts — generator / proxy vitest suites" "$RESULT_SCRIPTS_TESTS" "$SCOPE_SCRIPTS_TESTS"
627650
628651
if [[ "$failed" -ne 0 ]]; then
629652
exit 1

scripts/ci-scope.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export const SCOPE_KEYS = [
1616
'cockpit_e2e',
1717
'examples_chat',
1818
'posthog',
19+
'scripts_tests',
1920
];
2021

2122
const GLOBAL_CI_FILES = new Set([

scripts/ci-scope.spec.mjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ describe('classifyFromAffected — tag isolation', () => {
338338
});
339339

340340
describe('SCOPE_KEYS export', () => {
341-
it('contains the 11 documented scope keys', () => {
341+
it('contains the 12 documented scope keys', () => {
342342
assert.deepEqual(SCOPE_KEYS, [
343343
'library',
344344
'angular_compatibility',
@@ -351,6 +351,7 @@ describe('SCOPE_KEYS export', () => {
351351
'cockpit_e2e',
352352
'examples_chat',
353353
'posthog',
354+
'scripts_tests',
354355
]);
355356
});
356357
});

scripts/ci-workflow.spec.mjs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,31 @@ describe('CI workflow', () => {
347347
);
348348
});
349349

350+
it('runs the root scripts vitest suites when the scripts project is affected', async () => {
351+
const workflow = await readWorkflow();
352+
const scriptsTestsJob = readJobBlock(workflow, 'scripts-tests');
353+
354+
assert.match(
355+
scriptsTestsJob,
356+
/if: github\.event_name == 'push' \|\| needs\.ci-scope\.outputs\.scripts_tests == 'true'/
357+
);
358+
assert.match(scriptsTestsJob, /npx nx test scripts/);
359+
360+
const requiredPrChecksJob = await readRequiredPrChecksJob();
361+
assert.match(
362+
requiredPrChecksJob,
363+
/RESULT_SCRIPTS_TESTS:\s*\$\{\{\s*needs\.scripts-tests\.result\s*\}\}/
364+
);
365+
assert.match(
366+
requiredPrChecksJob,
367+
/SCOPE_SCRIPTS_TESTS:\s*\$\{\{\s*needs\.ci-scope\.outputs\.scripts_tests\s*\}\}/
368+
);
369+
assert.match(
370+
requiredPrChecksJob,
371+
/require_scoped "scripts_tests" "Scripts generator \/ proxy vitest suites"/
372+
);
373+
});
374+
350375
it('provides one stable required PR check that waits for scoped CI jobs', async () => {
351376
const requiredPrChecksJob = await readRequiredPrChecksJob();
352377
const expectedNeeds = [
@@ -363,6 +388,7 @@ describe('CI workflow', () => {
363388
'cockpit-e2e-summary',
364389
'website-e2e',
365390
'posthog-sync-plan',
391+
'scripts-tests',
366392
];
367393

368394
assert.match(requiredPrChecksJob, /name:\s*CI required/);

scripts/project.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "scripts",
3+
"$schema": "../node_modules/nx/schemas/project-schema.json",
4+
"projectType": "library",
5+
"tags": ["scope:scripts-tests", "type:tooling"],
6+
"implicitDependencies": [],
7+
"targets": {
8+
"test": {
9+
"executor": "@nx/vitest:test",
10+
"options": {
11+
"configFile": "scripts/vite.config.mts"
12+
}
13+
}
14+
}
15+
}

scripts/tsconfig.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"extends": "../tsconfig.base.json",
3+
"compilerOptions": {
4+
"module": "esnext",
5+
"moduleResolution": "bundler",
6+
"target": "es2022",
7+
"esModuleInterop": true,
8+
"skipLibCheck": true,
9+
"resolveJsonModule": true,
10+
"types": ["node", "vitest/globals"],
11+
"lib": ["es2022"]
12+
},
13+
"include": ["*.ts", "*.mts"]
14+
}

scripts/vite.config.mts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { defineConfig } from 'vite';
2+
3+
// Vitest config for the root deployment/proxy generator scripts.
4+
//
5+
// Two runners share scripts/: the node:test suites listed in `exclude`
6+
// below are invoked directly by .github/workflows/ci.yml (`node --test`),
7+
// everything else matching `include` runs under vitest via `nx test scripts`.
8+
// A new *.spec.ts / *.spec.mjs file here is picked up automatically; a new
9+
// node:test suite must be added to `exclude` AND to the ci.yml `node --test`
10+
// invocation, otherwise vitest fails loudly on it ("no test suite found") —
11+
// loud-by-default beats silently unrun.
12+
export default defineConfig({
13+
test: {
14+
environment: 'node',
15+
globals: true,
16+
include: ['*.spec.ts', '*.spec.mjs'],
17+
exclude: [
18+
// node:test suites — run by ci.yml directly, not by vitest.
19+
'ci-scope.spec.mjs',
20+
'ci-workflow.spec.mjs',
21+
'cockpit-matrix.spec.mjs',
22+
'cockpit-ports.spec.mjs',
23+
'verify-angular-support.spec.mjs',
24+
// STALE (excluded deliberately, not a runner mismatch): this one-time
25+
// #881 cutover checklist now fails against main on two counts —
26+
// libs/licensing is still tracked (and consumed by Angular bundles),
27+
// and the Mastra runtime content/lockfiles legitimately mention the
28+
// "excluded competitor". Reinstate only after the spec is reconciled
29+
// with current policy.
30+
'mit-cutover.spec.mjs',
31+
],
32+
// Generator specs shell out to `npx tsx` and (re)generate committed
33+
// deployment manifests; keep them serial to avoid write races.
34+
fileParallelism: false,
35+
testTimeout: 60000,
36+
hookTimeout: 60000,
37+
},
38+
});

0 commit comments

Comments
 (0)