Skip to content

Commit af6b899

Browse files
committed
Fetch baseline bundle metadata
1 parent 989d6f4 commit af6b899

File tree

2 files changed

+115
-1
lines changed

2 files changed

+115
-1
lines changed

pr-checks/bundle-metadata.ts

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,43 @@
11
#!/usr/bin/env npx tsx
22

33
import * as fs from "node:fs/promises";
4+
import { parseArgs, ParseArgsConfig } from "node:util";
45

5-
import { BUNDLE_METADATA_FILE } from "./config";
6+
import * as exec from "@actions/exec";
7+
8+
import {
9+
ApiClient,
10+
CODEQL_ACTION_REPO,
11+
getApiClient,
12+
TOKEN_OPTION_CONFIG,
13+
} from "./api-client";
14+
import { BASELINE_BUNDLE_METADATA_FILE, BUNDLE_METADATA_FILE } from "./config";
15+
16+
const optionsConfig = {
17+
...TOKEN_OPTION_CONFIG,
18+
branch: {
19+
type: "string",
20+
default: "main",
21+
},
22+
runner: {
23+
type: "string",
24+
default: "macos-latest",
25+
},
26+
"node-version": {
27+
type: "string",
28+
default: "24",
29+
},
30+
} satisfies ParseArgsConfig["options"];
31+
32+
function parseOptions() {
33+
const { values: options } = parseArgs({
34+
options: optionsConfig,
35+
});
36+
37+
return options;
38+
}
39+
40+
type Options = ReturnType<typeof parseOptions>;
641

742
interface InputInfo {
843
bytesInOutput: number;
@@ -23,7 +58,80 @@ function toMB(bytes: number): string {
2358
return `${(bytes / (1024 * 1024)).toFixed(2)}MB`;
2459
}
2560

61+
async function getBaselineFrom(client: ApiClient, options: Options) {
62+
const workflowRun = await client.rest.actions.listWorkflowRuns({
63+
...CODEQL_ACTION_REPO,
64+
branch: options.branch,
65+
workflow_id: "pr-checks.yml",
66+
status: "success",
67+
per_page: 1,
68+
event: "push",
69+
});
70+
71+
if (workflowRun.data.total_count === 0) {
72+
throw new Error(
73+
`Expected to find a 'pr-checks.yml' run for '${options.branch}', but found none.`,
74+
);
75+
}
76+
77+
const expectedArtifactName = `bundle-metadata-${options.runner}-${options["node-version"]}`;
78+
const artifacts = await client.rest.actions.listWorkflowRunArtifacts({
79+
...CODEQL_ACTION_REPO,
80+
run_id: workflowRun.data.workflow_runs[0].id,
81+
name: expectedArtifactName,
82+
});
83+
84+
if (artifacts.data.total_count === 0) {
85+
throw new Error(
86+
`Expected to find an artifact named '${expectedArtifactName}', but found none.`,
87+
);
88+
}
89+
90+
const downloadInfo = await client.rest.actions.downloadArtifact({
91+
...CODEQL_ACTION_REPO,
92+
artifact_id: artifacts.data.artifacts[0].id,
93+
archive_format: "zip",
94+
});
95+
96+
// This works fine for us with our version of Octokit, so we don't need to
97+
// worry about over-complicating this script and handle other possibilities.
98+
if (downloadInfo.data instanceof ArrayBuffer) {
99+
const archivePath = `${expectedArtifactName}.zip`;
100+
await fs.writeFile(archivePath, Buffer.from(downloadInfo.data));
101+
102+
console.info(`Extracting zip file: ${archivePath}`);
103+
await exec.exec("unzip", ["-o", archivePath, "-d", "."]);
104+
105+
// We no longer need the archive after unzipping it.
106+
await fs.rm(archivePath);
107+
108+
// Check that we have the expected file.
109+
try {
110+
await fs.stat(BASELINE_BUNDLE_METADATA_FILE);
111+
} catch (err) {
112+
throw new Error(
113+
`Expected '${BASELINE_BUNDLE_METADATA_FILE}' to have been extracted, but it does not exist: ${err}`,
114+
);
115+
}
116+
117+
const baselineData = await fs.readFile(BASELINE_BUNDLE_METADATA_FILE);
118+
return JSON.parse(String(baselineData)) as Metadata;
119+
} else {
120+
throw new Error("Expected to receive artifact data, but didn't.");
121+
}
122+
}
123+
26124
async function main() {
125+
const options = parseOptions();
126+
127+
if (options.token === undefined) {
128+
throw new Error("Missing --token");
129+
}
130+
131+
// Initialise the API client.
132+
const client = getApiClient(options.token);
133+
const baselineMetadata = await getBaselineFrom(client, options);
134+
27135
const fileContents = await fs.readFile(BUNDLE_METADATA_FILE);
28136
const metadata = JSON.parse(String(fileContents)) as Metadata;
29137

pr-checks/config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,9 @@ export const PR_CHECK_EXCLUDED_FILE = path.join(PR_CHECKS_DIR, "excluded.yml");
1111

1212
/** The path to the esbuild metadata file. */
1313
export const BUNDLE_METADATA_FILE = path.join(PR_CHECKS_DIR, "..", "meta.json");
14+
15+
/** The path of the baseline esbuild metadata file, once extracted from a workflow artifact. */
16+
export const BASELINE_BUNDLE_METADATA_FILE = path.join(
17+
PR_CHECKS_DIR,
18+
"meta.json",
19+
);

0 commit comments

Comments
 (0)