@argos-ci/core 4.1.6 → 4.2.1-alpha.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.
- package/dist/index.d.ts +178 -147
- package/dist/index.js +182 -120
- package/package.json +5 -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
|
-
|
|
5
|
-
interface UploadParameters {
|
|
4
|
+
interface Config {
|
|
6
5
|
/**
|
|
7
|
-
*
|
|
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
|
-
|
|
10
|
+
apiBaseUrl: string;
|
|
10
11
|
/**
|
|
11
|
-
*
|
|
12
|
-
* @default process.cwd()
|
|
12
|
+
* Git commit SHA.
|
|
13
13
|
*/
|
|
14
|
-
|
|
14
|
+
commit: string;
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
17
|
-
* @
|
|
16
|
+
* Git branch name of the build.
|
|
17
|
+
* @example "main", "develop", "release/1.0"
|
|
18
18
|
*/
|
|
19
|
-
|
|
19
|
+
branch: string;
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
22
|
-
* @default "https://api.argos-ci.com/v2/"
|
|
21
|
+
* Argos repository access token.
|
|
23
22
|
*/
|
|
24
|
-
|
|
23
|
+
token: string | null;
|
|
25
24
|
/**
|
|
26
|
-
*
|
|
25
|
+
* Custom build name.
|
|
26
|
+
* Useful for multi-build setups on the same commit.
|
|
27
27
|
*/
|
|
28
|
-
|
|
28
|
+
buildName: string | null;
|
|
29
29
|
/**
|
|
30
|
-
*
|
|
30
|
+
* Whether this build is split across multiple parallel jobs.
|
|
31
|
+
* @default false
|
|
31
32
|
*/
|
|
32
|
-
|
|
33
|
+
parallel: boolean;
|
|
33
34
|
/**
|
|
34
|
-
*
|
|
35
|
+
* Unique identifier shared by all parallel jobs.
|
|
35
36
|
*/
|
|
36
|
-
|
|
37
|
+
parallelNonce: string | null;
|
|
37
38
|
/**
|
|
38
|
-
*
|
|
39
|
+
* Index of the current parallel job.
|
|
40
|
+
* Must be between 1 and `parallelTotal`, or null if not set.
|
|
39
41
|
*/
|
|
40
|
-
|
|
42
|
+
parallelIndex: number | null;
|
|
41
43
|
/**
|
|
42
|
-
*
|
|
44
|
+
* Total number of parallel jobs.
|
|
45
|
+
* Use -1 if unknown, or null if not set.
|
|
43
46
|
*/
|
|
44
|
-
|
|
47
|
+
parallelTotal: number | null;
|
|
45
48
|
/**
|
|
46
|
-
*
|
|
47
|
-
* @default "ci"
|
|
49
|
+
* Git branch used as the baseline for screenshot comparison.
|
|
48
50
|
*/
|
|
49
|
-
|
|
51
|
+
referenceBranch: string | null;
|
|
50
52
|
/**
|
|
51
|
-
|
|
53
|
+
* Git commit SHA used as the baseline for screenshot comparison.
|
|
52
54
|
*/
|
|
53
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
61
|
+
repository: string | null;
|
|
65
62
|
/**
|
|
66
|
-
*
|
|
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
|
-
|
|
67
|
+
originalRepository: string | null;
|
|
69
68
|
/**
|
|
70
|
-
*
|
|
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
|
-
|
|
71
|
+
jobId: string | null;
|
|
75
72
|
/**
|
|
76
|
-
*
|
|
73
|
+
* CI run identifier (if provided by the CI environment).
|
|
77
74
|
*/
|
|
78
|
-
|
|
75
|
+
runId: string | null;
|
|
79
76
|
/**
|
|
80
|
-
*
|
|
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
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
-
|
|
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
|
-
*
|
|
313
|
+
* Globs that match image file paths to upload.
|
|
318
314
|
*/
|
|
319
|
-
|
|
315
|
+
files?: string[];
|
|
320
316
|
/**
|
|
321
|
-
*
|
|
317
|
+
* Root directory used to resolve image paths.
|
|
318
|
+
* @default process.cwd()
|
|
322
319
|
*/
|
|
323
|
-
|
|
320
|
+
root?: string;
|
|
324
321
|
/**
|
|
325
|
-
*
|
|
322
|
+
* Globs that match image file paths to exclude from upload.
|
|
323
|
+
* @default ["**\/*.{png,jpg,jpeg}"]
|
|
326
324
|
*/
|
|
327
|
-
|
|
325
|
+
ignore?: string[];
|
|
328
326
|
/**
|
|
329
|
-
*
|
|
327
|
+
* Base URL of the Argos API.
|
|
328
|
+
* @default "https://api.argos-ci.com/v2/"
|
|
330
329
|
*/
|
|
331
|
-
|
|
330
|
+
apiBaseUrl?: string;
|
|
332
331
|
/**
|
|
333
|
-
*
|
|
332
|
+
* Git commit SHA of the build.
|
|
334
333
|
*/
|
|
335
|
-
|
|
334
|
+
commit?: string;
|
|
336
335
|
/**
|
|
337
|
-
*
|
|
336
|
+
* Git branch name of the build.
|
|
338
337
|
*/
|
|
339
|
-
|
|
338
|
+
branch?: string;
|
|
340
339
|
/**
|
|
341
|
-
*
|
|
342
|
-
* If from a fork, this is the fork's repository.
|
|
340
|
+
* Argos repository access token.
|
|
343
341
|
*/
|
|
344
|
-
|
|
342
|
+
token?: string;
|
|
345
343
|
/**
|
|
346
|
-
*
|
|
347
|
-
* If from a fork, this is the base repository.
|
|
344
|
+
* Pull request number associated with the build.
|
|
348
345
|
*/
|
|
349
|
-
|
|
346
|
+
prNumber?: number;
|
|
350
347
|
/**
|
|
351
|
-
*
|
|
348
|
+
* Custom build name. Useful when triggering multiple Argos builds
|
|
349
|
+
* for the same commit.
|
|
352
350
|
*/
|
|
353
|
-
|
|
351
|
+
buildName?: string;
|
|
354
352
|
/**
|
|
355
|
-
*
|
|
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
|
-
|
|
359
|
+
mode?: "ci" | "monitoring";
|
|
358
360
|
/**
|
|
359
|
-
*
|
|
361
|
+
* Parallel test suite configuration.
|
|
362
|
+
* @default false
|
|
360
363
|
*/
|
|
361
|
-
|
|
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
|
-
*
|
|
373
|
+
* Branch used as the baseline for screenshot comparison.
|
|
364
374
|
*/
|
|
365
|
-
|
|
375
|
+
referenceBranch?: string;
|
|
366
376
|
/**
|
|
367
|
-
*
|
|
377
|
+
* Commit SHA used as the baseline for screenshot comparison.
|
|
368
378
|
*/
|
|
369
|
-
|
|
379
|
+
referenceCommit?: string;
|
|
370
380
|
/**
|
|
371
|
-
*
|
|
381
|
+
* Diff sensitivity threshold between 0 and 1.
|
|
382
|
+
* Higher values make Argos less sensitive to differences.
|
|
383
|
+
* @default 0.5
|
|
372
384
|
*/
|
|
373
|
-
|
|
385
|
+
threshold?: number;
|
|
374
386
|
/**
|
|
375
|
-
*
|
|
387
|
+
* Additional build metadata.
|
|
376
388
|
*/
|
|
377
|
-
|
|
389
|
+
metadata?: BuildMetadata;
|
|
378
390
|
/**
|
|
379
|
-
*
|
|
391
|
+
* Preview URL configuration.
|
|
392
|
+
* Can be a fixed base URL or a function to transform URLs dynamically.
|
|
380
393
|
*/
|
|
381
|
-
|
|
394
|
+
previewUrl?: {
|
|
395
|
+
baseUrl: string;
|
|
396
|
+
} | ((url: string) => string);
|
|
382
397
|
/**
|
|
383
|
-
*
|
|
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
|
-
|
|
388
|
-
|
|
389
|
-
|
|
408
|
+
baseName: string | null;
|
|
409
|
+
pwTrace: {
|
|
410
|
+
path: string;
|
|
411
|
+
hash: string;
|
|
412
|
+
} | null;
|
|
413
|
+
name: string;
|
|
414
|
+
path: string;
|
|
390
415
|
}
|
|
391
|
-
|
|
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
|
|
|
@@ -344,6 +341,30 @@ function getPullRequestFromPayload(payload) {
|
|
|
344
341
|
}
|
|
345
342
|
return null;
|
|
346
343
|
}
|
|
344
|
+
function getVercelDeploymentPayload(payload) {
|
|
345
|
+
if (!payload) {
|
|
346
|
+
return null;
|
|
347
|
+
}
|
|
348
|
+
if (process.env.GITHUB_EVENT_NAME !== "repository_dispatch") {
|
|
349
|
+
return null;
|
|
350
|
+
}
|
|
351
|
+
if (!("client_payload" in payload) || !("action" in payload)) {
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
if (payload.action !== "vercel.deployment.success") {
|
|
355
|
+
return null;
|
|
356
|
+
}
|
|
357
|
+
return payload;
|
|
358
|
+
}
|
|
359
|
+
function getSha(context, vercelPayload) {
|
|
360
|
+
if (vercelPayload) {
|
|
361
|
+
return vercelPayload.client_payload.git.sha;
|
|
362
|
+
}
|
|
363
|
+
if (!context.env.GITHUB_SHA) {
|
|
364
|
+
throw new Error(`GITHUB_SHA is missing`);
|
|
365
|
+
}
|
|
366
|
+
return context.env.GITHUB_SHA;
|
|
367
|
+
}
|
|
347
368
|
var service4 = {
|
|
348
369
|
name: "GitHub Actions",
|
|
349
370
|
key: "github-actions",
|
|
@@ -351,10 +372,8 @@ var service4 = {
|
|
|
351
372
|
config: async (context) => {
|
|
352
373
|
const { env } = context;
|
|
353
374
|
const payload = readEventPayload(context);
|
|
354
|
-
const
|
|
355
|
-
|
|
356
|
-
throw new Error(`GITHUB_SHA is missing`);
|
|
357
|
-
}
|
|
375
|
+
const vercelPayload = getVercelDeploymentPayload(payload);
|
|
376
|
+
const sha = getSha(context, vercelPayload);
|
|
358
377
|
const pullRequest = payload ? getPullRequestFromPayload(payload) : await getPullRequestFromHeadSha(context, sha);
|
|
359
378
|
return {
|
|
360
379
|
commit: sha,
|
|
@@ -364,7 +383,7 @@ var service4 = {
|
|
|
364
383
|
runId: env.GITHUB_RUN_ID || null,
|
|
365
384
|
runAttempt: env.GITHUB_RUN_ATTEMPT ? Number(env.GITHUB_RUN_ATTEMPT) : null,
|
|
366
385
|
nonce: `${env.GITHUB_RUN_ID}-${env.GITHUB_RUN_ATTEMPT}`,
|
|
367
|
-
branch: getBranchFromContext(context) || pullRequest?.head.ref || (payload ? getBranchFromPayload(payload) : null) || null,
|
|
386
|
+
branch: vercelPayload?.client_payload?.git?.ref || getBranchFromContext(context) || pullRequest?.head.ref || (payload ? getBranchFromPayload(payload) : null) || null,
|
|
368
387
|
prNumber: pullRequest?.number || null,
|
|
369
388
|
prHeadCommit: pullRequest?.head.sha ?? null,
|
|
370
389
|
prBaseBranch: pullRequest?.base.ref ?? null
|
|
@@ -775,6 +794,11 @@ var schema = {
|
|
|
775
794
|
format: String,
|
|
776
795
|
default: null,
|
|
777
796
|
nullable: true
|
|
797
|
+
},
|
|
798
|
+
skipped: {
|
|
799
|
+
env: "ARGOS_SKIPPED",
|
|
800
|
+
format: Boolean,
|
|
801
|
+
default: false
|
|
778
802
|
}
|
|
779
803
|
};
|
|
780
804
|
function createConfig() {
|
|
@@ -815,7 +839,8 @@ async function readConfig(options = {}) {
|
|
|
815
839
|
parallelIndex: options.parallelIndex ?? defaultConfig.parallelIndex ?? null,
|
|
816
840
|
mode: options.mode || defaultConfig.mode || null,
|
|
817
841
|
ciProvider: ciEnv?.key || null,
|
|
818
|
-
previewBaseUrl: defaultConfig.previewBaseUrl || null
|
|
842
|
+
previewBaseUrl: defaultConfig.previewBaseUrl || null,
|
|
843
|
+
skipped: options.skipped ?? defaultConfig.skipped ?? false
|
|
819
844
|
});
|
|
820
845
|
if (!config.get("branch") || !config.get("commit")) {
|
|
821
846
|
throw new Error(
|
|
@@ -825,6 +850,83 @@ async function readConfig(options = {}) {
|
|
|
825
850
|
config.validate();
|
|
826
851
|
return config.get();
|
|
827
852
|
}
|
|
853
|
+
async function getConfigFromOptions({
|
|
854
|
+
parallel,
|
|
855
|
+
...options
|
|
856
|
+
}) {
|
|
857
|
+
return readConfig({
|
|
858
|
+
...options,
|
|
859
|
+
parallel: parallel !== void 0 ? Boolean(parallel) : void 0,
|
|
860
|
+
parallelNonce: parallel ? parallel.nonce : void 0,
|
|
861
|
+
parallelTotal: parallel ? parallel.total : void 0,
|
|
862
|
+
parallelIndex: parallel ? parallel.index : void 0
|
|
863
|
+
});
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
// src/finalize.ts
|
|
867
|
+
import { createClient, throwAPIError } from "@argos-ci/api-client";
|
|
868
|
+
|
|
869
|
+
// src/auth.ts
|
|
870
|
+
var base64Encode = (obj) => Buffer.from(JSON.stringify(obj), "utf8").toString("base64");
|
|
871
|
+
function getAuthToken(args) {
|
|
872
|
+
const {
|
|
873
|
+
token,
|
|
874
|
+
ciProvider,
|
|
875
|
+
originalRepository: repository,
|
|
876
|
+
jobId,
|
|
877
|
+
runId,
|
|
878
|
+
prNumber
|
|
879
|
+
} = args;
|
|
880
|
+
if (token) {
|
|
881
|
+
return token;
|
|
882
|
+
}
|
|
883
|
+
switch (ciProvider) {
|
|
884
|
+
case "github-actions": {
|
|
885
|
+
if (!repository || !jobId || !runId) {
|
|
886
|
+
throw new Error(
|
|
887
|
+
`Automatic GitHub Actions variables detection failed. Please add the 'ARGOS_TOKEN'`
|
|
888
|
+
);
|
|
889
|
+
}
|
|
890
|
+
const [owner, repo] = repository.split("/");
|
|
891
|
+
return `tokenless-github-${base64Encode({
|
|
892
|
+
owner,
|
|
893
|
+
repository: repo,
|
|
894
|
+
jobId,
|
|
895
|
+
runId,
|
|
896
|
+
prNumber: prNumber ?? void 0
|
|
897
|
+
})}`;
|
|
898
|
+
}
|
|
899
|
+
default:
|
|
900
|
+
throw new Error("Missing Argos repository token 'ARGOS_TOKEN'");
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
// src/finalize.ts
|
|
905
|
+
async function finalize(params) {
|
|
906
|
+
const config = await readConfig({
|
|
907
|
+
parallelNonce: params.parallel?.nonce
|
|
908
|
+
});
|
|
909
|
+
const authToken = getAuthToken(config);
|
|
910
|
+
const apiClient = createClient({
|
|
911
|
+
baseUrl: config.apiBaseUrl,
|
|
912
|
+
authToken
|
|
913
|
+
});
|
|
914
|
+
if (!config.parallelNonce) {
|
|
915
|
+
throw new Error("parallel.nonce is required to finalize the build");
|
|
916
|
+
}
|
|
917
|
+
const finalizeBuildsResult = await apiClient.POST("/builds/finalize", {
|
|
918
|
+
body: {
|
|
919
|
+
parallelNonce: config.parallelNonce
|
|
920
|
+
}
|
|
921
|
+
});
|
|
922
|
+
if (finalizeBuildsResult.error) {
|
|
923
|
+
throwAPIError(finalizeBuildsResult.error);
|
|
924
|
+
}
|
|
925
|
+
return finalizeBuildsResult.data;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
// src/upload.ts
|
|
929
|
+
import { createClient as createClient2, throwAPIError as throwAPIError2 } from "@argos-ci/api-client";
|
|
828
930
|
|
|
829
931
|
// src/discovery.ts
|
|
830
932
|
import { resolve } from "path";
|
|
@@ -925,41 +1027,6 @@ var hashFile = async (filepath) => {
|
|
|
925
1027
|
return hash.digest("hex");
|
|
926
1028
|
};
|
|
927
1029
|
|
|
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
1030
|
// src/s3.ts
|
|
964
1031
|
import { readFile } from "fs/promises";
|
|
965
1032
|
async function uploadFile(input) {
|
|
@@ -992,7 +1059,10 @@ var chunk = (collection, size) => {
|
|
|
992
1059
|
};
|
|
993
1060
|
|
|
994
1061
|
// src/upload.ts
|
|
995
|
-
import {
|
|
1062
|
+
import {
|
|
1063
|
+
getPlaywrightTracePath,
|
|
1064
|
+
readMetadata
|
|
1065
|
+
} from "@argos-ci/util";
|
|
996
1066
|
|
|
997
1067
|
// src/version.ts
|
|
998
1068
|
import { readVersionFromPackage } from "@argos-ci/util";
|
|
@@ -1006,66 +1076,48 @@ async function getArgosCoreSDKIdentifier() {
|
|
|
1006
1076
|
|
|
1007
1077
|
// src/upload.ts
|
|
1008
1078
|
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
1079
|
async function upload(params) {
|
|
1056
1080
|
debug("Starting upload with params", params);
|
|
1057
1081
|
const [config, argosSdk] = await Promise.all([
|
|
1058
1082
|
getConfigFromOptions(params),
|
|
1059
1083
|
getArgosCoreSDKIdentifier()
|
|
1060
1084
|
]);
|
|
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
1085
|
const authToken = getAuthToken(config);
|
|
1065
|
-
const apiClient =
|
|
1086
|
+
const apiClient = createClient2({
|
|
1066
1087
|
baseUrl: config.apiBaseUrl,
|
|
1067
1088
|
authToken
|
|
1068
1089
|
});
|
|
1090
|
+
if (config.skipped) {
|
|
1091
|
+
const createBuildResponse2 = await apiClient.POST("/builds", {
|
|
1092
|
+
body: {
|
|
1093
|
+
commit: config.commit,
|
|
1094
|
+
branch: config.branch,
|
|
1095
|
+
name: config.buildName,
|
|
1096
|
+
mode: config.mode,
|
|
1097
|
+
parallel: config.parallel,
|
|
1098
|
+
parallelNonce: config.parallelNonce,
|
|
1099
|
+
prNumber: config.prNumber,
|
|
1100
|
+
prHeadCommit: config.prHeadCommit,
|
|
1101
|
+
referenceBranch: config.referenceBranch,
|
|
1102
|
+
referenceCommit: config.referenceCommit,
|
|
1103
|
+
argosSdk,
|
|
1104
|
+
ciProvider: config.ciProvider,
|
|
1105
|
+
runId: config.runId,
|
|
1106
|
+
runAttempt: config.runAttempt,
|
|
1107
|
+
skipped: true,
|
|
1108
|
+
screenshotKeys: [],
|
|
1109
|
+
pwTraceKeys: [],
|
|
1110
|
+
parentCommits: []
|
|
1111
|
+
}
|
|
1112
|
+
});
|
|
1113
|
+
if (createBuildResponse2.error) {
|
|
1114
|
+
throwAPIError2(createBuildResponse2.error);
|
|
1115
|
+
}
|
|
1116
|
+
return { build: createBuildResponse2.data.build, screenshots: [] };
|
|
1117
|
+
}
|
|
1118
|
+
const previewUrlFormatter = params.previewUrl ?? (config.previewBaseUrl ? { baseUrl: config.previewBaseUrl } : void 0);
|
|
1119
|
+
const files = params.files ?? ["**/*.{png,jpg,jpeg}"];
|
|
1120
|
+
debug("Using config and files", config, files);
|
|
1069
1121
|
const foundScreenshots = await discoverScreenshots(files, {
|
|
1070
1122
|
root: params.root,
|
|
1071
1123
|
ignore: params.ignore
|
|
@@ -1107,7 +1159,7 @@ async function upload(params) {
|
|
|
1107
1159
|
debug("Fetch project");
|
|
1108
1160
|
const projectResponse = await apiClient.GET("/project");
|
|
1109
1161
|
if (projectResponse.error) {
|
|
1110
|
-
|
|
1162
|
+
throwAPIError2(projectResponse.error);
|
|
1111
1163
|
}
|
|
1112
1164
|
debug("Project fetched", projectResponse.data);
|
|
1113
1165
|
const { defaultBaseBranch, hasRemoteContentAccess } = projectResponse.data;
|
|
@@ -1178,7 +1230,7 @@ async function upload(params) {
|
|
|
1178
1230
|
}
|
|
1179
1231
|
});
|
|
1180
1232
|
if (createBuildResponse.error) {
|
|
1181
|
-
|
|
1233
|
+
throwAPIError2(createBuildResponse.error);
|
|
1182
1234
|
}
|
|
1183
1235
|
const result = createBuildResponse.data;
|
|
1184
1236
|
debug("Got uploads url", result);
|
|
@@ -1232,37 +1284,47 @@ async function upload(params) {
|
|
|
1232
1284
|
}
|
|
1233
1285
|
});
|
|
1234
1286
|
if (uploadBuildResponse.error) {
|
|
1235
|
-
|
|
1287
|
+
throwAPIError2(uploadBuildResponse.error);
|
|
1236
1288
|
}
|
|
1237
1289
|
return { build: uploadBuildResponse.data.build, screenshots };
|
|
1238
1290
|
}
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
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
|
|
1291
|
+
async function uploadFilesToS3(files) {
|
|
1292
|
+
debug(`Split files in chunks of ${CHUNK_SIZE}`);
|
|
1293
|
+
const chunks = chunk(files, CHUNK_SIZE);
|
|
1294
|
+
debug(`Starting upload of ${chunks.length} chunks`);
|
|
1295
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
1296
|
+
debug(`Uploading chunk ${i + 1}/${chunks.length}`);
|
|
1297
|
+
const timeLabel = `Chunk ${i + 1}/${chunks.length}`;
|
|
1298
|
+
debugTime(timeLabel);
|
|
1299
|
+
const chunk2 = chunks[i];
|
|
1300
|
+
if (!chunk2) {
|
|
1301
|
+
throw new Error(`Invariant: chunk ${i} is empty`);
|
|
1257
1302
|
}
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1303
|
+
await Promise.all(
|
|
1304
|
+
chunk2.map(async ({ url, path, contentType }) => {
|
|
1305
|
+
await uploadFile({
|
|
1306
|
+
url,
|
|
1307
|
+
path,
|
|
1308
|
+
contentType
|
|
1309
|
+
});
|
|
1310
|
+
})
|
|
1311
|
+
);
|
|
1312
|
+
debugTimeEnd(timeLabel);
|
|
1261
1313
|
}
|
|
1262
|
-
|
|
1314
|
+
}
|
|
1315
|
+
function formatPreviewUrl(url, formatter) {
|
|
1316
|
+
if (typeof formatter === "function") {
|
|
1317
|
+
return formatter(url);
|
|
1318
|
+
}
|
|
1319
|
+
const urlObj = new URL(url);
|
|
1320
|
+
return new URL(
|
|
1321
|
+
urlObj.pathname + urlObj.search + urlObj.hash,
|
|
1322
|
+
formatter.baseUrl
|
|
1323
|
+
).href;
|
|
1263
1324
|
}
|
|
1264
1325
|
export {
|
|
1265
1326
|
finalize,
|
|
1327
|
+
getConfigFromOptions,
|
|
1266
1328
|
readConfig,
|
|
1267
1329
|
upload
|
|
1268
1330
|
};
|
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.
|
|
4
|
+
"version": "4.2.1-alpha.4+d1894ac",
|
|
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.
|
|
44
|
-
"@argos-ci/util": "3.1.
|
|
43
|
+
"@argos-ci/api-client": "0.12.1-alpha.4+d1894ac",
|
|
44
|
+
"@argos-ci/util": "3.1.2-alpha.4+d1894ac",
|
|
45
45
|
"convict": "^6.2.4",
|
|
46
46
|
"debug": "^4.4.3",
|
|
47
47
|
"fast-glob": "^3.3.3",
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"@types/convict": "^6.1.6",
|
|
54
54
|
"@types/debug": "^4.1.12",
|
|
55
55
|
"@types/tmp": "^0.2.6",
|
|
56
|
+
"@vercel/repository-dispatch": "^0.1.0",
|
|
56
57
|
"msw": "^2.11.3",
|
|
57
58
|
"vitest": "catalog:"
|
|
58
59
|
},
|
|
@@ -64,5 +65,5 @@
|
|
|
64
65
|
"lint": "eslint .",
|
|
65
66
|
"test": "vitest"
|
|
66
67
|
},
|
|
67
|
-
"gitHead": "
|
|
68
|
+
"gitHead": "d1894acc62fb886d4673c88cc7e8cc95e81db78b"
|
|
68
69
|
}
|