xgauntlet 0.8.3 → 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bin/xgauntlet.js +47 -11
  2. package/package.json +1 -1
package/bin/xgauntlet.js CHANGED
@@ -236,6 +236,34 @@ function findLocalBinary() {
236
236
  return null;
237
237
  }
238
238
 
239
+ export async function fetchAttestationBundle(repo = REPO, version = VERSION, customFetcher = null) {
240
+ const fetchFn = customFetcher || fetch;
241
+ const candidates = [
242
+ `https://github.com/${repo}/releases/download/v${version}/attestation.bundle`,
243
+ `https://github.com/${repo}/releases/download/v${version}/attestation.json`,
244
+ ];
245
+
246
+ let lastStatus = 404;
247
+ let lastStatusText = 'Not Found';
248
+
249
+ for (const url of candidates) {
250
+ try {
251
+ const res = await fetchFn(url, { redirect: 'follow' });
252
+ if (res && res.ok) {
253
+ return await res.json();
254
+ }
255
+ if (res) {
256
+ lastStatus = res.status;
257
+ lastStatusText = res.statusText || 'Not Found';
258
+ }
259
+ } catch (err) {
260
+ lastStatusText = err.message;
261
+ }
262
+ }
263
+
264
+ throw new Error(`HTTP ${lastStatus} fetching attestation bundle: ${lastStatusText}`);
265
+ }
266
+
239
267
  async function downloadAndCacheBinary() {
240
268
  if (process.env.XGAUNTLET_TEST_FORCE_NOT_FOUND === '1') {
241
269
  throw new Error('Forced missing binary for test');
@@ -254,27 +282,22 @@ async function downloadAndCacheBinary() {
254
282
  }
255
283
 
256
284
  const downloadUrl = `https://github.com/${REPO}/releases/download/v${VERSION}/${archiveName}`;
257
- const bundleUrl = `https://github.com/${REPO}/releases/download/v${VERSION}/attestation.bundle`;
258
285
  process.stderr.write(`[xgauntlet] Fetching native engine v${VERSION} for ${platform}-${arch}...\n`);
259
286
 
260
- fs.mkdirSync(cacheDir, { recursive: true });
261
- const tempArchive = path.join(cacheDir, `temp-${Date.now()}-${archiveName}`);
287
+ let tempArchive = null;
288
+ let createdCacheDir = false;
262
289
 
263
290
  try {
264
- const [resArchive, resBundle] = await Promise.all([
291
+ const [resArchive, bundleJson] = await Promise.all([
265
292
  fetch(downloadUrl, { redirect: 'follow' }),
266
- fetch(bundleUrl, { redirect: 'follow' }),
293
+ fetchAttestationBundle(REPO, VERSION),
267
294
  ]);
268
295
 
269
296
  if (!resArchive.ok) {
270
297
  throw new Error(`HTTP ${resArchive.status} fetching binary archive: ${resArchive.statusText}`);
271
298
  }
272
- if (!resBundle.ok) {
273
- throw new Error(`HTTP ${resBundle.status} fetching attestation bundle: ${resBundle.statusText}`);
274
- }
275
299
 
276
300
  const archiveBuffer = Buffer.from(await resArchive.arrayBuffer());
277
- const bundleJson = await resBundle.json();
278
301
 
279
302
  process.stderr.write(`[xgauntlet] Verifying cryptographic release attestation for ${archiveName}...\n`);
280
303
  await verifyReleaseArchive({
@@ -288,6 +311,11 @@ async function downloadAndCacheBinary() {
288
311
  });
289
312
  process.stderr.write(`[xgauntlet] Attestation verified successfully (Repo ID: ${EXPECTED_REPOSITORY_ID}).\n`);
290
313
 
314
+ if (!fs.existsSync(cacheDir)) {
315
+ fs.mkdirSync(cacheDir, { recursive: true });
316
+ createdCacheDir = true;
317
+ }
318
+ tempArchive = path.join(cacheDir, `temp-${Date.now()}-${archiveName}`);
291
319
  fs.writeFileSync(tempArchive, archiveBuffer);
292
320
 
293
321
  if (archiveName.endsWith('.tar.gz')) {
@@ -300,7 +328,7 @@ async function downloadAndCacheBinary() {
300
328
  }
301
329
  }
302
330
 
303
- if (fs.existsSync(tempArchive)) {
331
+ if (tempArchive && fs.existsSync(tempArchive)) {
304
332
  fs.unlinkSync(tempArchive);
305
333
  }
306
334
 
@@ -315,9 +343,17 @@ async function downloadAndCacheBinary() {
315
343
  throw new Error(`Extracted archive did not contain expected binary: ${binName}`);
316
344
  }
317
345
  } catch (err) {
318
- if (fs.existsSync(tempArchive)) {
346
+ if (tempArchive && fs.existsSync(tempArchive)) {
319
347
  try { fs.unlinkSync(tempArchive); } catch {}
320
348
  }
349
+ if (createdCacheDir && fs.existsSync(cacheDir)) {
350
+ try {
351
+ const files = fs.readdirSync(cacheDir);
352
+ if (files.length === 0) {
353
+ fs.rmdirSync(cacheDir);
354
+ }
355
+ } catch {}
356
+ }
321
357
  throw err;
322
358
  }
323
359
  }
package/package.json CHANGED
@@ -38,7 +38,7 @@
38
38
  "test": "node --test"
39
39
  },
40
40
  "type": "module",
41
- "version": "0.8.3",
41
+ "version": "0.8.4",
42
42
  "dependencies": {
43
43
  "sigstore": "^3.1.0"
44
44
  }