Files
HiveGrid-Wireframes/03 Quellen und Referenzen/hivegrid-cloud/scripts/verify-action-pins.test.mjs
T

80 lines
2.6 KiB
JavaScript

import assert from "node:assert/strict";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { afterEach, describe, it } from "vitest";
import { inspectWorkflowActionPins, verifyActionPins } from "./verify-action-pins.mjs";
const temporaryDirectories = [];
afterEach(() => {
for (const directory of temporaryDirectories.splice(0)) {
fs.rmSync(directory, { recursive: true, force: true });
}
});
function createWorkflow(source) {
const root = fs.mkdtempSync(path.join(os.tmpdir(), "hivegrid-action-pins-"));
temporaryDirectories.push(root);
const directory = path.join(root, ".gitea/workflows");
fs.mkdirSync(directory, { recursive: true });
fs.writeFileSync(path.join(directory, "ci.yml"), source);
return root;
}
describe("workflow action pin verification", () => {
it("accepts commit SHAs, image digests, and local workflows", () => {
const source = [
"steps:",
" - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4",
` - uses: docker://alpine@sha256:${"a".repeat(64)}`,
" - uses: ./.gitea/workflows/local.yml",
].join("\n");
const result = inspectWorkflowActionPins(source, "ci.yml");
assert.equal(result.failures.length, 0);
assert.equal(result.passes.length, 3);
});
it("rejects tags, branches, missing refs, uppercase SHAs, and mutable images", () => {
const source = [
"steps:",
" - uses: actions/checkout@v4",
" - uses: owner/action@main",
" - uses: owner/action",
` - uses: owner/action@${"A".repeat(40)}`,
" - uses: docker://alpine:3.20",
].join("\n");
const result = inspectWorkflowActionPins(source, "ci.yml");
assert.equal(result.failures.length, 5);
});
it("checks workflow directories recursively", () => {
const root = createWorkflow("steps:\n - uses: actions/cache@v4\n");
const result = verifyActionPins(root);
assert.equal(result.failures.length, 1);
assert.match(result.failures[0], /actions\/cache@v4/);
});
it("accepts exact executable package versions and rejects mutable ranges", () => {
const source = [
"steps:",
" - run: npx --yes @lhci/cli@0.13.0 autorun",
" - run: pnpm dlx @lhci/cli@0.13.x autorun",
" - run: npx -y @subframe/cli@latest sync --all",
].join("\n");
const result = inspectWorkflowActionPins(source, "ci.yml");
assert.equal(result.passes.length, 1);
assert.equal(result.failures.length, 2);
assert.match(result.failures[0], /0\.13\.x/);
assert.match(result.failures[1], /latest/);
});
});