Files
purpur-potato/scripts/workflow.test.ts
T
dmg 6b07d3bf87
Release / release (push) Successful in 9m13s
CI / build (push) Successful in 50s
feat(potato): add native poisonous potato throws and releases
2026-09-18 08:06:50 -04:00

200 lines
13 KiB
TypeScript

import assert from "node:assert/strict";
import { spawnSync } from "node:child_process";
import { mkdtempSync, mkdirSync, readFileSync, writeFileSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join, resolve } from "node:path";
import { test } from "node:test";
const root = resolve(".");
const sha = "a".repeat(40);
const fixture = "synthetic-workflow-credential";
function workflow(name: string): string { return readFileSync(join(root, `.gitea/workflows/${name}.yml`), "utf8"); }
function step(name: string, title: string): string {
const value = workflow(name).split(" - name: ").find(block => block.startsWith(title + "\n"));
assert.ok(value, `Missing workflow step: ${title}`);
return value;
}
function script(name: string, title: string): string {
const block = step(name, title);
const run = block.split(" run: ")[1];
assert.ok(run, `Missing run body: ${title}`);
return run.startsWith("|\n") ? run.slice(2).split("\n").map(line => line.replace(/^ /, "")).join("\n") : run.trim();
}
function sandbox(body: (dir: string) => void): void {
const dir = mkdtempSync(join(tmpdir(), "potato-workflow-"));
try { body(dir); } finally { rmSync(dir, { recursive: true, force: true }); }
}
function fake(dir: string, command: string, source: string): void {
mkdirSync(join(dir, "bin"), { recursive: true });
writeFileSync(join(dir, "bin", command), `#!${process.execPath}\n${source}`, { mode: 0o700 });
}
function shell(dir: string, source: string, env: NodeJS.ProcessEnv = {}) {
return spawnSync("/bin/sh", ["-eu", "-c", source], { cwd: dir, encoding: "utf8", env: {
PATH: `${join(dir, "bin")}:${process.env.PATH}`, HOME: dir, GIT_CONFIG_NOSYSTEM: "1",
GIT_CONFIG_GLOBAL: "/dev/null", GITHUB_WORKSPACE: root, GITHUB_OUTPUT: join(dir, "output"), ...env,
} });
}
test("CI runs the full check and commitlint with inert SHA arguments and SHA-named artifacts", () => {
sandbox(dir => {
writeFileSync(join(dir, "build-args"), "");
writeFileSync(join(dir, "gradlew"), '#!/bin/sh\nprintf "%s\\n" "$@" > build-args\n', { mode: 0o700 });
assert.equal(shell(dir, script("ci", "Build and test")).status, 0);
assert.equal(readFileSync(join(dir, "build-args"), "utf8"), "clean\ncheck\njar\n");
fake(dir, "npx", `require('node:fs').writeFileSync('lint-args', JSON.stringify(process.argv.slice(2)));`);
const child = shell(dir, script("ci", "Validate conventional commits"), { BASE_SHA: "b".repeat(40), HEAD_SHA: sha });
assert.equal(child.status, 0, child.stderr);
const args = JSON.parse(readFileSync(join(dir, "lint-args"), "utf8"));
assert.deepEqual(args.slice(-6), ["--from", "b".repeat(40), "--to", sha, "--extends", "@commitlint/config-conventional"]);
assert.match(step("ci", "Validate conventional commits"), /if: github.event_name == 'pull_request'/);
assert.match(step("ci", "Upload development artifact"), /name: purpur-potato-\$\{\{ github.sha \}\}/);
assert.match(step("ci", "Upload development artifact"), /path: build\/libs\/purpur-potato-\*\.jar/);
assert.match(step("ci", "Upload development artifact"), /if-no-files-found: error/);
assert.match(workflow("ci"), /java-version: 25/);
assert.match(workflow("ci"), /node-version: 20/);
});
});
test("release performs full snapshot and versioned checks and gates versioned artifacts on a new release", () => sandbox(dir => {
writeFileSync(join(dir, "build-args"), "");
writeFileSync(join(dir, "gradlew"), '#!/bin/sh\nprintf "%s\\n" "$@" > build-args\n', { mode: 0o700 });
assert.equal(shell(dir, script("release", "Build and test before release")).status, 0);
assert.equal(readFileSync(join(dir, "build-args"), "utf8"), "clean\ncheck\njar\n");
assert.equal(shell(dir, script("release", "Verify versioned plugin and release tooling"), { VERSION: "1.2.3" }).status, 0);
assert.equal(readFileSync(join(dir, "build-args"), "utf8"), "clean\ncheck\njar\n-PreleaseVersion=1.2.3\n");
for (const title of ["Verify versioned plugin and release tooling", "Upload release workflow artifact"]) {
assert.match(step("release", title), /if: steps.release.outputs.created == 'true'/);
}
const release = workflow("release");
assert.ok(release.indexOf("Build and test before release") < release.indexOf("Compute and push"));
assert.ok(release.indexOf("Capture previous tag") < release.indexOf("Compute and push"));
assert.ok(release.indexOf("Verify versioned") < release.indexOf("Upload release workflow artifact"));
assert.match(release, /branches: \[main\]/);
assert.match(release, /group: potato-release\n cancel-in-progress: false/);
assert.match(step("release", "Upload release workflow artifact"), /path: build\/libs\/purpur-potato-\$\{\{ steps.release.outputs.version \}\}\.jar/);
}));
for (const scenario of ["new", "none", "unchanged", "wrong-source", "invalid-tag"] as const) {
test(`release resolution proves exact source and does not claim no-release publication: ${scenario}`, () => sandbox(dir => {
const init = shell(dir, "git init -q; git -c user.name=Fixture -c user.email=fixture@example.invalid commit --allow-empty -qm 'feat: fixture'");
assert.equal(init.status, 0, init.stderr);
if (scenario === "unchanged") assert.equal(shell(dir, "git tag v1.2.3").status, 0);
writeFileSync(join(dir, "output"), "");
const previous = shell(dir, script("release", "Capture previous tag"));
assert.equal(previous.status, 0, previous.stderr);
const previousOutput = readFileSync(join(dir, "output"), "utf8");
assert.equal(previousOutput, scenario === "unchanged" ? "tag=v1.2.3\n" : "tag=\n");
writeFileSync(join(dir, "output"), "");
if (scenario === "new" || scenario === "wrong-source") assert.equal(shell(dir, "git tag v1.2.3").status, 0);
if (scenario === "invalid-tag") assert.equal(shell(dir, "git tag v01.2.3-unsupported").status, 0);
const head = shell(dir, "git rev-parse HEAD").stdout.trim();
const child = shell(dir, script("release", "Resolve newly created exact-source release"), {
PREVIOUS_TAG: scenario === "unchanged" ? "v1.2.3" : "", EXPECTED_COMMIT: scenario === "wrong-source" ? sha : head,
});
const output = readFileSync(join(dir, "output"), "utf8");
if (scenario === "wrong-source" || scenario === "invalid-tag") {
assert.notEqual(child.status, 0);
assert.ok(!output.includes("created=true"));
} else {
assert.equal(child.status, 0, child.stderr);
assert.equal(output, scenario === "new" ? "created=true\nversion=1.2.3\n" : "created=false\n");
}
}));
}
const forbiddenEnv = [
"GIT_CREDENTIALS", "GH_TOKEN", "GITHUB_TOKEN", "GL_TOKEN", "GITLAB_TOKEN", "BB_TOKEN", "BITBUCKET_TOKEN",
"BB_TOKEN_BASIC_AUTH", "BITBUCKET_TOKEN_BASIC_AUTH", "DEBUG", "NODE_DEBUG", "GIT_TRACE", "GIT_TRACE_CURL",
"GIT_CURL_VERBOSE", "GIT_TRACE_PACKET", "GIT_TRACE_SETUP", "GIT_TRACE2", "GIT_TRACE2_EVENT", "GIT_TRACE2_PERF",
];
test("publication invokes only the in-process publisher with no secret argv or tracing", () => sandbox(dir => {
assert.equal(shell(dir, "git init -q; git -c user.name=Fixture -c user.email=fixture@example.invalid commit --allow-empty -qm 'feat: fixture'").status, 0);
writeFileSync(join(dir, "publish-command"), "null");
fake(dir, "node", `
const assert = require('node:assert/strict');
for (const key of ${JSON.stringify(forbiddenEnv)}) assert.equal(process.env[key], undefined, key);
assert.equal(process.env.RELEASE_CREDENTIAL, ${JSON.stringify(fixture)});
assert.match(process.env.RELEASE_NOTES, /feat: fixture/);
require('node:fs').writeFileSync('publish-command', JSON.stringify(process.argv.slice(2)));
`);
const child = shell(dir, script("release", "Publish verified JAR through a draft release"), {
RELEASE_CREDENTIAL: fixture, PREVIOUS_TAG: "",
...Object.fromEntries(forbiddenEnv.map(key => [key, key.includes("TOKEN") ? fixture : "1"])),
});
assert.equal(child.status, 0, child.stderr);
assert.deepEqual(JSON.parse(readFileSync(join(dir, "publish-command"), "utf8")), ["build/release-tools/publish-release.js"]);
assert.ok(![child.stdout, child.stderr].join("").includes(fixture));
assert.match(step("release", "Publish verified JAR through a draft release"), /if: steps.release.outputs.created == 'true'/);
assert.ok(workflow("release").indexOf("Verify versioned") < workflow("release").indexOf("Publish verified"));
assert.doesNotMatch(workflow("release"), /curl|secrets\.RELEASE_TOKEN[^\n]*(?:curl|git|node)/);
}));
test("semantic tagging keeps the dummy credential only in helper environment, never argv, URLs or diagnostics", () => {
sandbox(dir => {
assert.equal(shell(dir, "git init -q").status, 0);
writeFileSync(join(dir, "tag-command"), "null");
fake(dir, "npx", `
const assert = require('node:assert/strict');
for (const key of ${JSON.stringify(forbiddenEnv)}) assert.equal(process.env[key], undefined, key);
assert.equal(process.env.RELEASE_CREDENTIAL, ${JSON.stringify(fixture)});
assert.equal(process.env.GIT_TERMINAL_PROMPT, '0');
require('node:fs').writeFileSync('tag-command', JSON.stringify(process.argv.slice(2)));
`);
const child = shell(dir, script("release", "Compute and push semantic release tag"), {
RELEASE_CREDENTIAL: fixture, REPOSITORY: "dmg/purpur-potato",
...Object.fromEntries(forbiddenEnv.map(key => [key, key.includes("TOKEN") ? fixture : "1"])),
});
assert.equal(child.status, 0, child.stderr);
const args = JSON.parse(readFileSync(join(dir, "tag-command"), "utf8"));
assert.ok(Array.isArray(args), "Must actually invoke semantic-release");
assert.ok(args.includes("semantic-release@24.2.9"));
assert.ok(args.includes("@semantic-release/commit-analyzer@13.0.1"));
assert.ok(args.includes("@semantic-release/release-notes-generator@14.1.0"));
assert.equal(args[args.indexOf("--repository-url") + 1], "https://git.garvis.dev/dmg/purpur-potato.git");
const config = shell(dir, "git config --local --list");
assert.match(config.stdout, /credential.usehttppath=true/);
assert.match(config.stdout, /http.followredirects=false/);
assert.ok(config.stdout.includes(`credential.helper=${root}/scripts/git-credential.sh`));
assert.ok(![JSON.stringify(args), config.stdout, child.stdout, child.stderr].join("").includes(fixture));
});
});
for (const env of [{ RELEASE_CREDENTIAL: "", REPOSITORY: "dmg/purpur-potato" },
{ RELEASE_CREDENTIAL: fixture, REPOSITORY: "evil/purpur-potato" }]) {
test(`tagging refuses missing credential or wrong repository: ${env.REPOSITORY}`, () => sandbox(dir => {
fake(dir, "npx", "process.exit(90);");
const child = shell(dir, script("release", "Compute and push semantic release tag"), env);
assert.notEqual(child.status, 0);
assert.notEqual(child.status, 90);
assert.ok(!child.stderr.includes(fixture));
}));
}
for (const name of ["ci", "release"]) {
test(`${name} rejects multiline source SHAs before invoking Git`, () => sandbox(dir => {
writeFileSync(join(dir, "calls"), "");
fake(dir, "git", `require('node:fs').appendFileSync('calls', 'called');`);
const child = shell(dir, script(name, "Checkout public source without a credential"), { SOURCE_SHA: `${sha}\nmalformed` });
assert.notEqual(child.status, 0);
assert.equal(readFileSync(join(dir, "calls"), "utf8"), "");
}));
}
for (const name of ["ci", "release"]) test(`${name} anonymously fetches full history and exact source without credentials or redirects`, () => {
sandbox(dir => {
writeFileSync(join(dir, "calls"), "");
fake(dir, "git", `require('node:fs').appendFileSync('calls', JSON.stringify(process.argv.slice(2))+'\\n');`);
const child = shell(dir, script(name, "Checkout public source without a credential"), { SOURCE_SHA: sha });
assert.equal(child.status, 0, child.stderr);
const calls = readFileSync(join(dir, "calls"), "utf8").trim().split("\n").filter(Boolean).map(line => JSON.parse(line));
assert.ok(calls.some(args => JSON.stringify(args) === JSON.stringify(["remote", "add", "origin", "https://git.garvis.dev/dmg/purpur-potato.git"])));
for (const [key, value] of [["credential.helper", ""], ["http.extraHeader", ""], ["http.followRedirects", "false"]]) {
assert.ok(calls.some(args => JSON.stringify(args) === JSON.stringify(["config", "--local", key, value])));
}
assert.ok(calls.some(args => JSON.stringify(args) === JSON.stringify(["fetch", "--force", "--tags", "origin", "+refs/heads/*:refs/remotes/origin/*"])));
assert.deepEqual(calls.at(-1), name === "ci" ? ["checkout", "--detach", sha] : ["checkout", "-B", "main", sha]);
assert.doesNotMatch(step(name, "Checkout public source without a credential"), /secrets\.|token:/);
});
});