Files
everything-claude-code/tests/ci/supply-chain-watch-workflow.test.js
Affaan Mustafa e755c5f72b fix: make plugin hooks run on Node 21+ and green the suite under modern Node (#2184)
ROOT CAUSE: hooks load plugin-hook-bootstrap.js via
`node -e "...; process.argv.splice(1,0,s); require(s)"`. On Node 21+,
require.main is `undefined` under --eval, so the `if (require.main === module)`
guard was false and main() never ran — every plugin hook silently no-op'd
(e.g. the MCP-health PreToolUse hook stopped blocking). CI (Node 18/20) hid
this; it only surfaces on Node 21+. Fix: also run main() when require.main is
undefined (the eval-bootstrap case), while staying dormant on real imports.

Also clears pre-existing main debt the full local suite enforces:
- catalog:sync — README/docs agent+skill counts drifted after recent merges
- tests/ci/supply-chain-watch-workflow: update checkout SHA to the merged v6.0.3 (#2183)
- markdownlint + check-unicode-safety --write across docs/skills

Suite: 2683/2683 green under Node v25; lint + unicode clean.

Co-authored-by: ECC Test <ecc@example.test>
2026-06-07 16:05:28 +08:00

78 lines
2.7 KiB
JavaScript

#!/usr/bin/env node
/**
* Validate the scheduled supply-chain watch workflow contract.
*/
const assert = require('assert');
const fs = require('fs');
const path = require('path');
const WORKFLOW_PATH = path.join(
__dirname,
'..',
'..',
'.github',
'workflows',
'supply-chain-watch.yml',
);
function test(name, fn) {
try {
fn();
console.log(`${name}`);
return true;
} catch (error) {
console.log(`${name}`);
console.log(` Error: ${error.message}`);
return false;
}
}
function run() {
console.log('\n=== Testing supply-chain watch workflow ===\n');
const source = fs.readFileSync(WORKFLOW_PATH, 'utf8');
let passed = 0;
let failed = 0;
if (test('runs on schedule and manual dispatch', () => {
assert.match(source, /schedule:\r?\n\s+- cron: '17 \*\/6 \* \* \*'/);
assert.match(source, /workflow_dispatch:/);
})) passed++; else failed++;
if (test('uses read-only permissions and non-persisting checkout credentials', () => {
assert.match(source, /permissions:\r?\n\s+contents: read/);
assert.doesNotMatch(source, /^\s+[A-Za-z-]+:\s*write\b/m);
assert.match(source, /uses: actions\/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10/);
assert.match(source, /persist-credentials: false/);
assert.doesNotMatch(source, /id-token:\s*write/);
assert.doesNotMatch(source, /actions\/cache@/);
})) passed++; else failed++;
if (test('installs without lifecycle scripts and verifies registry signatures', () => {
assert.match(source, /npm ci --ignore-scripts/);
assert.match(source, /npm audit signatures/);
assert.match(source, /npm audit --audit-level=high/);
})) passed++; else failed++;
if (test('runs IOC fixtures, emits JSON report, and uploads the artifact', () => {
assert.match(source, /node tests\/ci\/scan-supply-chain-iocs\.test\.js/);
assert.match(source, /node scripts\/ci\/scan-supply-chain-iocs\.js --json > artifacts\/supply-chain-ioc-report\.json/);
assert.match(source, /node tests\/ci\/supply-chain-advisory-sources\.test\.js/);
assert.match(source, /node scripts\/ci\/supply-chain-advisory-sources\.js --refresh --json > artifacts\/supply-chain-advisory-sources\.json/);
assert.match(source, /node scripts\/ci\/validate-workflow-security\.js/);
assert.match(source, /uses: actions\/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a/);
assert.match(source, /name: supply-chain-ioc-report/);
assert.match(source, /artifacts\/supply-chain-ioc-report\.json/);
assert.match(source, /artifacts\/supply-chain-advisory-sources\.json/);
assert.match(source, /retention-days: 14/);
})) passed++; else failed++;
console.log(`\nPassed: ${passed}`);
console.log(`Failed: ${failed}`);
process.exit(failed > 0 ? 1 : 0);
}
run();