@argos-ci/core 6.0.2 → 6.1.0

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.
package/dist/index.d.mts CHANGED
@@ -236,6 +236,7 @@ declare function finalize(params: FinalizeParameters): Promise<{
236
236
  gitlab: {
237
237
  state: "pending" | "running" | "success" | "failed" | "canceled";
238
238
  };
239
+ url: string;
239
240
  } | null;
240
241
  }[];
241
242
  }>;
package/dist/index.mjs CHANGED
@@ -1002,6 +1002,18 @@ async function uploadFile(input) {
1002
1002
  });
1003
1003
  if (!response.ok) throw new Error(`Failed to upload file to ${input.url}: ${response.status} ${response.statusText}`);
1004
1004
  }
1005
+ async function uploadFileWithPresignedPost(input) {
1006
+ const file = await readFile(input.path);
1007
+ const formData = new FormData();
1008
+ for (const [key, value] of Object.entries(input.fields)) formData.append(key, value);
1009
+ formData.append("file", new Blob([new Uint8Array(file)], { type: input.contentType }), basename(input.path));
1010
+ const response = await fetch(input.url, {
1011
+ method: "POST",
1012
+ signal: AbortSignal.timeout(3e4),
1013
+ body: formData
1014
+ });
1015
+ if (!response.ok) throw new Error(`Failed to upload file to ${input.url}: ${response.status} ${response.statusText}`);
1016
+ }
1005
1017
  //#endregion
1006
1018
  //#region src/util/chunk.ts
1007
1019
  /**
@@ -1348,7 +1360,7 @@ async function skip(params) {
1348
1360
  runId: config.runId,
1349
1361
  runAttempt: config.runAttempt,
1350
1362
  skipped: true,
1351
- screenshotKeys: [],
1363
+ screenshots: [],
1352
1364
  pwTraceKeys: [],
1353
1365
  parentCommits: []
1354
1366
  } });
@@ -1361,6 +1373,7 @@ async function skip(params) {
1361
1373
  * Size of the chunks used to upload screenshots to Argos.
1362
1374
  */
1363
1375
  const CHUNK_SIZE = 10;
1376
+ const PLAYWRIGHT_TRACE_CONTENT_TYPE = "application/zip";
1364
1377
  /**
1365
1378
  * Upload screenshots to Argos.
1366
1379
  */
@@ -1447,11 +1460,15 @@ async function upload(params) {
1447
1460
  return null;
1448
1461
  })();
1449
1462
  debug("Creating build");
1450
- const [pwTraceKeys, snapshotKeys] = snapshots.reduce(([pwTraceKeys, snapshotKeys], snapshot) => {
1463
+ const pwTraceKeys = [];
1464
+ const screenshots = [];
1465
+ for (const snapshot of snapshots) {
1451
1466
  if (snapshot.pwTrace && !pwTraceKeys.includes(snapshot.pwTrace.hash)) pwTraceKeys.push(snapshot.pwTrace.hash);
1452
- if (!snapshotKeys.includes(snapshot.hash)) snapshotKeys.push(snapshot.hash);
1453
- return [pwTraceKeys, snapshotKeys];
1454
- }, [[], []]);
1467
+ if (!screenshots.some((item) => item.key === snapshot.hash)) screenshots.push({
1468
+ key: snapshot.hash,
1469
+ contentType: snapshot.contentType
1470
+ });
1471
+ }
1455
1472
  const createBuildResponse = await apiClient.POST("/builds", { body: {
1456
1473
  commit: config.commit,
1457
1474
  branch: config.branch,
@@ -1459,7 +1476,7 @@ async function upload(params) {
1459
1476
  mode: config.mode,
1460
1477
  parallel: config.parallel,
1461
1478
  parallelNonce: config.parallelNonce,
1462
- screenshotKeys: snapshotKeys,
1479
+ screenshots,
1463
1480
  pwTraceKeys,
1464
1481
  prNumber: config.prNumber,
1465
1482
  prHeadCommit: config.prHeadCommit,
@@ -1477,22 +1494,20 @@ async function upload(params) {
1477
1494
  if (createBuildResponse.error) throwAPIError(createBuildResponse.error);
1478
1495
  const result = createBuildResponse.data;
1479
1496
  debug("Got uploads url", result);
1480
- await uploadFilesToS3([...result.screenshots.map(({ key, putUrl }) => {
1481
- const snapshot = snapshots.find((s) => s.hash === key);
1482
- if (!snapshot) throw new Error(`Invariant: snapshot with hash ${key} not found`);
1483
- return {
1484
- url: putUrl,
1497
+ await uploadFilesToS3([...result.screenshots.map((upload) => {
1498
+ const snapshot = snapshots.find((s) => s.hash === upload.key);
1499
+ if (!snapshot) throw new Error(`Invariant: snapshot with hash ${upload.key} not found`);
1500
+ return createSecureUploadFileInput(upload, {
1485
1501
  path: snapshot.optimizedPath,
1486
1502
  contentType: snapshot.contentType
1487
- };
1488
- }), ...result.pwTraces?.map(({ key, putUrl }) => {
1489
- const snapshot = snapshots.find((s) => s.pwTrace && s.pwTrace.hash === key);
1490
- if (!snapshot || !snapshot.pwTrace) throw new Error(`Invariant: trace with ${key} not found`);
1491
- return {
1492
- url: putUrl,
1503
+ });
1504
+ }), ...result.pwTraces?.map((upload) => {
1505
+ const snapshot = snapshots.find((s) => s.pwTrace && s.pwTrace.hash === upload.key);
1506
+ if (!snapshot || !snapshot.pwTrace) throw new Error(`Invariant: trace with ${upload.key} not found`);
1507
+ return createSecureUploadFileInput(upload, {
1493
1508
  path: snapshot.pwTrace.path,
1494
- contentType: "application/json"
1495
- };
1509
+ contentType: PLAYWRIGHT_TRACE_CONTENT_TYPE
1510
+ });
1496
1511
  }) ?? []]);
1497
1512
  debug("Updating build");
1498
1513
  const uploadBuildResponse = await apiClient.PUT("/builds/{buildId}", {
@@ -1530,16 +1545,18 @@ async function uploadFilesToS3(files) {
1530
1545
  debugTime(timeLabel);
1531
1546
  const chunk = chunks[i];
1532
1547
  if (!chunk) throw new Error(`Invariant: chunk ${i} is empty`);
1533
- await Promise.all(chunk.map(async ({ url, path, contentType }) => {
1534
- await uploadFile({
1535
- url,
1536
- path,
1537
- contentType
1538
- });
1539
- }));
1548
+ await Promise.all(chunk.map((file) => uploadFileWithPresignedPost(file)));
1540
1549
  debugTimeEnd(timeLabel);
1541
1550
  }
1542
1551
  }
1552
+ function createSecureUploadFileInput(upload, file) {
1553
+ if (!("postUrl" in upload)) throw new Error(`Invariant: expected secure upload for ${upload.key}`);
1554
+ return {
1555
+ url: upload.postUrl,
1556
+ fields: upload.fields,
1557
+ ...file
1558
+ };
1559
+ }
1543
1560
  /**
1544
1561
  * Format the preview URL.
1545
1562
  */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@argos-ci/core",
3
3
  "description": "Node.js SDK for visual testing with Argos.",
4
- "version": "6.0.2",
4
+ "version": "6.1.0",
5
5
  "type": "module",
6
6
  "exports": {
7
7
  ".": {
@@ -39,7 +39,7 @@
39
39
  "access": "public"
40
40
  },
41
41
  "dependencies": {
42
- "@argos-ci/api-client": "0.20.1",
42
+ "@argos-ci/api-client": "0.22.0",
43
43
  "@argos-ci/util": "4.0.0",
44
44
  "convict": "^6.2.5",
45
45
  "debug": "^4.4.3",
@@ -67,5 +67,5 @@
67
67
  "lint": "eslint .",
68
68
  "test": "vitest"
69
69
  },
70
- "gitHead": "9c0f1aa0c2ca4bd1255f95f2dc1a9ad7c4cf36e9"
70
+ "gitHead": "4d890d5091bd313c327eb4e8c17dc1bee9d48578"
71
71
  }