Skip to content

Commit 8f7a2dd

Browse files
committed
Move upgrade-bundle.ts to pr-checks and add tests
1 parent 78e2769 commit 8f7a2dd

5 files changed

Lines changed: 152 additions & 82 deletions

File tree

.github/actions/update-bundle/action.yml

Lines changed: 0 additions & 14 deletions
This file was deleted.

.github/actions/update-bundle/index.ts

Lines changed: 0 additions & 67 deletions
This file was deleted.

.github/workflows/update-bundle.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ jobs:
5050
run: npm ci
5151

5252
- name: Update bundle
53-
uses: ./.github/actions/update-bundle
53+
run: npx tsx pr-checks/update-bundle.ts
5454

5555
- name: Set up CodeQL CLI from new bundle
5656
id: setup-codeql

pr-checks/update-bundle.test.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Tests for the update-bundle.ts script.
3+
*/
4+
5+
import * as assert from "node:assert/strict";
6+
import { describe, it } from "node:test";
7+
8+
import { Defaults, getNewDefaults } from "./update-bundle";
9+
10+
const testDefaults: Defaults = {
11+
bundleVersion: "codeql-bundle-v2.26.2",
12+
cliVersion: "2.26.2",
13+
priorBundleVersion: "codeql-bundle-v2.26.1",
14+
priorCliVersion: "2.26.1",
15+
};
16+
17+
describe("getNewDefaults", async () => {
18+
await it("throws if there is no cli-version-*.txt asset", async () => {
19+
assert.throws(
20+
() => getNewDefaults({ tag_name: "foo", assets: [] }, testDefaults),
21+
{ message: "Failed to find the CodeQL CLI version for release foo." },
22+
);
23+
});
24+
25+
await it("throws if there are multiple cli-version-*.txt assets", async () => {
26+
assert.throws(
27+
() =>
28+
getNewDefaults(
29+
{
30+
tag_name: "foo",
31+
assets: [
32+
{ name: "cli-version-foo.txt" },
33+
{ name: "cli-version-bar.txt" },
34+
],
35+
},
36+
testDefaults,
37+
),
38+
{ message: "Release foo has multiple CLI version marker files." },
39+
);
40+
});
41+
42+
await it("finds the new bundle info", async () => {
43+
const newDefaults = getNewDefaults(
44+
{
45+
tag_name: "foo",
46+
assets: [{ name: "cli-version-1.2.3.txt" }],
47+
},
48+
testDefaults,
49+
);
50+
51+
assert.deepEqual(newDefaults, {
52+
bundleVersion: "foo",
53+
cliVersion: "1.2.3",
54+
priorBundleVersion: testDefaults.bundleVersion,
55+
priorCliVersion: testDefaults.cliVersion,
56+
} satisfies Defaults);
57+
});
58+
});

pr-checks/update-bundle.ts

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#!/usr/bin/env npx tsx
2+
3+
/** Updates 'src/defaults.json' to point to a new CodeQL bundle release. */
4+
5+
import * as fs from "fs";
6+
7+
import * as github from "@actions/github";
8+
9+
import * as defaults from "../src/defaults.json";
10+
11+
import { DEFAULTS_FILE } from "./config";
12+
13+
interface BundleInfo {
14+
bundleVersion: string;
15+
cliVersion: string;
16+
}
17+
18+
export type Defaults = typeof defaults;
19+
20+
interface Release {
21+
tag_name: string;
22+
assets: Array<{
23+
name: string;
24+
}>;
25+
}
26+
27+
function getCodeQLCliVersionForRelease(release: Release): string {
28+
// We do not currently tag CodeQL bundles based on the CLI version they contain.
29+
// Instead, we use a marker file `cli-version-<version>.txt` to record the CLI version.
30+
// This marker file is uploaded as a release asset for all new CodeQL bundles.
31+
const cliVersionsFromMarkerFiles = release.assets
32+
.map((asset) => asset.name.match(/cli-version-(.*)\.txt/)?.[1])
33+
.filter((v) => v)
34+
.map((v) => v as string);
35+
if (cliVersionsFromMarkerFiles.length > 1) {
36+
throw new Error(
37+
`Release ${release.tag_name} has multiple CLI version marker files.`,
38+
);
39+
} else if (cliVersionsFromMarkerFiles.length === 0) {
40+
throw new Error(
41+
`Failed to find the CodeQL CLI version for release ${release.tag_name}.`,
42+
);
43+
}
44+
return cliVersionsFromMarkerFiles[0];
45+
}
46+
47+
function getBundleInfoFromRelease(release: Release): BundleInfo {
48+
return {
49+
bundleVersion: release.tag_name,
50+
cliVersion: getCodeQLCliVersionForRelease(release),
51+
};
52+
}
53+
54+
export function getNewDefaults(
55+
release: Release,
56+
currentDefaults: Defaults,
57+
): Defaults {
58+
console.log(
59+
"Updating default bundle as a result of the following release: " +
60+
`${JSON.stringify(release)}.`,
61+
);
62+
63+
const bundleInfo = getBundleInfoFromRelease(release);
64+
65+
return {
66+
bundleVersion: bundleInfo.bundleVersion,
67+
cliVersion: bundleInfo.cliVersion,
68+
priorBundleVersion: currentDefaults.bundleVersion,
69+
priorCliVersion: currentDefaults.cliVersion,
70+
};
71+
}
72+
73+
function main() {
74+
const release: Release = github.context.payload.release;
75+
76+
if (release === undefined) {
77+
console.error(`Release payload is undefined.`);
78+
return -1;
79+
}
80+
81+
const previousDefaults = defaults;
82+
const newDefaults = getNewDefaults(release, previousDefaults);
83+
84+
// Update the source file in the repository. Calling workflows should subsequently rebuild
85+
// the Action to update `lib/defaults.json`.
86+
fs.writeFileSync(DEFAULTS_FILE, `${JSON.stringify(newDefaults, null, 2)}\n`);
87+
88+
return 0;
89+
}
90+
91+
if (require.main === module) {
92+
process.exit(main());
93+
}

0 commit comments

Comments
 (0)