65 lines
2.4 KiB
JavaScript
65 lines
2.4 KiB
JavaScript
#!/usr/bin/env node
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const SENTRY_INSTALLER_PATH = "infra/sentry/install.sh";
|
|
const SENTRY_PIN_DOC_PATH = "infra/sentry/UPSTREAM.md";
|
|
|
|
export function inspectSentryPin(installer, pinDocument) {
|
|
const failures = [];
|
|
const passes = [];
|
|
const commit = installer.match(/^UPSTREAM_COMMIT="([0-9a-f]{40})"$/m)?.[1];
|
|
|
|
if (!commit) {
|
|
failures.push(`${SENTRY_INSTALLER_PATH}: UPSTREAM_COMMIT must be a full 40-character commit`);
|
|
return { failures, passes };
|
|
}
|
|
|
|
const requiredInstallerFragments = [
|
|
`fetch --depth 1 origin "\${UPSTREAM_COMMIT}"`,
|
|
`checkout --quiet --detach "\${UPSTREAM_COMMIT}"`,
|
|
`ACTUAL_COMMIT="$(git -C "\${UPSTREAM_DIR}" rev-parse --verify HEAD)"`,
|
|
`[[ "\${ACTUAL_COMMIT}" != "\${UPSTREAM_COMMIT}" ]]`,
|
|
];
|
|
for (const fragment of requiredInstallerFragments) {
|
|
if (installer.includes(fragment)) {
|
|
passes.push(`${SENTRY_INSTALLER_PATH}: enforces immutable upstream commit`);
|
|
} else {
|
|
failures.push(`${SENTRY_INSTALLER_PATH}: missing immutable-pin guard: ${fragment}`);
|
|
}
|
|
}
|
|
|
|
if (/git\s+clone[\s\S]{0,200}--branch\s+"?\$?\{?UPSTREAM_TAG/.test(installer)) {
|
|
failures.push(`${SENTRY_INSTALLER_PATH}: must not execute an upstream tag checkout`);
|
|
} else {
|
|
passes.push(`${SENTRY_INSTALLER_PATH}: does not execute a mutable tag checkout`);
|
|
}
|
|
|
|
if (pinDocument.includes(commit)) {
|
|
passes.push(`${SENTRY_PIN_DOC_PATH}: documents immutable upstream commit`);
|
|
} else {
|
|
failures.push(`${SENTRY_PIN_DOC_PATH}: must document ${commit}`);
|
|
}
|
|
|
|
return { failures, passes };
|
|
}
|
|
|
|
export function verifyUpstreamSourcePins(rootDir = process.cwd()) {
|
|
return inspectSentryPin(
|
|
fs.readFileSync(path.join(rootDir, SENTRY_INSTALLER_PATH), "utf8"),
|
|
fs.readFileSync(path.join(rootDir, SENTRY_PIN_DOC_PATH), "utf8"),
|
|
);
|
|
}
|
|
|
|
const isCli = process.argv[1] && fileURLToPath(import.meta.url) === path.resolve(process.argv[1]);
|
|
if (isCli) {
|
|
const result = verifyUpstreamSourcePins();
|
|
for (const failure of result.failures) process.stderr.write(`FAIL ${failure}\n`);
|
|
process.stdout.write(
|
|
`${result.failures.length === 0 ? "PASS" : "FAIL"} upstream source pin verification\n` +
|
|
`Summary: ${result.passes.length} checks passed, ${result.failures.length} failures\n`,
|
|
);
|
|
if (result.failures.length > 0) process.exitCode = 1;
|
|
}
|