Conversation
7526c65 to
2ab95cc
Compare
There was a problem hiding this comment.
Pull request overview
This PR refines how esbuild bundle metadata is produced and consumed for internal diagnostics by removing the metadata comparison script from the normal npm run build flow, uploading meta.json as a PR-check artifact, and enhancing the bundle-metadata.ts tool to fetch and compare against an artifact baseline for a branch.
Changes:
- Stop running
pr-checks/bundle-metadata.tsas part of the rootbuildnpm script. - Upload
meta.jsonas a workflow artifact inpr-checks.yml(per OS/Node matrix entry). - Extend
pr-checks/bundle-metadata.tsto download a branch baseline artifact and compare it to the localmeta.json.
Show a summary per file
| File | Description |
|---|---|
pr-checks/sync-checks.ts |
Reuses shared API client constants and shared --token CLI parsing config. |
pr-checks/config.ts |
Adds a baseline metadata file path constant used by the comparison script. |
pr-checks/bundle-metadata.ts |
Adds baseline download + unzip + comparison logic for bundle metadata. |
pr-checks/api-client.ts |
Centralizes CODEQL_ACTION_REPO and shared token option config for PR-check scripts. |
package.json |
Removes bundle-metadata script invocation from npm run build. |
.github/workflows/pr-checks.yml |
Uploads meta.json as an artifact for later baseline comparison. |
Copilot's findings
Comments suppressed due to low confidence (3)
pr-checks/bundle-metadata.ts:149
filesInBaseline.difference(filesInCurrent)relies onSet.prototype.difference, which is not available in Node 20 and will throw at runtime for anyone running this script under the repo’s minimum-supported Node version. Consider computing the set difference manually (or using a small helper) to avoid depending on these newer Set methods.
const filesInBaseline = new Set(Object.keys(baselineMetadata.outputs));
const filesInCurrent = new Set(Object.keys(metadata.outputs));
const filesNotPresent = filesInBaseline.difference(filesInCurrent);
if (filesNotPresent.size > 0) {
console.info(`Found ${filesNotPresent.size} file(s) which were removed:`);
for (const removedFile of filesNotPresent) {
console.info(` - ${removedFile}`);
}
}
pr-checks/bundle-metadata.ts:115
- The unzip destination is
-d "."(current working directory), but the script then asserts thatBASELINE_BUNDLE_METADATA_FILE(based on__dirname/PR_CHECKS_DIR) exists. If the script is invoked from the repo root (e.g.npx tsx ./pr-checks/bundle-metadata.ts), the extractedmeta.jsonwill land in the repo root and this check will fail. Use an explicit extraction directory (e.g.PR_CHECKS_DIRor a temp dir) and write/read the archive and extracted file using absolute paths so the script doesn’t depend on the caller’s CWD.
const archivePath = `${expectedArtifactName}.zip`;
await fs.writeFile(archivePath, Buffer.from(downloadInfo.data));
console.info(`Extracting zip file: ${archivePath}`);
await exec.exec("unzip", ["-o", archivePath, "-d", "."]);
// We no longer need the archive after unzipping it.
await fs.rm(archivePath);
// Check that we have the expected file.
try {
await fs.stat(BASELINE_BUNDLE_METADATA_FILE);
} catch (err) {
throw new Error(
`Expected '${BASELINE_BUNDLE_METADATA_FILE}' to have been extracted, but it does not exist: ${err}`,
);
}
pr-checks/bundle-metadata.ts:107
- The script downloads and extracts a ZIP from a workflow artifact using
unzip -odirectly into the working directory. This can overwrite local files and exposes you to zip-slip/path traversal risks if the artifact contents are ever attacker-controlled (e.g. comparing against an untrusted branch). Extract into a dedicated temporary directory and only read the expectedmeta.jsonfrom that directory (and consider validating the extracted path) to reduce the blast radius.
console.info(`Extracting zip file: ${archivePath}`);
await exec.exec("unzip", ["-o", archivePath, "-d", "."]);
// We no longer need the archive after unzipping it.
await fs.rm(archivePath);
- Files reviewed: 6/6 changed files
- Comments generated: 2
| uses: actions/upload-artifact@v7 | ||
| with: | ||
| name: bundle-metadata-${{ matrix.os }}-${{ matrix.node-version }} | ||
| path: meta.json |
There was a problem hiding this comment.
This uploads 6 artifacts per workflow run (3 OS × 2 Node versions) without setting retention-days or if-no-files-found. To limit storage growth and make failures obvious when meta.json isn’t produced, set a short retention (e.g. 7 days, consistent with other PR-check artifacts) and consider if-no-files-found: error.
| path: meta.json | |
| path: meta.json | |
| retention-days: 7 | |
| if-no-files-found: error |
Follow-up to #3787 which makes the following changes:
bundle-metadata.tsscript is no longer run as part of thebuildscript since it wasn't particularly useful in its existing form.pr-checks.ymlworkflow.bundle-metadata.tsscript is improved so that it can download the bundle metadata from workflow artifacts for a given branch and compare the current, local metadata to that.Since we don't yet have these artifacts on
main, this PR does not automatically invokebundle-metadata.tsas part of any workflow. This is intentional. The script can be run manually if desired. E.g. to compare local bundle metadata against that generated for this branch:./bundle-metadata.ts --token "$(gh auth token)" --branch "mbg/bundle-metadata-improvements"Risk assessment
For internal use only. Please select the risk level of this change:
Which use cases does this change impact?
Environments:
How did/will you validate this change?
.test.tsfiles).pr-checks).If something goes wrong after this change is released, what are the mitigation and rollback strategies?
How will you know if something goes wrong after this change is released?
Are there any special considerations for merging or releasing this change?
Merge / deployment checklist