11#!/usr/bin/env npx tsx
22
33import * as fs from "node:fs/promises" ;
4+ import { parseArgs , ParseArgsConfig } from "node:util" ;
45
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" ;
514import { BUNDLE_METADATA_FILE } from "./config" ;
615
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 > ;
41+
742interface InputInfo {
843 bytesInOutput : number ;
944}
@@ -23,7 +58,66 @@ 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 !== 1 ) {
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+ if ( downloadInfo . data instanceof ArrayBuffer ) {
97+ const archivePath = `${ expectedArtifactName } .zip` ;
98+ await fs . writeFile ( archivePath , Buffer . from ( downloadInfo . data ) ) ;
99+
100+ console . info ( `Extracting zip file: ${ archivePath } ` ) ;
101+ await exec . exec ( "unzip" , [ "-o" , archivePath , "-d" , "." ] ) ;
102+
103+ const baselineData = await fs . readFile ( "meta.json" ) ;
104+ return JSON . parse ( String ( baselineData ) ) as Metadata ;
105+ } else {
106+ throw new Error ( "Expected to receive artifact data, but didn't." ) ;
107+ }
108+ }
109+
26110async function main ( ) {
111+ const options = parseOptions ( ) ;
112+
113+ if ( options . token === undefined ) {
114+ throw new Error ( "Missing --token" ) ;
115+ }
116+
117+ // Initialise the API client.
118+ const client = getApiClient ( options . token ) ;
119+ const baselineMetadata = await getBaselineFrom ( client , options ) ;
120+
27121 const fileContents = await fs . readFile ( BUNDLE_METADATA_FILE ) ;
28122 const metadata = JSON . parse ( String ( fileContents ) ) as Metadata ;
29123
0 commit comments