Files
SubMiner/src/workflow-policy.test.ts
T

46 lines
1.6 KiB
TypeScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { readdirSync } from 'node:fs';
import { resolve } from 'node:path';
import {
readWorkflow,
stepsReadingUndeclaredEnv,
templateExpressionsInRunBodies,
} from './workflow-test-helpers';
// Policy lints that apply to every workflow, so new workflows are covered automatically.
const workflowsDir = resolve(__dirname, '../.github/workflows');
const workflows = readdirSync(workflowsDir)
.filter((file) => /\.ya?ml$/.test(file))
.sort()
.map((file) => ({ file, workflow: readWorkflow(resolve(workflowsDir, file)) }));
test('workflow policy lint finds the workflow files', () => {
assert.ok(workflows.length > 0);
});
for (const { file, workflow } of workflows) {
test(`${file} passes values to shell through env, not template expressions`, () => {
assert.deepEqual(templateExpressionsInRunBodies(workflow), []);
assert.deepEqual(stepsReadingUndeclaredEnv(workflow), []);
});
}
test('reusable workflows default to read-only contents and do not persist checkout credentials', () => {
const reusable = workflows.filter(
({ workflow }) => workflow.on && 'workflow_call' in workflow.on,
);
assert.ok(reusable.length > 0);
for (const { file, workflow } of reusable) {
assert.deepEqual(workflow.permissions, { contents: 'read' }, file);
for (const [job, definition] of Object.entries(workflow.jobs ?? {})) {
for (const step of definition?.steps ?? []) {
if (step.uses?.startsWith('actions/checkout@')) {
assert.equal(step.with?.['persist-credentials'], false, `${file}/${job}`);
}
}
}
}
});