@argos-ci/core 4.1.6 → 4.2.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.
Files changed (3) hide show
  1. package/dist/index.d.ts +178 -147
  2. package/dist/index.js +155 -115
  3. package/package.json +4 -4
package/dist/index.d.ts CHANGED
@@ -1,123 +1,133 @@
1
- import * as _argos_ci_util from '@argos-ci/util';
2
1
  import { ArgosAPISchema } from '@argos-ci/api-client';
2
+ import { ScreenshotMetadata } from '@argos-ci/util';
3
3
 
4
- type BuildMetadata = ArgosAPISchema.components["schemas"]["BuildMetadata"];
5
- interface UploadParameters {
4
+ interface Config {
6
5
  /**
7
- * Globs matching image file paths to upload
6
+ * Base URL of the Argos API.
7
+ * Use this to target a self-hosted installation.
8
+ * @default "https://api.argos-ci.com/v2/"
8
9
  */
9
- files?: string[];
10
+ apiBaseUrl: string;
10
11
  /**
11
- * Root directory to look for image to upload
12
- * @default process.cwd()
12
+ * Git commit SHA.
13
13
  */
14
- root?: string;
14
+ commit: string;
15
15
  /**
16
- * Globs matching image file paths to ignore
17
- * @default ["**\/*.\{png,jpg,jpeg\}"]
16
+ * Git branch name of the build.
17
+ * @example "main", "develop", "release/1.0"
18
18
  */
19
- ignore?: string[];
19
+ branch: string;
20
20
  /**
21
- * Base URL of Argos API
22
- * @default "https://api.argos-ci.com/v2/"
21
+ * Argos repository access token.
23
22
  */
24
- apiBaseUrl?: string;
23
+ token: string | null;
25
24
  /**
26
- * Git commit
25
+ * Custom build name.
26
+ * Useful for multi-build setups on the same commit.
27
27
  */
28
- commit?: string;
28
+ buildName: string | null;
29
29
  /**
30
- * Git branch
30
+ * Whether this build is split across multiple parallel jobs.
31
+ * @default false
31
32
  */
32
- branch?: string;
33
+ parallel: boolean;
33
34
  /**
34
- * Argos repository token
35
+ * Unique identifier shared by all parallel jobs.
35
36
  */
36
- token?: string;
37
+ parallelNonce: string | null;
37
38
  /**
38
- * Pull-request number
39
+ * Index of the current parallel job.
40
+ * Must be between 1 and `parallelTotal`, or null if not set.
39
41
  */
40
- prNumber?: number;
42
+ parallelIndex: number | null;
41
43
  /**
42
- * Name of the build used to trigger multiple Argos builds on one commit
44
+ * Total number of parallel jobs.
45
+ * Use -1 if unknown, or null if not set.
43
46
  */
44
- buildName?: string;
47
+ parallelTotal: number | null;
45
48
  /**
46
- * Mode of comparison applied
47
- * @default "ci"
49
+ * Git branch used as the baseline for screenshot comparison.
48
50
  */
49
- mode?: "ci" | "monitoring";
51
+ referenceBranch: string | null;
50
52
  /**
51
- Parallel test suite mode
53
+ * Git commit SHA used as the baseline for screenshot comparison.
52
54
  */
53
- parallel?: {
54
- /** Unique build ID for this parallel build */
55
- nonce: string;
56
- /** The number of parallel nodes being ran */
57
- total: number;
58
- /** The index of the parallel node */
59
- index?: number;
60
- } | false;
55
+ referenceCommit: string | null;
61
56
  /**
62
- * Branch used as baseline for screenshot comparison
57
+ * Repository slug of the source repository.
58
+ * Example: "my-org/my-repo" or "my-user/my-repo".
59
+ * If from a fork, this refers to the fork repository.
63
60
  */
64
- referenceBranch?: string;
61
+ repository: string | null;
65
62
  /**
66
- * Commit used as baseline for screenshot comparison
63
+ * Repository slug of the original (base) repository.
64
+ * Example: "my-org/my-repo" or "my-user/my-repo".
65
+ * If from a fork, this refers to the base repository.
67
66
  */
68
- referenceCommit?: string;
67
+ originalRepository: string | null;
69
68
  /**
70
- * Sensitivity threshold between 0 and 1.
71
- * The higher the threshold, the less sensitive the diff will be.
72
- * @default 0.5
69
+ * CI job identifier (if provided by the CI environment).
73
70
  */
74
- threshold?: number;
71
+ jobId: string | null;
75
72
  /**
76
- * Build metadata.
73
+ * CI run identifier (if provided by the CI environment).
77
74
  */
78
- metadata?: BuildMetadata;
75
+ runId: string | null;
79
76
  /**
80
- * Preview URL configuration.
81
- * Accepts a base URL or a function that receives the URL and returns the preview URL.
77
+ * CI run attempt number (if provided by the CI environment).
82
78
  */
83
- previewUrl?: {
84
- baseUrl: string;
85
- } | ((url: string) => string);
79
+ runAttempt: number | null;
80
+ /**
81
+ * Pull request number associated with the build.
82
+ */
83
+ prNumber: number | null;
84
+ /**
85
+ * Pull request head commit SHA (if available).
86
+ */
87
+ prHeadCommit: string | null;
88
+ /**
89
+ * Pull request base branch (if available).
90
+ */
91
+ prBaseBranch: string | null;
92
+ /**
93
+ * Build mode to use.
94
+ * - "ci": Review visual changes introduced by a feature branch and prevent regressions.
95
+ * - "monitoring": Track visual changes outside the standard CI flow, either on a schedule or before a release.
96
+ * @see https://argos-ci.com/docs/build-modes
97
+ */
98
+ mode: "ci" | "monitoring" | null;
99
+ /**
100
+ * Name of the detected CI provider (if available).
101
+ * @example "github-actions", "gitlab-ci", "circleci"
102
+ */
103
+ ciProvider: string | null;
104
+ /**
105
+ * Diff sensitivity threshold between 0 and 1.
106
+ * Higher values make Argos less sensitive to differences.
107
+ */
108
+ threshold: number | null;
109
+ /**
110
+ * Base URL to use for preview links.
111
+ * @example "https://my-preview.example.com"
112
+ */
113
+ previewBaseUrl: string | null;
114
+ /**
115
+ * Skip this build.
116
+ * No screenshots are uploaded, and the commit status is marked as success.
117
+ */
118
+ skipped?: boolean;
86
119
  }
87
- /**
88
- * Upload screenshots to Argos.
89
- */
90
- declare function upload(params: UploadParameters): Promise<{
91
- build: {
92
- id: ArgosAPISchema.components["schemas"]["BuildId"];
93
- number: number;
94
- status: ("accepted" | "rejected") | ("no-changes" | "changes-detected") | ("expired" | "pending" | "progress" | "error" | "aborted");
95
- url: string;
96
- notification: {
97
- description: string;
98
- context: string;
99
- github: {
100
- state: "pending" | "success" | "error" | "failure";
101
- };
102
- gitlab: {
103
- state: "pending" | "running" | "success" | "failed" | "canceled";
104
- };
105
- } | null;
106
- };
107
- screenshots: {
108
- hash: string;
109
- optimizedPath: string;
110
- metadata: _argos_ci_util.ScreenshotMetadata | null;
111
- threshold: number | null;
112
- baseName: string | null;
113
- pwTrace: {
114
- path: string;
115
- hash: string;
116
- } | null;
117
- name: string;
118
- path: string;
119
- }[];
120
- }>;
120
+ declare function readConfig(options?: Partial<Config>): Promise<Config>;
121
+ declare function getConfigFromOptions({ parallel, ...options }: Omit<Partial<Config>, "parallel"> & {
122
+ parallel?: {
123
+ /** Unique build ID for this parallel build */
124
+ nonce: string;
125
+ /** The number of parallel nodes being ran */
126
+ total: number;
127
+ /** The index of the parallel node */
128
+ index?: number;
129
+ } | false | undefined;
130
+ }): Promise<Config>;
121
131
 
122
132
  interface components {
123
133
  schemas: {
@@ -136,6 +146,11 @@ interface components {
136
146
  name: string;
137
147
  baseName?: string | null;
138
148
  metadata?: {
149
+ /**
150
+ * @description Ignored. Can be set to get completions, validations and documentation in some editors.
151
+ * @example https://api.argos-ci.com/v2/screenshot-metadata.json
152
+ */
153
+ $schema?: string;
139
154
  /** @description The URL of the page that was screenshotted */
140
155
  url?: string | null;
141
156
  /** @description An URL to an accessible preview of the screenshot */
@@ -292,102 +307,118 @@ declare function finalize(params: FinalizeParameters): Promise<{
292
307
  builds: components["schemas"]["Build"][];
293
308
  }>;
294
309
 
295
- interface Config {
296
- /**
297
- * Argos API base URL (for self-hosted installations)
298
- */
299
- apiBaseUrl: string;
300
- /**
301
- * The commit SHA1 (40 characters)
302
- */
303
- commit: string;
304
- /**
305
- * The git branch name (e.g. "main", "master", "develop", "release/1.0" etc.)
306
- */
307
- branch: string;
308
- /**
309
- * The Argos repository token (40 characters)
310
- */
311
- token: string | null;
312
- /**
313
- * The name of the build (for multi-build setups)
314
- */
315
- buildName: string | null;
310
+ type BuildMetadata = ArgosAPISchema.components["schemas"]["BuildMetadata"];
311
+ interface UploadParameters {
316
312
  /**
317
- * Whether the current run is parallelized (split in multiple jobs) or not
313
+ * Globs that match image file paths to upload.
318
314
  */
319
- parallel: boolean;
315
+ files?: string[];
320
316
  /**
321
- * The parallelization nonce (identifier shared by all parallel jobs)
317
+ * Root directory used to resolve image paths.
318
+ * @default process.cwd()
322
319
  */
323
- parallelNonce: string | null;
320
+ root?: string;
324
321
  /**
325
- * The index of the current job (between 1 and parallelTotal inclusive, or null if not set)
322
+ * Globs that match image file paths to exclude from upload.
323
+ * @default ["**\/*.{png,jpg,jpeg}"]
326
324
  */
327
- parallelIndex: number | null;
325
+ ignore?: string[];
328
326
  /**
329
- * The total number of parallel jobs (or -1 if unknown, or null if not set)
327
+ * Base URL of the Argos API.
328
+ * @default "https://api.argos-ci.com/v2/"
330
329
  */
331
- parallelTotal: number | null;
330
+ apiBaseUrl?: string;
332
331
  /**
333
- * The reference git branch to compare against
332
+ * Git commit SHA of the build.
334
333
  */
335
- referenceBranch: string | null;
334
+ commit?: string;
336
335
  /**
337
- * The reference commit SHA1 to compare against
336
+ * Git branch name of the build.
338
337
  */
339
- referenceCommit: string | null;
338
+ branch?: string;
340
339
  /**
341
- * The git repository slug (e.g. "my-org/my-repo" or "my-user/my-repo")
342
- * If from a fork, this is the fork's repository.
340
+ * Argos repository access token.
343
341
  */
344
- repository: string | null;
342
+ token?: string;
345
343
  /**
346
- * The original git repository slug (e.g. "my-org/my-repo" or "my-user/my-repo")
347
- * If from a fork, this is the base repository.
344
+ * Pull request number associated with the build.
348
345
  */
349
- originalRepository: string | null;
346
+ prNumber?: number;
350
347
  /**
351
- * The CI job identifier (if available)
348
+ * Custom build name. Useful when triggering multiple Argos builds
349
+ * for the same commit.
352
350
  */
353
- jobId: string | null;
351
+ buildName?: string;
354
352
  /**
355
- * The CI run identifier (if available)
353
+ * Build mode to use.
354
+ * - "ci": Review the visual changes introduced by a feature branch and prevent regressions.
355
+ * - "monitoring": Track visual changes outside the standard CI flow, either on a schedule or before a release.
356
+ * @see https://argos-ci.com/docs/build-modes
357
+ * @default "ci"
356
358
  */
357
- runId: string | null;
359
+ mode?: "ci" | "monitoring";
358
360
  /**
359
- * The CI run attempt (if available)
361
+ * Parallel test suite configuration.
362
+ * @default false
360
363
  */
361
- runAttempt: number | null;
364
+ parallel?: {
365
+ /** Unique build identifier shared across parallel jobs. */
366
+ nonce: string;
367
+ /** Total number of parallel jobs, set to -1 to finalize manually. */
368
+ total: number;
369
+ /** Index of the current job (must start from 1). */
370
+ index?: number;
371
+ } | false;
362
372
  /**
363
- * The pull request number (if available)
373
+ * Branch used as the baseline for screenshot comparison.
364
374
  */
365
- prNumber: number | null;
375
+ referenceBranch?: string;
366
376
  /**
367
- * The pull request head commit SHA1 (if available)
377
+ * Commit SHA used as the baseline for screenshot comparison.
368
378
  */
369
- prHeadCommit: string | null;
379
+ referenceCommit?: string;
370
380
  /**
371
- * The pull request base branch (if available)
381
+ * Diff sensitivity threshold between 0 and 1.
382
+ * Higher values make Argos less sensitive to differences.
383
+ * @default 0.5
372
384
  */
373
- prBaseBranch: string | null;
385
+ threshold?: number;
374
386
  /**
375
- * The mode Argos is running in (ci or monitoring)
387
+ * Additional build metadata.
376
388
  */
377
- mode: "ci" | "monitoring" | null;
389
+ metadata?: BuildMetadata;
378
390
  /**
379
- * The CI provider name (if detected)
391
+ * Preview URL configuration.
392
+ * Can be a fixed base URL or a function to transform URLs dynamically.
380
393
  */
381
- ciProvider: string | null;
394
+ previewUrl?: {
395
+ baseUrl: string;
396
+ } | ((url: string) => string);
382
397
  /**
383
- * The threshold to use for this run (if any, between 0 and 1 inclusive, e.g. 0.1 for 10% or 0.0 for 0%)
398
+ * Mark this build as skipped.
399
+ * No screenshots are uploaded, and the commit status is marked as success.
384
400
  */
401
+ skipped?: boolean;
402
+ }
403
+ interface Screenshot {
404
+ hash: string;
405
+ optimizedPath: string;
406
+ metadata: ScreenshotMetadata | null;
385
407
  threshold: number | null;
386
- /**
387
- * The base URL to use for preview links (if any)
388
- */
389
- previewBaseUrl: string | null;
408
+ baseName: string | null;
409
+ pwTrace: {
410
+ path: string;
411
+ hash: string;
412
+ } | null;
413
+ name: string;
414
+ path: string;
390
415
  }
391
- declare function readConfig(options?: Partial<Config>): Promise<Config>;
416
+ /**
417
+ * Upload screenshots to Argos.
418
+ */
419
+ declare function upload(params: UploadParameters): Promise<{
420
+ build: ArgosAPISchema.components["schemas"]["Build"];
421
+ screenshots: Screenshot[];
422
+ }>;
392
423
 
393
- export { type Config, type FinalizeParameters, type UploadParameters, finalize, readConfig, upload };
424
+ export { type Config, type FinalizeParameters, type UploadParameters, finalize, getConfigFromOptions, readConfig, upload };
package/dist/index.js CHANGED
@@ -1,6 +1,3 @@
1
- // src/upload.ts
2
- import { createClient, throwAPIError } from "@argos-ci/api-client";
3
-
4
1
  // src/config.ts
5
2
  import convict from "convict";
6
3
 
@@ -775,6 +772,11 @@ var schema = {
775
772
  format: String,
776
773
  default: null,
777
774
  nullable: true
775
+ },
776
+ skipped: {
777
+ env: "ARGOS_SKIPPED",
778
+ format: Boolean,
779
+ default: false
778
780
  }
779
781
  };
780
782
  function createConfig() {
@@ -815,7 +817,8 @@ async function readConfig(options = {}) {
815
817
  parallelIndex: options.parallelIndex ?? defaultConfig.parallelIndex ?? null,
816
818
  mode: options.mode || defaultConfig.mode || null,
817
819
  ciProvider: ciEnv?.key || null,
818
- previewBaseUrl: defaultConfig.previewBaseUrl || null
820
+ previewBaseUrl: defaultConfig.previewBaseUrl || null,
821
+ skipped: options.skipped ?? defaultConfig.skipped ?? false
819
822
  });
820
823
  if (!config.get("branch") || !config.get("commit")) {
821
824
  throw new Error(
@@ -825,6 +828,83 @@ async function readConfig(options = {}) {
825
828
  config.validate();
826
829
  return config.get();
827
830
  }
831
+ async function getConfigFromOptions({
832
+ parallel,
833
+ ...options
834
+ }) {
835
+ return readConfig({
836
+ ...options,
837
+ parallel: parallel !== void 0 ? Boolean(parallel) : void 0,
838
+ parallelNonce: parallel ? parallel.nonce : void 0,
839
+ parallelTotal: parallel ? parallel.total : void 0,
840
+ parallelIndex: parallel ? parallel.index : void 0
841
+ });
842
+ }
843
+
844
+ // src/finalize.ts
845
+ import { createClient, throwAPIError } from "@argos-ci/api-client";
846
+
847
+ // src/auth.ts
848
+ var base64Encode = (obj) => Buffer.from(JSON.stringify(obj), "utf8").toString("base64");
849
+ function getAuthToken(args) {
850
+ const {
851
+ token,
852
+ ciProvider,
853
+ originalRepository: repository,
854
+ jobId,
855
+ runId,
856
+ prNumber
857
+ } = args;
858
+ if (token) {
859
+ return token;
860
+ }
861
+ switch (ciProvider) {
862
+ case "github-actions": {
863
+ if (!repository || !jobId || !runId) {
864
+ throw new Error(
865
+ `Automatic GitHub Actions variables detection failed. Please add the 'ARGOS_TOKEN'`
866
+ );
867
+ }
868
+ const [owner, repo] = repository.split("/");
869
+ return `tokenless-github-${base64Encode({
870
+ owner,
871
+ repository: repo,
872
+ jobId,
873
+ runId,
874
+ prNumber: prNumber ?? void 0
875
+ })}`;
876
+ }
877
+ default:
878
+ throw new Error("Missing Argos repository token 'ARGOS_TOKEN'");
879
+ }
880
+ }
881
+
882
+ // src/finalize.ts
883
+ async function finalize(params) {
884
+ const config = await readConfig({
885
+ parallelNonce: params.parallel?.nonce
886
+ });
887
+ const authToken = getAuthToken(config);
888
+ const apiClient = createClient({
889
+ baseUrl: config.apiBaseUrl,
890
+ authToken
891
+ });
892
+ if (!config.parallelNonce) {
893
+ throw new Error("parallel.nonce is required to finalize the build");
894
+ }
895
+ const finalizeBuildsResult = await apiClient.POST("/builds/finalize", {
896
+ body: {
897
+ parallelNonce: config.parallelNonce
898
+ }
899
+ });
900
+ if (finalizeBuildsResult.error) {
901
+ throwAPIError(finalizeBuildsResult.error);
902
+ }
903
+ return finalizeBuildsResult.data;
904
+ }
905
+
906
+ // src/upload.ts
907
+ import { createClient as createClient2, throwAPIError as throwAPIError2 } from "@argos-ci/api-client";
828
908
 
829
909
  // src/discovery.ts
830
910
  import { resolve } from "path";
@@ -925,41 +1005,6 @@ var hashFile = async (filepath) => {
925
1005
  return hash.digest("hex");
926
1006
  };
927
1007
 
928
- // src/auth.ts
929
- var base64Encode = (obj) => Buffer.from(JSON.stringify(obj), "utf8").toString("base64");
930
- function getAuthToken(args) {
931
- const {
932
- token,
933
- ciProvider,
934
- originalRepository: repository,
935
- jobId,
936
- runId,
937
- prNumber
938
- } = args;
939
- if (token) {
940
- return token;
941
- }
942
- switch (ciProvider) {
943
- case "github-actions": {
944
- if (!repository || !jobId || !runId) {
945
- throw new Error(
946
- `Automatic GitHub Actions variables detection failed. Please add the 'ARGOS_TOKEN'`
947
- );
948
- }
949
- const [owner, repo] = repository.split("/");
950
- return `tokenless-github-${base64Encode({
951
- owner,
952
- repository: repo,
953
- jobId,
954
- runId,
955
- prNumber: prNumber ?? void 0
956
- })}`;
957
- }
958
- default:
959
- throw new Error("Missing Argos repository token 'ARGOS_TOKEN'");
960
- }
961
- }
962
-
963
1008
  // src/s3.ts
964
1009
  import { readFile } from "fs/promises";
965
1010
  async function uploadFile(input) {
@@ -992,7 +1037,10 @@ var chunk = (collection, size) => {
992
1037
  };
993
1038
 
994
1039
  // src/upload.ts
995
- import { getPlaywrightTracePath, readMetadata } from "@argos-ci/util";
1040
+ import {
1041
+ getPlaywrightTracePath,
1042
+ readMetadata
1043
+ } from "@argos-ci/util";
996
1044
 
997
1045
  // src/version.ts
998
1046
  import { readVersionFromPackage } from "@argos-ci/util";
@@ -1006,66 +1054,48 @@ async function getArgosCoreSDKIdentifier() {
1006
1054
 
1007
1055
  // src/upload.ts
1008
1056
  var CHUNK_SIZE = 10;
1009
- async function getConfigFromOptions({
1010
- parallel,
1011
- ...options
1012
- }) {
1013
- return readConfig({
1014
- ...options,
1015
- parallel: parallel !== void 0 ? Boolean(parallel) : void 0,
1016
- parallelNonce: parallel ? parallel.nonce : void 0,
1017
- parallelTotal: parallel ? parallel.total : void 0,
1018
- parallelIndex: parallel ? parallel.index : void 0
1019
- });
1020
- }
1021
- async function uploadFilesToS3(files) {
1022
- debug(`Split files in chunks of ${CHUNK_SIZE}`);
1023
- const chunks = chunk(files, CHUNK_SIZE);
1024
- debug(`Starting upload of ${chunks.length} chunks`);
1025
- for (let i = 0; i < chunks.length; i++) {
1026
- debug(`Uploading chunk ${i + 1}/${chunks.length}`);
1027
- const timeLabel = `Chunk ${i + 1}/${chunks.length}`;
1028
- debugTime(timeLabel);
1029
- const chunk2 = chunks[i];
1030
- if (!chunk2) {
1031
- throw new Error(`Invariant: chunk ${i} is empty`);
1032
- }
1033
- await Promise.all(
1034
- chunk2.map(async ({ url, path, contentType }) => {
1035
- await uploadFile({
1036
- url,
1037
- path,
1038
- contentType
1039
- });
1040
- })
1041
- );
1042
- debugTimeEnd(timeLabel);
1043
- }
1044
- }
1045
- function formatPreviewUrl(url, formatter) {
1046
- if (typeof formatter === "function") {
1047
- return formatter(url);
1048
- }
1049
- const urlObj = new URL(url);
1050
- return new URL(
1051
- urlObj.pathname + urlObj.search + urlObj.hash,
1052
- formatter.baseUrl
1053
- ).href;
1054
- }
1055
1057
  async function upload(params) {
1056
1058
  debug("Starting upload with params", params);
1057
1059
  const [config, argosSdk] = await Promise.all([
1058
1060
  getConfigFromOptions(params),
1059
1061
  getArgosCoreSDKIdentifier()
1060
1062
  ]);
1061
- const previewUrlFormatter = params.previewUrl ?? (config.previewBaseUrl ? { baseUrl: config.previewBaseUrl } : void 0);
1062
- const files = params.files ?? ["**/*.{png,jpg,jpeg}"];
1063
- debug("Using config and files", config, files);
1064
1063
  const authToken = getAuthToken(config);
1065
- const apiClient = createClient({
1064
+ const apiClient = createClient2({
1066
1065
  baseUrl: config.apiBaseUrl,
1067
1066
  authToken
1068
1067
  });
1068
+ if (config.skipped) {
1069
+ const createBuildResponse2 = await apiClient.POST("/builds", {
1070
+ body: {
1071
+ commit: config.commit,
1072
+ branch: config.branch,
1073
+ name: config.buildName,
1074
+ mode: config.mode,
1075
+ parallel: config.parallel,
1076
+ parallelNonce: config.parallelNonce,
1077
+ prNumber: config.prNumber,
1078
+ prHeadCommit: config.prHeadCommit,
1079
+ referenceBranch: config.referenceBranch,
1080
+ referenceCommit: config.referenceCommit,
1081
+ argosSdk,
1082
+ ciProvider: config.ciProvider,
1083
+ runId: config.runId,
1084
+ runAttempt: config.runAttempt,
1085
+ skipped: true,
1086
+ screenshotKeys: [],
1087
+ pwTraceKeys: [],
1088
+ parentCommits: []
1089
+ }
1090
+ });
1091
+ if (createBuildResponse2.error) {
1092
+ throwAPIError2(createBuildResponse2.error);
1093
+ }
1094
+ return { build: createBuildResponse2.data.build, screenshots: [] };
1095
+ }
1096
+ const previewUrlFormatter = params.previewUrl ?? (config.previewBaseUrl ? { baseUrl: config.previewBaseUrl } : void 0);
1097
+ const files = params.files ?? ["**/*.{png,jpg,jpeg}"];
1098
+ debug("Using config and files", config, files);
1069
1099
  const foundScreenshots = await discoverScreenshots(files, {
1070
1100
  root: params.root,
1071
1101
  ignore: params.ignore
@@ -1107,7 +1137,7 @@ async function upload(params) {
1107
1137
  debug("Fetch project");
1108
1138
  const projectResponse = await apiClient.GET("/project");
1109
1139
  if (projectResponse.error) {
1110
- throwAPIError(projectResponse.error);
1140
+ throwAPIError2(projectResponse.error);
1111
1141
  }
1112
1142
  debug("Project fetched", projectResponse.data);
1113
1143
  const { defaultBaseBranch, hasRemoteContentAccess } = projectResponse.data;
@@ -1178,7 +1208,7 @@ async function upload(params) {
1178
1208
  }
1179
1209
  });
1180
1210
  if (createBuildResponse.error) {
1181
- throwAPIError(createBuildResponse.error);
1211
+ throwAPIError2(createBuildResponse.error);
1182
1212
  }
1183
1213
  const result = createBuildResponse.data;
1184
1214
  debug("Got uploads url", result);
@@ -1232,37 +1262,47 @@ async function upload(params) {
1232
1262
  }
1233
1263
  });
1234
1264
  if (uploadBuildResponse.error) {
1235
- throwAPIError(uploadBuildResponse.error);
1265
+ throwAPIError2(uploadBuildResponse.error);
1236
1266
  }
1237
1267
  return { build: uploadBuildResponse.data.build, screenshots };
1238
1268
  }
1239
-
1240
- // src/finalize.ts
1241
- import { createClient as createClient2, throwAPIError as throwAPIError2 } from "@argos-ci/api-client";
1242
- async function finalize(params) {
1243
- const config = await readConfig({
1244
- parallelNonce: params.parallel?.nonce
1245
- });
1246
- const authToken = getAuthToken(config);
1247
- const apiClient = createClient2({
1248
- baseUrl: config.apiBaseUrl,
1249
- authToken
1250
- });
1251
- if (!config.parallelNonce) {
1252
- throw new Error("parallel.nonce is required to finalize the build");
1253
- }
1254
- const finalizeBuildsResult = await apiClient.POST("/builds/finalize", {
1255
- body: {
1256
- parallelNonce: config.parallelNonce
1269
+ async function uploadFilesToS3(files) {
1270
+ debug(`Split files in chunks of ${CHUNK_SIZE}`);
1271
+ const chunks = chunk(files, CHUNK_SIZE);
1272
+ debug(`Starting upload of ${chunks.length} chunks`);
1273
+ for (let i = 0; i < chunks.length; i++) {
1274
+ debug(`Uploading chunk ${i + 1}/${chunks.length}`);
1275
+ const timeLabel = `Chunk ${i + 1}/${chunks.length}`;
1276
+ debugTime(timeLabel);
1277
+ const chunk2 = chunks[i];
1278
+ if (!chunk2) {
1279
+ throw new Error(`Invariant: chunk ${i} is empty`);
1257
1280
  }
1258
- });
1259
- if (finalizeBuildsResult.error) {
1260
- throwAPIError2(finalizeBuildsResult.error);
1281
+ await Promise.all(
1282
+ chunk2.map(async ({ url, path, contentType }) => {
1283
+ await uploadFile({
1284
+ url,
1285
+ path,
1286
+ contentType
1287
+ });
1288
+ })
1289
+ );
1290
+ debugTimeEnd(timeLabel);
1261
1291
  }
1262
- return finalizeBuildsResult.data;
1292
+ }
1293
+ function formatPreviewUrl(url, formatter) {
1294
+ if (typeof formatter === "function") {
1295
+ return formatter(url);
1296
+ }
1297
+ const urlObj = new URL(url);
1298
+ return new URL(
1299
+ urlObj.pathname + urlObj.search + urlObj.hash,
1300
+ formatter.baseUrl
1301
+ ).href;
1263
1302
  }
1264
1303
  export {
1265
1304
  finalize,
1305
+ getConfigFromOptions,
1266
1306
  readConfig,
1267
1307
  upload
1268
1308
  };
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": "4.1.6",
4
+ "version": "4.2.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
7
7
  "exports": {
@@ -40,8 +40,8 @@
40
40
  "access": "public"
41
41
  },
42
42
  "dependencies": {
43
- "@argos-ci/api-client": "0.11.1",
44
- "@argos-ci/util": "3.1.0",
43
+ "@argos-ci/api-client": "0.12.0",
44
+ "@argos-ci/util": "3.1.1",
45
45
  "convict": "^6.2.4",
46
46
  "debug": "^4.4.3",
47
47
  "fast-glob": "^3.3.3",
@@ -64,5 +64,5 @@
64
64
  "lint": "eslint .",
65
65
  "test": "vitest"
66
66
  },
67
- "gitHead": "00f28041a847158e437aaab5fc9e816f6b609021"
67
+ "gitHead": "867a93c5ffc01d55c7385d3ac3903c4c3ab270b6"
68
68
  }