Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CI: replace validation of zip compression with create-foxglove-extension minimum version #37

Merged
merged 1 commit into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
"@actions/core": "1.10.1",
"@foxglove/tsconfig": "2.0.0",
"@types/node": "22.0.2",
"@types/semver": "7.5.8",
"jszip": "3.10.1",
"semver": "7.6.3",
"ts-node": "10.9.2",
"typescript": "5.5.4"
}
Expand Down
64 changes: 41 additions & 23 deletions validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import registryJson from "./extensions.json";
import crypto from "node:crypto";
import path from "node:path";
import * as core from "@actions/core";
import semver from "semver";

function warning(message: string) {
core.warning(message, { file: "extensions.json" });
Expand All @@ -14,10 +15,16 @@ function error(message: string) {
}

/**
* SHA sums of extensions that are known to be uncompressed. For these we will only log a warning.
* We require newly submitted extensions to use at least this version of create-foxglove-extension.
*
* 1.0.3: fixed a bug where packaged extensions were not compressed
*/
const createFoxgloveExtensionMinVersion = "1.0.3";
/**
* SHA sums of extensions that are exempt from the version check. For these we will only log a warning.
* For other (newer) ones it will be an error if compression is not used.
*/
const knownUncompressedExtensionsSHAs = [
const exemptExtensionsSHAs = [
"fa2b11af8ed7c420ca6e541196bca608661c0c1a81cd1f768c565c72a55a63c8",
"ac07f5f84b96ad1139b4d66b685b864cf5713081e198e63fccef7a0546dd1ab2",
"1193589eb2779a1224328defca4e2ca378ef786474be1842ac43b674b9535d82",
Expand Down Expand Up @@ -84,25 +91,6 @@ async function validateExtension(extension: (typeof registryJson)[number]) {
}

const zip = await JSZip.loadAsync(foxeContent, { checkCRC32: true });
let uncompressedFiles = [];
let anyFilesAreCompressed = false;
for (const [path, zipObj] of Object.entries(zip.files)) {
if (zipObj.dir) continue;
if (zipObj.options.compression === "DEFLATE") {
anyFilesAreCompressed = true;
} else {
uncompressedFiles.push(path);
}
}
if (uncompressedFiles.length > 0) {
(knownUncompressedExtensionsSHAs.includes(extension.sha256sum)
? warning
: error)(
`${extension.id}: the following files are stored without compression: ${
anyFilesAreCompressed ? uncompressedFiles.join(", ") : "(all files)"
}`
);
}

const packageJsonContent = await zip.file("package.json")?.async("string");
if (!packageJsonContent) {
Expand All @@ -115,6 +103,36 @@ async function validateExtension(extension: (typeof registryJson)[number]) {
return;
}

const createFoxgloveExtensionRange =
packageJson.devDependencies?.["create-foxglove-extension"] ??
packageJson.devDependencies?.["@foxglove/fox"];
if (!createFoxgloveExtensionRange) {
error(
`${extension.id}: Invalid package.json: expected create-foxglove-extension in devDependencies`
);
return;
}
const actualMinVersion = semver.minVersion(createFoxgloveExtensionRange);
if (!actualMinVersion) {
error(
`${extension.id}: Invalid package.json: unable to determine min version of create-foxglove-extension`
);
return;
}
if (!semver.gte(actualMinVersion, createFoxgloveExtensionMinVersion)) {
const message = `${extension.id}: must use create-foxglove-extension ${createFoxgloveExtensionMinVersion}, found ${createFoxgloveExtensionRange}`;
if (exemptExtensionsSHAs.includes(extension.sha256sum)) {
warning(message);
} else {
error(message);
return;
}
} else if (exemptExtensionsSHAs.includes(extension.sha256sum)) {
error(
`The following SHA should be removed from exemptExtensionsSHAs: ${extension.sha256sum}`
);
}

const mainPath = packageJson.main;
if (typeof mainPath !== "string") {
error(`${extension.id}: Invalid package.json: missing "main" field`);
Expand All @@ -138,12 +156,12 @@ async function validateExtension(extension: (typeof registryJson)[number]) {
}

async function main() {
const unusedSHAs = knownUncompressedExtensionsSHAs.filter(
const unusedSHAs = exemptExtensionsSHAs.filter(
(sha) => !registryJson.find((ext) => ext.sha256sum === sha)
);
for (const sha of unusedSHAs) {
error(
`The following SHA should be removed from knownUncompressedExtensionsSHAs: ${sha}`
`The following SHA should be removed from exemptExtensionSHAs: ${sha}`
);
}

Expand Down
18 changes: 18 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,13 @@ __metadata:
languageName: node
linkType: hard

"@types/semver@npm:7.5.8":
version: 7.5.8
resolution: "@types/semver@npm:7.5.8"
checksum: 10c0/8663ff927234d1c5fcc04b33062cb2b9fcfbe0f5f351ed26c4d1e1581657deebd506b41ff7fdf89e787e3d33ce05854bc01686379b89e9c49b564c4cfa988efa
languageName: node
linkType: hard

"acorn-walk@npm:^8.1.1":
version: 8.3.3
resolution: "acorn-walk@npm:8.3.3"
Expand Down Expand Up @@ -240,7 +247,9 @@ __metadata:
"@actions/core": "npm:1.10.1"
"@foxglove/tsconfig": "npm:2.0.0"
"@types/node": "npm:22.0.2"
"@types/semver": "npm:7.5.8"
jszip: "npm:3.10.1"
semver: "npm:7.6.3"
ts-node: "npm:10.9.2"
typescript: "npm:5.5.4"
languageName: unknown
Expand All @@ -253,6 +262,15 @@ __metadata:
languageName: node
linkType: hard

"semver@npm:7.6.3":
version: 7.6.3
resolution: "semver@npm:7.6.3"
bin:
semver: bin/semver.js
checksum: 10c0/88f33e148b210c153873cb08cfe1e281d518aaa9a666d4d148add6560db5cd3c582f3a08ccb91f38d5f379ead256da9931234ed122057f40bb5766e65e58adaf
languageName: node
linkType: hard

"setimmediate@npm:^1.0.5":
version: 1.0.5
resolution: "setimmediate@npm:1.0.5"
Expand Down
Loading