Skip to content

Commit 82ed820

Browse files
authoredSep 27, 2024
CI: replace validation of zip compression with create-foxglove-extension minimum version (foxglove#37)
In foxglove#32, I added a CI check to validate that .foxe zip files actually use compression (a bug fixed in foxglove/create-foxglove-extension#147). However, it turns out this check was broken because when loading a zip file with JSZip, `zipObj.options.compression` is not set even if the file was compressed. This PR replaces it with an alternative approach where we read the version of `create-foxglove-extension` from the extension's package.json and validate that it's >=1.0.3.
1 parent eaa6bbe commit 82ed820

File tree

3 files changed

+61
-23
lines changed

3 files changed

+61
-23
lines changed
 

‎package.json

+2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
"@actions/core": "1.10.1",
99
"@foxglove/tsconfig": "2.0.0",
1010
"@types/node": "22.0.2",
11+
"@types/semver": "7.5.8",
1112
"jszip": "3.10.1",
13+
"semver": "7.6.3",
1214
"ts-node": "10.9.2",
1315
"typescript": "5.5.4"
1416
}

‎validate.ts

+41-23
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import registryJson from "./extensions.json";
33
import crypto from "node:crypto";
44
import path from "node:path";
55
import * as core from "@actions/core";
6+
import semver from "semver";
67

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

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

8693
const zip = await JSZip.loadAsync(foxeContent, { checkCRC32: true });
87-
let uncompressedFiles = [];
88-
let anyFilesAreCompressed = false;
89-
for (const [path, zipObj] of Object.entries(zip.files)) {
90-
if (zipObj.dir) continue;
91-
if (zipObj.options.compression === "DEFLATE") {
92-
anyFilesAreCompressed = true;
93-
} else {
94-
uncompressedFiles.push(path);
95-
}
96-
}
97-
if (uncompressedFiles.length > 0) {
98-
(knownUncompressedExtensionsSHAs.includes(extension.sha256sum)
99-
? warning
100-
: error)(
101-
`${extension.id}: the following files are stored without compression: ${
102-
anyFilesAreCompressed ? uncompressedFiles.join(", ") : "(all files)"
103-
}`
104-
);
105-
}
10694

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

106+
const createFoxgloveExtensionRange =
107+
packageJson.devDependencies?.["create-foxglove-extension"] ??
108+
packageJson.devDependencies?.["@foxglove/fox"];
109+
if (!createFoxgloveExtensionRange) {
110+
error(
111+
`${extension.id}: Invalid package.json: expected create-foxglove-extension in devDependencies`
112+
);
113+
return;
114+
}
115+
const actualMinVersion = semver.minVersion(createFoxgloveExtensionRange);
116+
if (!actualMinVersion) {
117+
error(
118+
`${extension.id}: Invalid package.json: unable to determine min version of create-foxglove-extension`
119+
);
120+
return;
121+
}
122+
if (!semver.gte(actualMinVersion, createFoxgloveExtensionMinVersion)) {
123+
const message = `${extension.id}: must use create-foxglove-extension ${createFoxgloveExtensionMinVersion}, found ${createFoxgloveExtensionRange}`;
124+
if (exemptExtensionsSHAs.includes(extension.sha256sum)) {
125+
warning(message);
126+
} else {
127+
error(message);
128+
return;
129+
}
130+
} else if (exemptExtensionsSHAs.includes(extension.sha256sum)) {
131+
error(
132+
`The following SHA should be removed from exemptExtensionsSHAs: ${extension.sha256sum}`
133+
);
134+
}
135+
118136
const mainPath = packageJson.main;
119137
if (typeof mainPath !== "string") {
120138
error(`${extension.id}: Invalid package.json: missing "main" field`);
@@ -138,12 +156,12 @@ async function validateExtension(extension: (typeof registryJson)[number]) {
138156
}
139157

140158
async function main() {
141-
const unusedSHAs = knownUncompressedExtensionsSHAs.filter(
159+
const unusedSHAs = exemptExtensionsSHAs.filter(
142160
(sha) => !registryJson.find((ext) => ext.sha256sum === sha)
143161
);
144162
for (const sha of unusedSHAs) {
145163
error(
146-
`The following SHA should be removed from knownUncompressedExtensionsSHAs: ${sha}`
164+
`The following SHA should be removed from exemptExtensionSHAs: ${sha}`
147165
);
148166
}
149167

‎yarn.lock

+18
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,13 @@ __metadata:
109109
languageName: node
110110
linkType: hard
111111

112+
"@types/semver@npm:7.5.8":
113+
version: 7.5.8
114+
resolution: "@types/semver@npm:7.5.8"
115+
checksum: 10c0/8663ff927234d1c5fcc04b33062cb2b9fcfbe0f5f351ed26c4d1e1581657deebd506b41ff7fdf89e787e3d33ce05854bc01686379b89e9c49b564c4cfa988efa
116+
languageName: node
117+
linkType: hard
118+
112119
"acorn-walk@npm:^8.1.1":
113120
version: 8.3.3
114121
resolution: "acorn-walk@npm:8.3.3"
@@ -240,7 +247,9 @@ __metadata:
240247
"@actions/core": "npm:1.10.1"
241248
"@foxglove/tsconfig": "npm:2.0.0"
242249
"@types/node": "npm:22.0.2"
250+
"@types/semver": "npm:7.5.8"
243251
jszip: "npm:3.10.1"
252+
semver: "npm:7.6.3"
244253
ts-node: "npm:10.9.2"
245254
typescript: "npm:5.5.4"
246255
languageName: unknown
@@ -253,6 +262,15 @@ __metadata:
253262
languageName: node
254263
linkType: hard
255264

265+
"semver@npm:7.6.3":
266+
version: 7.6.3
267+
resolution: "semver@npm:7.6.3"
268+
bin:
269+
semver: bin/semver.js
270+
checksum: 10c0/88f33e148b210c153873cb08cfe1e281d518aaa9a666d4d148add6560db5cd3c582f3a08ccb91f38d5f379ead256da9931234ed122057f40bb5766e65e58adaf
271+
languageName: node
272+
linkType: hard
273+
256274
"setimmediate@npm:^1.0.5":
257275
version: 1.0.5
258276
resolution: "setimmediate@npm:1.0.5"

0 commit comments

Comments
 (0)
Please sign in to comment.