Skip to content

Commit d4e579e

Browse files
Use package version for action install default
Signed-off-by: jmclaughlin724 <31931302+jmclaughlin724@users.noreply.github.com>
1 parent 4a5ead1 commit d4e579e

5 files changed

Lines changed: 86 additions & 19 deletions

File tree

action.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@ inputs:
99
description: JSON array of argv entries passed to supaschema, excluding the binary name. Use ["scan","--reporter","json"] for PR comments and check runs.
1010
required: true
1111
version:
12-
description: Exact supaschema npm version to run.
12+
description: Exact supaschema npm version to run. Defaults to this action tag's package.json version.
1313
required: false
14-
default: "0.3.0"
1514
runs:
1615
using: composite
1716
steps:

docs/release.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ The package is designed for trusted publishing from GitHub Actions. `main` is th
2222
## Per-release checklist
2323

2424
1. Add changesets for user-facing PRs while the change is fresh.
25-
2. Run `npm run release:version` for the release PR and review the resulting `package.json`, `package-lock.json`, `CHANGELOG.md`, and `action.yml` changes.
25+
2. Run `npm run release:version` for the release PR and review the resulting `package.json`, `package-lock.json`, and `CHANGELOG.md` changes.
2626
3. Run `npm run release:notes -- --version <version>` and confirm the output is the GitHub Release body you want.
2727
4. Run `npm run release:verify`.
2828
5. Confirm PR CI passes all required checks before merge.

scripts/actions/run-supaschema-action.mjs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,27 @@ import { fileURLToPath } from "node:url";
55

66
const scanReportMarker = "<!-- supaschema:scan-report -->";
77
const defaultApiUrl = "https://api.github.com";
8+
const packageJsonPath = fileURLToPath(new URL("../../package.json", import.meta.url));
89

910
export function validateExactVersion(version) {
1011
if (typeof version !== "string" || !isExactVersion(version)) {
11-
throw new Error(
12-
`invalid supaschema version: ${version} (use an exact npm version, e.g. 0.3.0)`
13-
);
12+
throw new Error(`invalid supaschema version: ${version} (use an exact npm version)`);
1413
}
1514
return version;
1615
}
1716

17+
export function readPackageVersion(readFile = readFileSync) {
18+
const packageJson = JSON.parse(readFile(packageJsonPath, "utf8"));
19+
return validateExactVersion(packageJson.version);
20+
}
21+
22+
export function resolveActionVersion(version, readFile = readFileSync) {
23+
if (version === undefined || version.length === 0) {
24+
return readPackageVersion(readFile);
25+
}
26+
return validateExactVersion(version);
27+
}
28+
1829
function isExactVersion(version) {
1930
const plusParts = version.split("+");
2031
if (plusParts.length > 2) {
@@ -106,7 +117,7 @@ export async function runAction({
106117
platform = process.platform,
107118
spawnImpl = spawn,
108119
} = {}) {
109-
const version = validateExactVersion(env.SUPASCHEMA_ACTION_VERSION);
120+
const version = resolveActionVersion(env.SUPASCHEMA_ACTION_VERSION, readFile);
110121
const argv = parseActionArgv(env.SUPASCHEMA_ACTION_ARGV);
111122
const command = npxCommand(platform);
112123
const args = buildNpxArgs(version, argv);

scripts/guards/check-release-version-surfaces.mjs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,13 @@ const action = parseYaml(actionText);
3030
const actionVersionInput = action?.inputs?.version;
3131
assert(actionVersionInput, "action.yml must declare inputs.version");
3232
assert(
33-
actionVersionInput.default === version,
34-
`action.yml inputs.version.default must match package.json version ${version}`
33+
actionVersionInput.default === undefined,
34+
"action.yml inputs.version.default must stay unset; the runner defaults from package.json"
3535
);
3636
assert(
3737
typeof actionVersionInput.description === "string" &&
38-
actionVersionInput.description.includes("Exact supaschema npm version"),
38+
actionVersionInput.description.includes("Exact supaschema npm version") &&
39+
actionVersionInput.description.includes("package.json version"),
3940
"action.yml inputs.version.description must require an exact supaschema npm version"
4041
);
4142
assert(
@@ -48,8 +49,13 @@ assert(
4849
"supaschema action runner version validation must tell users to use an exact npm version"
4950
);
5051
assert(
51-
actionRunnerText.includes(`e.g. ${version}`),
52-
`supaschema action runner exact-version example must use package.json version ${version}`
52+
actionRunnerText.includes("../../package.json") &&
53+
actionRunnerText.includes("resolveActionVersion"),
54+
"supaschema action runner must default the action version from package.json"
55+
);
56+
assert(
57+
!actionRunnerText.includes(`e.g. ${version}`),
58+
"supaschema action runner must not duplicate package.json version in validation text"
5359
);
5460
assert(
5561
!actionRunnerText.includes("latest|next"),

tests/action.test.ts

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,25 +9,32 @@ import {
99
parseScanReport,
1010
publishActionReport,
1111
renderActionScanMarkdown,
12+
resolveActionVersion,
1213
runAction,
1314
validateExactVersion,
1415
} from "../scripts/actions/run-supaschema-action.mjs";
1516

1617
const githubExpression = (name: string) => `${"$"}{{ ${name} }}`;
1718
const shellParameter = (name: string) => `${"$"}{${name}}`;
19+
const explicitVersion = "1.2.3";
1820

1921
describe("composite action", () => {
20-
it("defaults to the pinned package version, not an npm dist-tag", () => {
22+
it("defaults to package.json version, not an action metadata literal or npm dist-tag", () => {
2123
const root = resolve(import.meta.dirname, "..");
2224
const action = readFileSync(resolve(root, "action.yml"), "utf8");
2325
const actionRunner = readFileSync(
2426
resolve(root, "scripts/actions/run-supaschema-action.mjs"),
2527
"utf8"
2628
);
2729
const packageJson = JSON.parse(readFileSync(resolve(root, "package.json"), "utf8"));
30+
const actionMetadata = parse(action);
2831

29-
expect(action).toContain(`default: "${packageJson.version}"`);
32+
expect(actionMetadata.inputs?.version?.default).toBeUndefined();
33+
expect(resolveActionVersion(undefined)).toBe(packageJson.version);
34+
expect(resolveActionVersion("")).toBe(packageJson.version);
3035
expect(actionRunner).toContain("use an exact npm version");
36+
expect(actionRunner).toContain("../../package.json");
37+
expect(actionRunner).not.toContain(`e.g. ${packageJson.version}`);
3138
expect(action).not.toContain("default: latest");
3239
expect(action).not.toContain("latest|next");
3340
});
@@ -73,9 +80,9 @@ describe("composite action", () => {
7380
"--fail-on-diff",
7481
"--quiet",
7582
]);
76-
expect(buildNpxArgs("0.2.3", ["diff", "--fail-on-diff", "--quiet"])).toEqual([
83+
expect(buildNpxArgs(explicitVersion, ["diff", "--fail-on-diff", "--quiet"])).toEqual([
7784
"--yes",
78-
"supaschema@0.2.3",
85+
`supaschema@${explicitVersion}`,
7986
"diff",
8087
"--fail-on-diff",
8188
"--quiet",
@@ -112,7 +119,7 @@ describe("composite action", () => {
112119
const code = await runAction({
113120
env: {
114121
SUPASCHEMA_ACTION_ARGV: '["sync","--target","remote"]',
115-
SUPASCHEMA_ACTION_VERSION: "0.2.4",
122+
SUPASCHEMA_ACTION_VERSION: explicitVersion,
116123
},
117124
platform: "linux",
118125
spawnImpl,
@@ -122,16 +129,60 @@ describe("composite action", () => {
122129
expect(captured?.args).toEqual([
123130
"npx",
124131
"--yes",
125-
"supaschema@0.2.4",
132+
`supaschema@${explicitVersion}`,
126133
"sync",
127134
"--target",
128135
"remote",
129136
]);
130137
expect(captured?.options.shell).toBe(false);
131-
expect(captured?.env?.SUPASCHEMA_ACTION_VERSION).toBe("0.2.4");
138+
expect(captured?.env?.SUPASCHEMA_ACTION_VERSION).toBe(explicitVersion);
132139
expect(captured?.env?.SUPASCHEMA_REMOTE_SYNC_APPROVED).toBeUndefined();
133140
});
134141

142+
it("uses package.json version when action version input is omitted", async () => {
143+
const packageJson = JSON.parse(
144+
readFileSync(resolve(import.meta.dirname, "..", "package.json"), "utf8")
145+
);
146+
let captured:
147+
| {
148+
args: string[];
149+
options: { shell?: boolean };
150+
}
151+
| undefined;
152+
const spawnImpl = (
153+
command: string,
154+
args: string[],
155+
options: { env?: NodeJS.ProcessEnv; shell?: boolean }
156+
) => {
157+
captured = { args: [command, ...args], options };
158+
return {
159+
on(event: string, handler: (code: number) => void) {
160+
if (event === "exit") {
161+
queueMicrotask(() => handler(0));
162+
}
163+
return this;
164+
},
165+
};
166+
};
167+
168+
const code = await runAction({
169+
env: {
170+
SUPASCHEMA_ACTION_ARGV: '["--version"]',
171+
},
172+
platform: "linux",
173+
spawnImpl,
174+
});
175+
176+
expect(code).toBe(0);
177+
expect(captured?.args).toEqual([
178+
"npx",
179+
"--yes",
180+
`supaschema@${packageJson.version}`,
181+
"--version",
182+
]);
183+
expect(captured?.options.shell).toBe(false);
184+
});
185+
135186
it("renders a scan report for GitHub surfaces", () => {
136187
const report = scanReport();
137188
const parsed = parseScanReport(JSON.stringify(report));

0 commit comments

Comments
 (0)