ci: list file and line only in the public portability report (#59)

Co-authored-by: orch-advisor <orch-advisor@openrig-build>
This commit is contained in:
Mike Schwarzandorch-advisor authored and GitHub committed 2026-09-26 01:00:48 -07:00
1 parent 6d27f87586
commit fbc30c2b6d
3 files changed
+23 -4

No files matched your search

+4 -1
View File
@@ -3,7 +3,9 @@ name: Portability report
# Lists lines a pull request adds that contain values tied to one machine, network or account
# (credentials, home paths, temporary paths, network addresses, email addresses). Findings never
# fail the job; the author reads the report and decides what to change. An operational error (for
# example a git failure) does fail it. See scripts/portability-report.mjs.
# example a git failure) does fail it. The repository is public, so this summary lists file and
# line only; authors see the matched text when they run the report locally or on push.
# See scripts/portability-report.mjs.
on:
pull_request:
@@ -27,4 +29,5 @@ jobs:
node scripts/portability-report.mjs
--from ${{ github.event.pull_request.base.sha }}
--to ${{ github.event.pull_request.head.sha }}
--locations-only
--out "$GITHUB_STEP_SUMMARY"
+11 -3
View File
@@ -16,6 +16,7 @@
// node scripts/portability-report.mjs --from A --to B # a commit range
// node scripts/portability-report.mjs --staged # what is staged for the next commit
// add --out report.md to also write the report to a file
// add --locations-only to list file and line without quoting the matched text (for public CI output)
import { execFileSync } from "node:child_process";
import { writeFileSync } from "node:fs";
@@ -79,7 +80,7 @@ export function findPortabilityIssues(lines, checks = CHECKS) {
return findings;
}
export function renderReport(findings, label) {
export function renderReport(findings, label, { locationsOnly = false } = {}) {
const out = [`# Portability report: ${label}`, ""];
if (findings.length === 0) {
out.push("No matching machine-specific values detected.");
@@ -105,6 +106,10 @@ export function renderReport(findings, label) {
if (group.length === 0) continue;
out.push(`## ${check.category} (${group.length})`, "", `_${check.why}_`, "");
for (const { file, line, match, text } of group) {
if (locationsOnly) {
out.push(`- \`${file}:${line}\``);
continue;
}
if (check.category === "Credential") {
out.push(`- \`${file}:${line}\` matched \`${match.slice(0, 6)}…\` (value withheld)`);
continue;
@@ -120,10 +125,11 @@ export function renderReport(findings, label) {
}
function parseArguments(argv) {
const options = { staged: false };
const options = { staged: false, locationsOnly: false };
for (let index = 0; index < argv.length; index += 1) {
const key = argv[index];
if (key === "--staged") options.staged = true;
else if (key === "--locations-only") options.locationsOnly = true;
else if (["--from", "--to", "--out", "--repo"].includes(key)) options[key.slice(2)] = argv[++index];
else throw new Error(`Unknown argument: ${key}`);
}
@@ -149,7 +155,9 @@ export function main(argv = process.argv.slice(2)) {
label = `${from.slice(0, 8)}..${to.length > 12 ? to.slice(0, 8) : to}`;
}
const diff = git(repo, ["diff", "-U0", "--no-color", "--diff-filter=ACMR", ...range]);
const report = renderReport(findPortabilityIssues(addedLines(diff)), label);
const report = renderReport(findPortabilityIssues(addedLines(diff)), label, {
locationsOnly: options.locationsOnly,
});
process.stdout.write(report);
if (options.out) writeFileSync(options.out, report);
return 0;
+8
View File
@@ -82,6 +82,14 @@ test("a credential on the same line as another finding is withheld from every ca
assert.match(report, /100\.95\.1\.2/);
});
test("locations-only output names file and line without quoting the matched text", () => {
const findings = findPortabilityIssues(addedLines(diff));
const report = renderReport(findings, "x..y", { locationsOnly: true });
assert.match(report, /## Home path \(1\)/);
assert.match(report, /- `docs\/a\.md:10`/);
assert.ok(!report.includes("/Users/alice/"), report);
});
test("the report says so when nothing is found and groups findings when something is", () => {
assert.match(renderReport([], "x..y"), /No matching machine-specific values detected/);
const report = renderReport(findPortabilityIssues(addedLines(diff)), "x..y");