Skip to content

Commit bee9891

Browse files
committed
Add build plugin to check Node versions
1 parent f4d0a7a commit bee9891

1 file changed

Lines changed: 60 additions & 2 deletions

File tree

build.mjs

Lines changed: 60 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { fileURLToPath } from "node:url";
44

55
import * as esbuild from "esbuild";
66
import { globSync } from "glob";
7+
import * as yaml from "js-yaml";
78

89
import pkg from "./package.json" with { type: "json" };
910

@@ -27,6 +28,57 @@ const cleanPlugin = {
2728
},
2829
};
2930

31+
/** A plugin that checks that the Node versions in all `action.yml` files are the same. */
32+
const checkNodeVersionsPlugin = {
33+
name: "check-node-versions",
34+
setup(build) {
35+
build.onStart(async () => {
36+
// Find all the `action.yml` files. We don't care about the stub in the repository root,
37+
// since that is a `composite` action.
38+
const actionSpecifications = globSync("*/action.yml");
39+
40+
// Track the Node versions we find for each file.
41+
const nodeVersions = {};
42+
43+
// We will store the first Node version we find and use it to compare against the others.
44+
// If there's any disagreement, we set `versionMismatch` to `true` and throw an error
45+
// that includes all the discovered Node versions at the end.
46+
let nodeVersion = undefined;
47+
let versionMismatch = false;
48+
49+
for (const actionSpecification of actionSpecifications) {
50+
// Read the contents of the action.yml file.
51+
const contents = await readFile(actionSpecification, "utf-8");
52+
const specification = yaml.load(contents);
53+
54+
// Find the `runs.using` value in the specification.
55+
const using = specification.runs.using;
56+
if (using === undefined) {
57+
throw new Error(
58+
`Couldn't find 'runs.using' in ${actionSpecification}`,
59+
);
60+
}
61+
62+
if (nodeVersion === undefined) {
63+
// First one we found: set it as the baseline.
64+
nodeVersion = using;
65+
} else if (nodeVersion !== using) {
66+
// Disagreement: set `versionMismatch` to indicate that we should throw an error later.
67+
versionMismatch = true;
68+
}
69+
nodeVersions[actionSpecification] = using;
70+
}
71+
72+
// Throw an error if there was a version mismatch.
73+
if (versionMismatch) {
74+
throw new Error(
75+
`More than one node version used in 'action.yml' files: ${JSON.stringify(nodeVersions)}`,
76+
);
77+
}
78+
});
79+
},
80+
};
81+
3082
/**
3183
* Copy defaults.json to the output directory since other projects depend on it.
3284
*
@@ -78,7 +130,7 @@ const UPLOAD_LIB_SRC = "./src/upload-lib";
78130
*
79131
* The virtual module additionally re-exports `upload-lib` under the `uploadLib` namespace so that
80132
* external consumers can access it via the small `lib/upload-lib.js` stub emitted below.
81-
*
133+
*
82134
* A tiny stub file is emitted for each Action entrypoint, and one for `upload-lib`. Each stub
83135
* imports the shared bundle and calls/re-exports from the respective entry point.
84136
*
@@ -208,7 +260,13 @@ const context = await esbuild.context({
208260
outdir: OUT_DIR,
209261
platform: "node",
210262
external: ["./entry-points"],
211-
plugins: [cleanPlugin, copyDefaultsPlugin, entryPointsPlugin, onEndPlugin],
263+
plugins: [
264+
cleanPlugin,
265+
checkNodeVersionsPlugin,
266+
copyDefaultsPlugin,
267+
entryPointsPlugin,
268+
onEndPlugin,
269+
],
212270
target: ["node20"],
213271
define: {
214272
__CODEQL_ACTION_VERSION__: JSON.stringify(pkg.version),

0 commit comments

Comments
 (0)