@argos-ci/core 4.1.5 → 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.
- package/dist/index.d.ts +212 -109
- package/dist/index.js +192 -122
- package/package.json +8 -8
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,30 +307,118 @@ declare function finalize(params: FinalizeParameters): Promise<{
|
|
|
292
307
|
builds: components["schemas"]["Build"][];
|
|
293
308
|
}>;
|
|
294
309
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
310
|
+
type BuildMetadata = ArgosAPISchema.components["schemas"]["BuildMetadata"];
|
|
311
|
+
interface UploadParameters {
|
|
312
|
+
/**
|
|
313
|
+
* Globs that match image file paths to upload.
|
|
314
|
+
*/
|
|
315
|
+
files?: string[];
|
|
316
|
+
/**
|
|
317
|
+
* Root directory used to resolve image paths.
|
|
318
|
+
* @default process.cwd()
|
|
319
|
+
*/
|
|
320
|
+
root?: string;
|
|
321
|
+
/**
|
|
322
|
+
* Globs that match image file paths to exclude from upload.
|
|
323
|
+
* @default ["**\/*.{png,jpg,jpeg}"]
|
|
324
|
+
*/
|
|
325
|
+
ignore?: string[];
|
|
326
|
+
/**
|
|
327
|
+
* Base URL of the Argos API.
|
|
328
|
+
* @default "https://api.argos-ci.com/v2/"
|
|
329
|
+
*/
|
|
330
|
+
apiBaseUrl?: string;
|
|
331
|
+
/**
|
|
332
|
+
* Git commit SHA of the build.
|
|
333
|
+
*/
|
|
334
|
+
commit?: string;
|
|
335
|
+
/**
|
|
336
|
+
* Git branch name of the build.
|
|
337
|
+
*/
|
|
338
|
+
branch?: string;
|
|
339
|
+
/**
|
|
340
|
+
* Argos repository access token.
|
|
341
|
+
*/
|
|
342
|
+
token?: string;
|
|
343
|
+
/**
|
|
344
|
+
* Pull request number associated with the build.
|
|
345
|
+
*/
|
|
346
|
+
prNumber?: number;
|
|
347
|
+
/**
|
|
348
|
+
* Custom build name. Useful when triggering multiple Argos builds
|
|
349
|
+
* for the same commit.
|
|
350
|
+
*/
|
|
351
|
+
buildName?: string;
|
|
352
|
+
/**
|
|
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"
|
|
358
|
+
*/
|
|
359
|
+
mode?: "ci" | "monitoring";
|
|
360
|
+
/**
|
|
361
|
+
* Parallel test suite configuration.
|
|
362
|
+
* @default false
|
|
363
|
+
*/
|
|
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;
|
|
372
|
+
/**
|
|
373
|
+
* Branch used as the baseline for screenshot comparison.
|
|
374
|
+
*/
|
|
375
|
+
referenceBranch?: string;
|
|
376
|
+
/**
|
|
377
|
+
* Commit SHA used as the baseline for screenshot comparison.
|
|
378
|
+
*/
|
|
379
|
+
referenceCommit?: string;
|
|
380
|
+
/**
|
|
381
|
+
* Diff sensitivity threshold between 0 and 1.
|
|
382
|
+
* Higher values make Argos less sensitive to differences.
|
|
383
|
+
* @default 0.5
|
|
384
|
+
*/
|
|
385
|
+
threshold?: number;
|
|
386
|
+
/**
|
|
387
|
+
* Additional build metadata.
|
|
388
|
+
*/
|
|
389
|
+
metadata?: BuildMetadata;
|
|
390
|
+
/**
|
|
391
|
+
* Preview URL configuration.
|
|
392
|
+
* Can be a fixed base URL or a function to transform URLs dynamically.
|
|
393
|
+
*/
|
|
394
|
+
previewUrl?: {
|
|
395
|
+
baseUrl: string;
|
|
396
|
+
} | ((url: string) => string);
|
|
397
|
+
/**
|
|
398
|
+
* Mark this build as skipped.
|
|
399
|
+
* No screenshots are uploaded, and the commit status is marked as success.
|
|
400
|
+
*/
|
|
401
|
+
skipped?: boolean;
|
|
402
|
+
}
|
|
403
|
+
interface Screenshot {
|
|
404
|
+
hash: string;
|
|
405
|
+
optimizedPath: string;
|
|
406
|
+
metadata: ScreenshotMetadata | null;
|
|
316
407
|
threshold: number | null;
|
|
317
|
-
|
|
408
|
+
baseName: string | null;
|
|
409
|
+
pwTrace: {
|
|
410
|
+
path: string;
|
|
411
|
+
hash: string;
|
|
412
|
+
} | null;
|
|
413
|
+
name: string;
|
|
414
|
+
path: string;
|
|
318
415
|
}
|
|
319
|
-
|
|
416
|
+
/**
|
|
417
|
+
* Upload screenshots to Argos.
|
|
418
|
+
*/
|
|
419
|
+
declare function upload(params: UploadParameters): Promise<{
|
|
420
|
+
build: ArgosAPISchema.components["schemas"]["Build"];
|
|
421
|
+
screenshots: Screenshot[];
|
|
422
|
+
}>;
|
|
320
423
|
|
|
321
|
-
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
|
|
|
@@ -131,10 +128,12 @@ var service = {
|
|
|
131
128
|
detect: ({ env }) => Boolean(env.BITRISE_IO),
|
|
132
129
|
config: (context) => {
|
|
133
130
|
const { env } = context;
|
|
131
|
+
const repository = getRepository(context);
|
|
134
132
|
return {
|
|
135
133
|
commit: env.BITRISE_GIT_COMMIT || null,
|
|
136
134
|
branch: env.BITRISE_GIT_BRANCH || null,
|
|
137
|
-
repository
|
|
135
|
+
repository,
|
|
136
|
+
originalRepository: repository,
|
|
138
137
|
jobId: null,
|
|
139
138
|
runId: null,
|
|
140
139
|
runAttempt: null,
|
|
@@ -178,11 +177,13 @@ var service2 = {
|
|
|
178
177
|
detect: ({ env }) => Boolean(env.BUILDKITE),
|
|
179
178
|
config: (context) => {
|
|
180
179
|
const { env } = context;
|
|
180
|
+
const repository = getRepository2(context);
|
|
181
181
|
return {
|
|
182
182
|
// Buildkite doesn't work well so we fallback to git to ensure we have commit and branch
|
|
183
183
|
commit: env.BUILDKITE_COMMIT || head() || null,
|
|
184
184
|
branch: env.BUILDKITE_BRANCH || branch() || null,
|
|
185
|
-
repository
|
|
185
|
+
repository,
|
|
186
|
+
originalRepository: repository,
|
|
186
187
|
jobId: null,
|
|
187
188
|
runId: null,
|
|
188
189
|
runAttempt: null,
|
|
@@ -207,6 +208,7 @@ var service3 = {
|
|
|
207
208
|
branch: env.HEROKU_TEST_RUN_BRANCH || null,
|
|
208
209
|
owner: null,
|
|
209
210
|
repository: null,
|
|
211
|
+
originalRepository: null,
|
|
210
212
|
jobId: null,
|
|
211
213
|
runId: null,
|
|
212
214
|
runAttempt: null,
|
|
@@ -306,13 +308,16 @@ function getBranchFromPayload(payload) {
|
|
|
306
308
|
return null;
|
|
307
309
|
}
|
|
308
310
|
function getRepository3(context, payload) {
|
|
309
|
-
const { env } = context;
|
|
310
311
|
if (payload && "pull_request" in payload && payload.pull_request) {
|
|
311
312
|
const pr = payload.pull_request;
|
|
312
313
|
if (pr.head && pr.head.repo && pr.head.repo.full_name) {
|
|
313
314
|
return pr.head.repo.full_name;
|
|
314
315
|
}
|
|
315
316
|
}
|
|
317
|
+
return getOriginalRepository(context);
|
|
318
|
+
}
|
|
319
|
+
function getOriginalRepository(context) {
|
|
320
|
+
const { env } = context;
|
|
316
321
|
return env.GITHUB_REPOSITORY || null;
|
|
317
322
|
}
|
|
318
323
|
function readEventPayload({ env }) {
|
|
@@ -351,6 +356,7 @@ var service4 = {
|
|
|
351
356
|
return {
|
|
352
357
|
commit: sha,
|
|
353
358
|
repository: getRepository3(context, payload),
|
|
359
|
+
originalRepository: getOriginalRepository(context),
|
|
354
360
|
jobId: env.GITHUB_JOB || null,
|
|
355
361
|
runId: env.GITHUB_RUN_ID || null,
|
|
356
362
|
runAttempt: env.GITHUB_RUN_ATTEMPT ? Number(env.GITHUB_RUN_ATTEMPT) : null,
|
|
@@ -380,6 +386,10 @@ function getRepository4(context) {
|
|
|
380
386
|
if (env.CIRCLE_PR_REPONAME && env.CIRCLE_PR_USERNAME) {
|
|
381
387
|
return `${env.CIRCLE_PR_USERNAME}/${env.CIRCLE_PR_REPONAME}`;
|
|
382
388
|
}
|
|
389
|
+
return getOriginalRepository2(context);
|
|
390
|
+
}
|
|
391
|
+
function getOriginalRepository2(context) {
|
|
392
|
+
const { env } = context;
|
|
383
393
|
if (env.CIRCLE_PROJECT_USERNAME && env.CIRCLE_PROJECT_REPONAME) {
|
|
384
394
|
return `${env.CIRCLE_PROJECT_USERNAME}/${env.CIRCLE_PROJECT_REPONAME}`;
|
|
385
395
|
}
|
|
@@ -395,6 +405,7 @@ var service5 = {
|
|
|
395
405
|
commit: env.CIRCLE_SHA1 || null,
|
|
396
406
|
branch: env.CIRCLE_BRANCH || null,
|
|
397
407
|
repository: getRepository4(context),
|
|
408
|
+
originalRepository: getOriginalRepository2(context),
|
|
398
409
|
jobId: null,
|
|
399
410
|
runId: null,
|
|
400
411
|
runAttempt: null,
|
|
@@ -415,10 +426,11 @@ function getRepository5(context) {
|
|
|
415
426
|
if (env.TRAVIS_PULL_REQUEST_SLUG) {
|
|
416
427
|
return env.TRAVIS_PULL_REQUEST_SLUG;
|
|
417
428
|
}
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
429
|
+
return getOriginalRepository3(context);
|
|
430
|
+
}
|
|
431
|
+
function getOriginalRepository3(context) {
|
|
432
|
+
const { env } = context;
|
|
433
|
+
return env.TRAVIS_REPO_SLUG || null;
|
|
422
434
|
}
|
|
423
435
|
function getPrNumber3(context) {
|
|
424
436
|
const { env } = context;
|
|
@@ -437,6 +449,7 @@ var service6 = {
|
|
|
437
449
|
commit: env.TRAVIS_COMMIT || null,
|
|
438
450
|
branch: env.TRAVIS_BRANCH || null,
|
|
439
451
|
repository: getRepository5(ctx),
|
|
452
|
+
originalRepository: getOriginalRepository3(ctx),
|
|
440
453
|
jobId: null,
|
|
441
454
|
runId: null,
|
|
442
455
|
runAttempt: null,
|
|
@@ -457,6 +470,10 @@ function getRepository6(context) {
|
|
|
457
470
|
if (env.CI_MERGE_REQUEST_PROJECT_PATH) {
|
|
458
471
|
return env.CI_MERGE_REQUEST_PROJECT_PATH;
|
|
459
472
|
}
|
|
473
|
+
return getOriginalRepository4(context);
|
|
474
|
+
}
|
|
475
|
+
function getOriginalRepository4(context) {
|
|
476
|
+
const { env } = context;
|
|
460
477
|
return env.CI_PROJECT_PATH || null;
|
|
461
478
|
}
|
|
462
479
|
var service7 = {
|
|
@@ -469,6 +486,7 @@ var service7 = {
|
|
|
469
486
|
commit: env.CI_COMMIT_SHA || null,
|
|
470
487
|
branch: env.CI_COMMIT_REF_NAME || null,
|
|
471
488
|
repository: getRepository6(context),
|
|
489
|
+
originalRepository: getOriginalRepository4(context),
|
|
472
490
|
jobId: null,
|
|
473
491
|
runId: null,
|
|
474
492
|
runAttempt: null,
|
|
@@ -496,10 +514,12 @@ var service8 = {
|
|
|
496
514
|
key: "git",
|
|
497
515
|
detect: () => checkIsGitRepository(),
|
|
498
516
|
config: () => {
|
|
517
|
+
const repository = getRepository7();
|
|
499
518
|
return {
|
|
500
519
|
commit: head() || null,
|
|
501
520
|
branch: branch() || null,
|
|
502
|
-
repository
|
|
521
|
+
repository,
|
|
522
|
+
originalRepository: repository,
|
|
503
523
|
jobId: null,
|
|
504
524
|
runId: null,
|
|
505
525
|
runAttempt: null,
|
|
@@ -731,6 +751,11 @@ var schema = {
|
|
|
731
751
|
default: null,
|
|
732
752
|
nullable: true
|
|
733
753
|
},
|
|
754
|
+
originalRepository: {
|
|
755
|
+
format: String,
|
|
756
|
+
default: null,
|
|
757
|
+
nullable: true
|
|
758
|
+
},
|
|
734
759
|
ciProvider: {
|
|
735
760
|
format: String,
|
|
736
761
|
default: null,
|
|
@@ -747,6 +772,11 @@ var schema = {
|
|
|
747
772
|
format: String,
|
|
748
773
|
default: null,
|
|
749
774
|
nullable: true
|
|
775
|
+
},
|
|
776
|
+
skipped: {
|
|
777
|
+
env: "ARGOS_SKIPPED",
|
|
778
|
+
format: Boolean,
|
|
779
|
+
default: false
|
|
750
780
|
}
|
|
751
781
|
};
|
|
752
782
|
function createConfig() {
|
|
@@ -777,6 +807,7 @@ async function readConfig(options = {}) {
|
|
|
777
807
|
referenceBranch: options.referenceBranch || defaultConfig.referenceBranch || null,
|
|
778
808
|
referenceCommit: options.referenceCommit || defaultConfig.referenceCommit || null,
|
|
779
809
|
repository: ciEnv?.repository || null,
|
|
810
|
+
originalRepository: ciEnv?.originalRepository || null,
|
|
780
811
|
jobId: ciEnv?.jobId || null,
|
|
781
812
|
runId: ciEnv?.runId || null,
|
|
782
813
|
runAttempt: ciEnv?.runAttempt || null,
|
|
@@ -786,7 +817,8 @@ async function readConfig(options = {}) {
|
|
|
786
817
|
parallelIndex: options.parallelIndex ?? defaultConfig.parallelIndex ?? null,
|
|
787
818
|
mode: options.mode || defaultConfig.mode || null,
|
|
788
819
|
ciProvider: ciEnv?.key || null,
|
|
789
|
-
previewBaseUrl: defaultConfig.previewBaseUrl || null
|
|
820
|
+
previewBaseUrl: defaultConfig.previewBaseUrl || null,
|
|
821
|
+
skipped: options.skipped ?? defaultConfig.skipped ?? false
|
|
790
822
|
});
|
|
791
823
|
if (!config.get("branch") || !config.get("commit")) {
|
|
792
824
|
throw new Error(
|
|
@@ -796,6 +828,83 @@ async function readConfig(options = {}) {
|
|
|
796
828
|
config.validate();
|
|
797
829
|
return config.get();
|
|
798
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";
|
|
799
908
|
|
|
800
909
|
// src/discovery.ts
|
|
801
910
|
import { resolve } from "path";
|
|
@@ -896,40 +1005,6 @@ var hashFile = async (filepath) => {
|
|
|
896
1005
|
return hash.digest("hex");
|
|
897
1006
|
};
|
|
898
1007
|
|
|
899
|
-
// src/auth.ts
|
|
900
|
-
var base64Encode = (obj) => Buffer.from(JSON.stringify(obj), "utf8").toString("base64");
|
|
901
|
-
function getAuthToken({
|
|
902
|
-
token,
|
|
903
|
-
ciProvider,
|
|
904
|
-
repository,
|
|
905
|
-
jobId,
|
|
906
|
-
runId,
|
|
907
|
-
prNumber
|
|
908
|
-
}) {
|
|
909
|
-
if (token) {
|
|
910
|
-
return token;
|
|
911
|
-
}
|
|
912
|
-
switch (ciProvider) {
|
|
913
|
-
case "github-actions": {
|
|
914
|
-
if (!repository || !jobId || !runId) {
|
|
915
|
-
throw new Error(
|
|
916
|
-
`Automatic GitHub Actions variables detection failed. Please add the 'ARGOS_TOKEN'`
|
|
917
|
-
);
|
|
918
|
-
}
|
|
919
|
-
const [owner, repo] = repository.split("/");
|
|
920
|
-
return `tokenless-github-${base64Encode({
|
|
921
|
-
owner,
|
|
922
|
-
repository: repo,
|
|
923
|
-
jobId,
|
|
924
|
-
runId,
|
|
925
|
-
prNumber: prNumber ?? void 0
|
|
926
|
-
})}`;
|
|
927
|
-
}
|
|
928
|
-
default:
|
|
929
|
-
throw new Error("Missing Argos repository token 'ARGOS_TOKEN'");
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
|
-
|
|
933
1008
|
// src/s3.ts
|
|
934
1009
|
import { readFile } from "fs/promises";
|
|
935
1010
|
async function uploadFile(input) {
|
|
@@ -962,7 +1037,10 @@ var chunk = (collection, size) => {
|
|
|
962
1037
|
};
|
|
963
1038
|
|
|
964
1039
|
// src/upload.ts
|
|
965
|
-
import {
|
|
1040
|
+
import {
|
|
1041
|
+
getPlaywrightTracePath,
|
|
1042
|
+
readMetadata
|
|
1043
|
+
} from "@argos-ci/util";
|
|
966
1044
|
|
|
967
1045
|
// src/version.ts
|
|
968
1046
|
import { readVersionFromPackage } from "@argos-ci/util";
|
|
@@ -976,66 +1054,48 @@ async function getArgosCoreSDKIdentifier() {
|
|
|
976
1054
|
|
|
977
1055
|
// src/upload.ts
|
|
978
1056
|
var CHUNK_SIZE = 10;
|
|
979
|
-
async function getConfigFromOptions({
|
|
980
|
-
parallel,
|
|
981
|
-
...options
|
|
982
|
-
}) {
|
|
983
|
-
return readConfig({
|
|
984
|
-
...options,
|
|
985
|
-
parallel: parallel !== void 0 ? Boolean(parallel) : void 0,
|
|
986
|
-
parallelNonce: parallel ? parallel.nonce : void 0,
|
|
987
|
-
parallelTotal: parallel ? parallel.total : void 0,
|
|
988
|
-
parallelIndex: parallel ? parallel.index : void 0
|
|
989
|
-
});
|
|
990
|
-
}
|
|
991
|
-
async function uploadFilesToS3(files) {
|
|
992
|
-
debug(`Split files in chunks of ${CHUNK_SIZE}`);
|
|
993
|
-
const chunks = chunk(files, CHUNK_SIZE);
|
|
994
|
-
debug(`Starting upload of ${chunks.length} chunks`);
|
|
995
|
-
for (let i = 0; i < chunks.length; i++) {
|
|
996
|
-
debug(`Uploading chunk ${i + 1}/${chunks.length}`);
|
|
997
|
-
const timeLabel = `Chunk ${i + 1}/${chunks.length}`;
|
|
998
|
-
debugTime(timeLabel);
|
|
999
|
-
const chunk2 = chunks[i];
|
|
1000
|
-
if (!chunk2) {
|
|
1001
|
-
throw new Error(`Invariant: chunk ${i} is empty`);
|
|
1002
|
-
}
|
|
1003
|
-
await Promise.all(
|
|
1004
|
-
chunk2.map(async ({ url, path, contentType }) => {
|
|
1005
|
-
await uploadFile({
|
|
1006
|
-
url,
|
|
1007
|
-
path,
|
|
1008
|
-
contentType
|
|
1009
|
-
});
|
|
1010
|
-
})
|
|
1011
|
-
);
|
|
1012
|
-
debugTimeEnd(timeLabel);
|
|
1013
|
-
}
|
|
1014
|
-
}
|
|
1015
|
-
function formatPreviewUrl(url, formatter) {
|
|
1016
|
-
if (typeof formatter === "function") {
|
|
1017
|
-
return formatter(url);
|
|
1018
|
-
}
|
|
1019
|
-
const urlObj = new URL(url);
|
|
1020
|
-
return new URL(
|
|
1021
|
-
urlObj.pathname + urlObj.search + urlObj.hash,
|
|
1022
|
-
formatter.baseUrl
|
|
1023
|
-
).href;
|
|
1024
|
-
}
|
|
1025
1057
|
async function upload(params) {
|
|
1026
1058
|
debug("Starting upload with params", params);
|
|
1027
1059
|
const [config, argosSdk] = await Promise.all([
|
|
1028
1060
|
getConfigFromOptions(params),
|
|
1029
1061
|
getArgosCoreSDKIdentifier()
|
|
1030
1062
|
]);
|
|
1031
|
-
const previewUrlFormatter = params.previewUrl ?? (config.previewBaseUrl ? { baseUrl: config.previewBaseUrl } : void 0);
|
|
1032
|
-
const files = params.files ?? ["**/*.{png,jpg,jpeg}"];
|
|
1033
|
-
debug("Using config and files", config, files);
|
|
1034
1063
|
const authToken = getAuthToken(config);
|
|
1035
|
-
const apiClient =
|
|
1064
|
+
const apiClient = createClient2({
|
|
1036
1065
|
baseUrl: config.apiBaseUrl,
|
|
1037
1066
|
authToken
|
|
1038
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);
|
|
1039
1099
|
const foundScreenshots = await discoverScreenshots(files, {
|
|
1040
1100
|
root: params.root,
|
|
1041
1101
|
ignore: params.ignore
|
|
@@ -1077,7 +1137,7 @@ async function upload(params) {
|
|
|
1077
1137
|
debug("Fetch project");
|
|
1078
1138
|
const projectResponse = await apiClient.GET("/project");
|
|
1079
1139
|
if (projectResponse.error) {
|
|
1080
|
-
|
|
1140
|
+
throwAPIError2(projectResponse.error);
|
|
1081
1141
|
}
|
|
1082
1142
|
debug("Project fetched", projectResponse.data);
|
|
1083
1143
|
const { defaultBaseBranch, hasRemoteContentAccess } = projectResponse.data;
|
|
@@ -1148,7 +1208,7 @@ async function upload(params) {
|
|
|
1148
1208
|
}
|
|
1149
1209
|
});
|
|
1150
1210
|
if (createBuildResponse.error) {
|
|
1151
|
-
|
|
1211
|
+
throwAPIError2(createBuildResponse.error);
|
|
1152
1212
|
}
|
|
1153
1213
|
const result = createBuildResponse.data;
|
|
1154
1214
|
debug("Got uploads url", result);
|
|
@@ -1202,37 +1262,47 @@ async function upload(params) {
|
|
|
1202
1262
|
}
|
|
1203
1263
|
});
|
|
1204
1264
|
if (uploadBuildResponse.error) {
|
|
1205
|
-
|
|
1265
|
+
throwAPIError2(uploadBuildResponse.error);
|
|
1206
1266
|
}
|
|
1207
1267
|
return { build: uploadBuildResponse.data.build, screenshots };
|
|
1208
1268
|
}
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
});
|
|
1221
|
-
if (!config.parallelNonce) {
|
|
1222
|
-
throw new Error("parallel.nonce is required to finalize the build");
|
|
1223
|
-
}
|
|
1224
|
-
const finalizeBuildsResult = await apiClient.POST("/builds/finalize", {
|
|
1225
|
-
body: {
|
|
1226
|
-
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`);
|
|
1227
1280
|
}
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
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);
|
|
1231
1291
|
}
|
|
1232
|
-
|
|
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;
|
|
1233
1302
|
}
|
|
1234
1303
|
export {
|
|
1235
1304
|
finalize,
|
|
1305
|
+
getConfigFromOptions,
|
|
1236
1306
|
readConfig,
|
|
1237
1307
|
upload
|
|
1238
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.
|
|
4
|
+
"version": "4.2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
7
7
|
"exports": {
|
|
@@ -40,20 +40,20 @@
|
|
|
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.0",
|
|
44
|
+
"@argos-ci/util": "3.1.1",
|
|
45
45
|
"convict": "^6.2.4",
|
|
46
|
-
"debug": "^4.4.
|
|
46
|
+
"debug": "^4.4.3",
|
|
47
47
|
"fast-glob": "^3.3.3",
|
|
48
|
-
"sharp": "^0.34.
|
|
49
|
-
"tmp": "^0.2.
|
|
48
|
+
"sharp": "^0.34.4",
|
|
49
|
+
"tmp": "^0.2.5"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@octokit/webhooks": "^14.1.3",
|
|
53
53
|
"@types/convict": "^6.1.6",
|
|
54
54
|
"@types/debug": "^4.1.12",
|
|
55
55
|
"@types/tmp": "^0.2.6",
|
|
56
|
-
"msw": "^2.
|
|
56
|
+
"msw": "^2.11.3",
|
|
57
57
|
"vitest": "catalog:"
|
|
58
58
|
},
|
|
59
59
|
"scripts": {
|
|
@@ -64,5 +64,5 @@
|
|
|
64
64
|
"lint": "eslint .",
|
|
65
65
|
"test": "vitest"
|
|
66
66
|
},
|
|
67
|
-
"gitHead": "
|
|
67
|
+
"gitHead": "867a93c5ffc01d55c7385d3ac3903c4c3ab270b6"
|
|
68
68
|
}
|