Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion review-enrichment/src/analyzers/actions-pin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import { isWorkflowPath } from "../workflow-path.js";

const USES_RE = /^\s*-?\s*["']?uses["']?\s*:\s*["']?([\w.-]+\/[\w./-]+)@([^\s"'#]+)/;
const FULL_SHA = /^[0-9a-f]{40}$/;
const OFFICIAL = /^(actions|github)\//;
// GitHub org/user names are case-insensitive (mirrors isWorkflowPath's case-insensitive path match), so the
// official-action exclusion matches case-insensitively — otherwise `Actions/checkout` would be mis-flagged as a
// mutable third-party action. GitHub reserves the `actions`/`github` orgs, so this can never over-match a real one.
const OFFICIAL = /^(actions|github)\//i;

/** Scan one workflow patch's added lines for unpinned third-party `uses:` refs, line-cited via hunk headers. Pure. */
export function scanWorkflowPins(
Expand Down
19 changes: 19 additions & 0 deletions review-enrichment/test/actions-pin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,25 @@ test("scanWorkflowPins flags mutable third-party action refs with line citations
]);
});

test("scanWorkflowPins excludes official actions/github refs case-insensitively", () => {
const findings = scanWorkflowPins(
workflowPath,
[
"@@ -1,0 +5,4 @@",
"+ - uses: Actions/checkout@v4",
"+ - uses: GitHub/codeql-action/init@v3",
"+ - uses: ACTIONS/setup-node@v4",
"+ - uses: pnpm/action-setup@v3",
].join("\n"),
);

// GitHub org names are case-insensitive, so official actions/* and github/* refs are excluded regardless of
// casing; only the genuine mutable third-party ref is flagged.
assert.deepEqual(findings, [
{ file: workflowPath, line: 8, action: "pnpm/action-setup", ref: "v3" },
]);
});

test("scanWorkflowPins accepts quoted uses keys and ignores unchanged uses lines", () => {
const findings = scanWorkflowPins(
workflowPath,
Expand Down
Loading