@argos-ci/cli 0.2.4-alpha.4 → 0.2.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.mjs +478 -2
- package/package.json +7 -7
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,485 @@
|
|
|
1
1
|
import { readFile } from 'node:fs/promises';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { resolve } from 'node:path';
|
|
2
4
|
import { program } from 'commander';
|
|
3
|
-
import
|
|
5
|
+
import convict from 'convict';
|
|
6
|
+
import envCi from 'env-ci';
|
|
7
|
+
import { execSync } from 'child_process';
|
|
8
|
+
import glob from 'fast-glob';
|
|
9
|
+
import { promisify } from 'node:util';
|
|
10
|
+
import sharp from 'sharp';
|
|
11
|
+
import tmp from 'tmp';
|
|
12
|
+
import { createReadStream } from 'node:fs';
|
|
13
|
+
import { createHash } from 'node:crypto';
|
|
14
|
+
import axios from 'axios';
|
|
15
|
+
import createDebug from 'debug';
|
|
4
16
|
import ora from 'ora';
|
|
5
17
|
|
|
6
|
-
const
|
|
18
|
+
const mustBeApiBaseUrl = (value)=>{
|
|
19
|
+
const URL_REGEX = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;
|
|
20
|
+
if (!URL_REGEX.test(value)) {
|
|
21
|
+
throw new Error("Invalid Argos API base URL");
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const mustBeCommit = (value)=>{
|
|
25
|
+
const SHA1_REGEX = /^[0-9a-f]{40}$/;
|
|
26
|
+
if (!SHA1_REGEX.test(value)) {
|
|
27
|
+
const SHA1_SHORT_REGEX = /^[0-9a-f]{7}$/;
|
|
28
|
+
if (SHA1_SHORT_REGEX.test(value)) {
|
|
29
|
+
throw new Error("Short SHA1 is not allowed");
|
|
30
|
+
}
|
|
31
|
+
throw new Error("Invalid commit");
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const mustBeArgosToken = (value)=>{
|
|
35
|
+
if (value && value.length !== 40) {
|
|
36
|
+
throw new Error("Must be a valid Argos repository token");
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
const schema = {
|
|
40
|
+
apiBaseUrl: {
|
|
41
|
+
env: "ARGOS_API_BASE_URL",
|
|
42
|
+
default: "https://api.argos-ci.com/v2/",
|
|
43
|
+
format: mustBeApiBaseUrl
|
|
44
|
+
},
|
|
45
|
+
commit: {
|
|
46
|
+
env: "ARGOS_COMMIT",
|
|
47
|
+
default: "",
|
|
48
|
+
format: mustBeCommit
|
|
49
|
+
},
|
|
50
|
+
branch: {
|
|
51
|
+
env: "ARGOS_BRANCH",
|
|
52
|
+
default: null,
|
|
53
|
+
format: String,
|
|
54
|
+
nullable: true
|
|
55
|
+
},
|
|
56
|
+
token: {
|
|
57
|
+
env: "ARGOS_TOKEN",
|
|
58
|
+
default: null,
|
|
59
|
+
format: mustBeArgosToken
|
|
60
|
+
},
|
|
61
|
+
buildName: {
|
|
62
|
+
env: "ARGOS_BUILD_NAME",
|
|
63
|
+
default: null,
|
|
64
|
+
format: String,
|
|
65
|
+
nullable: true
|
|
66
|
+
},
|
|
67
|
+
parallel: {
|
|
68
|
+
env: "ARGOS_PARALLEL",
|
|
69
|
+
default: false,
|
|
70
|
+
format: Boolean
|
|
71
|
+
},
|
|
72
|
+
parallelNonce: {
|
|
73
|
+
env: "ARGOS_PARALLEL_NONCE",
|
|
74
|
+
format: String,
|
|
75
|
+
default: null,
|
|
76
|
+
nullable: true
|
|
77
|
+
},
|
|
78
|
+
parallelTotal: {
|
|
79
|
+
env: "ARGOS_PARALLEL_TOTAL",
|
|
80
|
+
format: "nat",
|
|
81
|
+
default: null,
|
|
82
|
+
nullable: true
|
|
83
|
+
},
|
|
84
|
+
ciService: {
|
|
85
|
+
format: String,
|
|
86
|
+
default: null,
|
|
87
|
+
nullable: true
|
|
88
|
+
},
|
|
89
|
+
jobId: {
|
|
90
|
+
format: String,
|
|
91
|
+
default: null,
|
|
92
|
+
nullable: true
|
|
93
|
+
},
|
|
94
|
+
runId: {
|
|
95
|
+
format: String,
|
|
96
|
+
default: null,
|
|
97
|
+
nullable: true
|
|
98
|
+
},
|
|
99
|
+
owner: {
|
|
100
|
+
format: String,
|
|
101
|
+
default: null,
|
|
102
|
+
nullable: true
|
|
103
|
+
},
|
|
104
|
+
repository: {
|
|
105
|
+
format: String,
|
|
106
|
+
default: null,
|
|
107
|
+
nullable: true
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
const createConfig = ()=>{
|
|
111
|
+
return convict(schema, {
|
|
112
|
+
args: []
|
|
113
|
+
});
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Omit undefined properties from an object.
|
|
118
|
+
*/ const omitUndefined = (obj)=>{
|
|
119
|
+
const result = {};
|
|
120
|
+
Object.keys(obj).forEach((key)=>{
|
|
121
|
+
if (obj[key] !== undefined) {
|
|
122
|
+
result[key] = obj[key];
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
return result;
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
const service$1 = {
|
|
129
|
+
detect: ({ env })=>Boolean(env.HEROKU_TEST_RUN_ID),
|
|
130
|
+
config: ({ env })=>({
|
|
131
|
+
name: "Heroku",
|
|
132
|
+
commit: env.HEROKU_TEST_RUN_COMMIT_VERSION || null,
|
|
133
|
+
branch: env.HEROKU_TEST_RUN_BRANCH || null,
|
|
134
|
+
owner: null,
|
|
135
|
+
repository: null,
|
|
136
|
+
jobId: env.HEROKU_TEST_RUN_ID || null,
|
|
137
|
+
runId: null
|
|
138
|
+
})
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const getSha = ({ env })=>{
|
|
142
|
+
const isPr = env.GITHUB_EVENT_NAME === "pull_request" || env.GITHUB_EVENT_NAME === "pull_request_target";
|
|
143
|
+
if (isPr) {
|
|
144
|
+
const mergeCommitRegex = /^[a-z0-9]{40} [a-z0-9]{40}$/;
|
|
145
|
+
const mergeCommitMessage = execSync("git show --no-patch --format=%P").toString().trim();
|
|
146
|
+
// console.log(
|
|
147
|
+
// `Handling PR with parent hash(es) '${mergeCommitMessage}' of current commit.`
|
|
148
|
+
// );
|
|
149
|
+
if (mergeCommitRegex.exec(mergeCommitMessage)) {
|
|
150
|
+
const mergeCommit = mergeCommitMessage.split(" ")[1];
|
|
151
|
+
// console.log(
|
|
152
|
+
// `Fixing merge commit SHA ${process.env.GITHUB_SHA} -> ${mergeCommit}`
|
|
153
|
+
// );
|
|
154
|
+
return mergeCommit;
|
|
155
|
+
} else if (mergeCommitMessage === "") {
|
|
156
|
+
console.error(`Error: automatic detection of commit SHA failed.
|
|
157
|
+
|
|
158
|
+
Please run "actions/checkout" with "fetch-depth: 2". Example:
|
|
159
|
+
|
|
160
|
+
steps:
|
|
161
|
+
- uses: actions/checkout@v3
|
|
162
|
+
with:
|
|
163
|
+
fetch-depth: 2
|
|
164
|
+
|
|
165
|
+
`);
|
|
166
|
+
process.exit(1);
|
|
167
|
+
} else {
|
|
168
|
+
console.error(`Commit with SHA ${process.env.GITHUB_SHA} is not a valid commit`);
|
|
169
|
+
process.exit(1);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return process.env.GITHUB_SHA ?? null;
|
|
173
|
+
};
|
|
174
|
+
function getBranch({ env }) {
|
|
175
|
+
if (env.GITHUB_HEAD_REF) {
|
|
176
|
+
return env.GITHUB_HEAD_REF;
|
|
177
|
+
}
|
|
178
|
+
const branchRegex = /refs\/heads\/(.*)/;
|
|
179
|
+
const branchMatches = branchRegex.exec(env.GITHUB_REF || "");
|
|
180
|
+
if (branchMatches) {
|
|
181
|
+
return branchMatches[1];
|
|
182
|
+
}
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
function getRepository({ env }) {
|
|
186
|
+
if (!env.GITHUB_REPOSITORY_OWNER) return null;
|
|
187
|
+
const [, ...repositoryParts] = env.GITHUB_REPOSITORY_OWNER.split("/");
|
|
188
|
+
return repositoryParts.join("/");
|
|
189
|
+
}
|
|
190
|
+
const service = {
|
|
191
|
+
detect: ({ env })=>Boolean(env.GITHUB_ACTIONS),
|
|
192
|
+
config: ({ env })=>({
|
|
193
|
+
name: "GitHub Actions",
|
|
194
|
+
commit: getSha({
|
|
195
|
+
env
|
|
196
|
+
}),
|
|
197
|
+
branch: getBranch({
|
|
198
|
+
env
|
|
199
|
+
}),
|
|
200
|
+
owner: env.GITHUB_REPOSITORY_OWNER || null,
|
|
201
|
+
repository: getRepository({
|
|
202
|
+
env
|
|
203
|
+
}),
|
|
204
|
+
jobId: env.GITHUB_JOB || null,
|
|
205
|
+
runId: env.GITHUB_RUN_ID || null
|
|
206
|
+
})
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
const services = [
|
|
210
|
+
service$1,
|
|
211
|
+
service
|
|
212
|
+
];
|
|
213
|
+
const getCiEnvironment = ({ env =process.env } = {})=>{
|
|
214
|
+
const ctx = {
|
|
215
|
+
env
|
|
216
|
+
};
|
|
217
|
+
const service = services.find((service)=>service.detect(ctx));
|
|
218
|
+
// Internal service matched
|
|
219
|
+
if (service) {
|
|
220
|
+
return service.config(ctx);
|
|
221
|
+
}
|
|
222
|
+
// Fallback on env-ci detection
|
|
223
|
+
const ciContext = envCi(ctx);
|
|
224
|
+
const name = ciContext.isCi ? ciContext.name ?? null : ciContext.commit ? "Git" : null;
|
|
225
|
+
const commit = ciContext.commit ?? null;
|
|
226
|
+
const branch = (ciContext.branch || ciContext.prBranch) ?? null;
|
|
227
|
+
const slug = ciContext.slug ? ciContext.slug.split("/") : null;
|
|
228
|
+
const owner = slug ? slug[0] : null;
|
|
229
|
+
const repository = slug ? slug[1] : null;
|
|
230
|
+
const jobId = ciContext.job ?? null;
|
|
231
|
+
const runId = null;
|
|
232
|
+
return commit ? {
|
|
233
|
+
name,
|
|
234
|
+
commit,
|
|
235
|
+
branch,
|
|
236
|
+
owner,
|
|
237
|
+
repository,
|
|
238
|
+
jobId,
|
|
239
|
+
runId
|
|
240
|
+
} : null;
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
const discoverScreenshots = async (patterns, { root =process.cwd() , ignore } = {})=>{
|
|
244
|
+
const matches = await glob(patterns, {
|
|
245
|
+
onlyFiles: true,
|
|
246
|
+
ignore,
|
|
247
|
+
cwd: root
|
|
248
|
+
});
|
|
249
|
+
return matches.map((match)=>({
|
|
250
|
+
name: match,
|
|
251
|
+
path: resolve(root, match)
|
|
252
|
+
}));
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
const tmpFile = promisify(tmp.file);
|
|
256
|
+
const getImageFormat = async (filepath)=>{
|
|
257
|
+
const metadata = await sharp(filepath).metadata();
|
|
258
|
+
if (!metadata.format) {
|
|
259
|
+
throw new Error(`Could not get image format for ${filepath}`);
|
|
260
|
+
}
|
|
261
|
+
return metadata.format;
|
|
262
|
+
};
|
|
263
|
+
const optimizeScreenshot = async (filepath, format)=>{
|
|
264
|
+
const resultFilePath = await tmpFile();
|
|
265
|
+
const optimization = sharp(filepath).resize(2048, 20480, {
|
|
266
|
+
fit: "inside",
|
|
267
|
+
withoutEnlargement: true
|
|
268
|
+
});
|
|
269
|
+
switch(format){
|
|
270
|
+
case "jpeg":
|
|
271
|
+
case "jpg":
|
|
272
|
+
{
|
|
273
|
+
optimization.jpeg();
|
|
274
|
+
break;
|
|
275
|
+
}
|
|
276
|
+
case "png":
|
|
277
|
+
{
|
|
278
|
+
optimization.png();
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
await optimization.toFile(resultFilePath);
|
|
283
|
+
return resultFilePath;
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
const hashFile = async (filepath)=>{
|
|
287
|
+
const fileStream = createReadStream(filepath);
|
|
288
|
+
const hash = createHash("sha256");
|
|
289
|
+
await new Promise((resolve, reject)=>{
|
|
290
|
+
fileStream.on("error", reject);
|
|
291
|
+
hash.on("error", reject);
|
|
292
|
+
hash.on("finish", resolve);
|
|
293
|
+
fileStream.pipe(hash);
|
|
294
|
+
});
|
|
295
|
+
return hash.read().toString("hex");
|
|
296
|
+
};
|
|
297
|
+
|
|
298
|
+
const base64Encode = (obj)=>Buffer.from(JSON.stringify(obj), "utf8").toString("base64");
|
|
299
|
+
const getBearerToken = ({ token , ciService , owner , repository , jobId , runId })=>{
|
|
300
|
+
if (token) return `Bearer ${token}`;
|
|
301
|
+
switch(ciService){
|
|
302
|
+
case "GitHub Actions":
|
|
303
|
+
{
|
|
304
|
+
if (!owner || !repository || !jobId || !runId) {
|
|
305
|
+
throw new Error(`Automatic ${ciService} variables detection failed. Please add the 'ARGOS_TOKEN'`);
|
|
306
|
+
}
|
|
307
|
+
return `Bearer tokenless-github-${base64Encode({
|
|
308
|
+
owner,
|
|
309
|
+
repository,
|
|
310
|
+
jobId,
|
|
311
|
+
runId
|
|
312
|
+
})}`;
|
|
313
|
+
}
|
|
314
|
+
default:
|
|
315
|
+
throw new Error("Missing Argos repository token 'ARGOS_TOKEN'");
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
const createArgosApiClient = (options)=>{
|
|
319
|
+
const axiosInstance = axios.create({
|
|
320
|
+
baseURL: options.baseUrl,
|
|
321
|
+
headers: {
|
|
322
|
+
Authorization: options.bearerToken,
|
|
323
|
+
"Content-Type": "application/json",
|
|
324
|
+
Accept: "application/json"
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
const call = async (method, path, data)=>{
|
|
328
|
+
try {
|
|
329
|
+
const response = await axiosInstance.request({
|
|
330
|
+
method,
|
|
331
|
+
url: path,
|
|
332
|
+
data
|
|
333
|
+
});
|
|
334
|
+
return response.data;
|
|
335
|
+
} catch (error) {
|
|
336
|
+
if (error?.response?.data?.error?.message) {
|
|
337
|
+
// @ts-ignore
|
|
338
|
+
throw new Error(error.response.data.error.message, {
|
|
339
|
+
cause: error
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
throw error;
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
return {
|
|
346
|
+
createBuild: async (input)=>{
|
|
347
|
+
return call("POST", "/builds", input);
|
|
348
|
+
},
|
|
349
|
+
updateBuild: async (input)=>{
|
|
350
|
+
const { buildId , ...body } = input;
|
|
351
|
+
return call("PUT", `/builds/${buildId}`, body);
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
const formatToContentType = (format)=>{
|
|
357
|
+
switch(format){
|
|
358
|
+
case "jpeg":
|
|
359
|
+
case "jpg":
|
|
360
|
+
return "image/jpeg";
|
|
361
|
+
case "png":
|
|
362
|
+
return "image/png";
|
|
363
|
+
default:
|
|
364
|
+
throw new Error(`Unsupported format ${format}`);
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
const upload$1 = async (input)=>{
|
|
368
|
+
const file = await readFile(input.path);
|
|
369
|
+
await axios({
|
|
370
|
+
method: "PUT",
|
|
371
|
+
url: input.url,
|
|
372
|
+
data: file,
|
|
373
|
+
headers: {
|
|
374
|
+
"Content-Type": formatToContentType(input.format)
|
|
375
|
+
}
|
|
376
|
+
});
|
|
377
|
+
};
|
|
378
|
+
|
|
379
|
+
const debug = createDebug("@argos-ci/core");
|
|
380
|
+
|
|
381
|
+
const getConfigFromOptions = (options)=>{
|
|
382
|
+
const { apiBaseUrl , commit , branch , token , buildName , parallel } = options;
|
|
383
|
+
const config = createConfig();
|
|
384
|
+
config.load(omitUndefined({
|
|
385
|
+
apiBaseUrl,
|
|
386
|
+
commit,
|
|
387
|
+
branch,
|
|
388
|
+
token,
|
|
389
|
+
buildName,
|
|
390
|
+
parallel: Boolean(parallel),
|
|
391
|
+
parallelNonce: parallel ? parallel.nonce : null,
|
|
392
|
+
parallelTotal: parallel ? parallel.total : null
|
|
393
|
+
}));
|
|
394
|
+
if (!config.get("commit")) {
|
|
395
|
+
const ciEnv = getCiEnvironment();
|
|
396
|
+
if (ciEnv) {
|
|
397
|
+
config.load(omitUndefined({
|
|
398
|
+
commit: ciEnv.commit,
|
|
399
|
+
branch: ciEnv.branch,
|
|
400
|
+
ciService: ciEnv.name,
|
|
401
|
+
owner: ciEnv.owner,
|
|
402
|
+
repository: ciEnv.repository,
|
|
403
|
+
jobId: ciEnv.jobId,
|
|
404
|
+
runId: ciEnv.runId
|
|
405
|
+
}));
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
config.validate();
|
|
409
|
+
return config.get();
|
|
410
|
+
};
|
|
411
|
+
/**
|
|
412
|
+
* Upload screenshots to argos-ci.com.
|
|
413
|
+
*/ const upload = async (params)=>{
|
|
414
|
+
// Read config
|
|
415
|
+
const config = getConfigFromOptions(params);
|
|
416
|
+
const files = params.files ?? [
|
|
417
|
+
"**/*.{png,jpg,jpeg}"
|
|
418
|
+
];
|
|
419
|
+
const apiClient = createArgosApiClient({
|
|
420
|
+
baseUrl: config.apiBaseUrl,
|
|
421
|
+
bearerToken: getBearerToken(config)
|
|
422
|
+
});
|
|
423
|
+
// Collect screenshots
|
|
424
|
+
const foundScreenshots = await discoverScreenshots(files, {
|
|
425
|
+
root: params.root,
|
|
426
|
+
ignore: params.ignore
|
|
427
|
+
});
|
|
428
|
+
// Optimize & compute hashes
|
|
429
|
+
const screenshots = await Promise.all(foundScreenshots.map(async (screenshot)=>{
|
|
430
|
+
const format = await getImageFormat(screenshot.path);
|
|
431
|
+
const optimizedPath = await optimizeScreenshot(screenshot.path, format);
|
|
432
|
+
const hash = await hashFile(optimizedPath);
|
|
433
|
+
return {
|
|
434
|
+
...screenshot,
|
|
435
|
+
optimizedPath,
|
|
436
|
+
format,
|
|
437
|
+
hash
|
|
438
|
+
};
|
|
439
|
+
}));
|
|
440
|
+
// Create build
|
|
441
|
+
debug("Creating build");
|
|
442
|
+
const result = await apiClient.createBuild({
|
|
443
|
+
commit: config.commit,
|
|
444
|
+
branch: config.branch,
|
|
445
|
+
name: config.buildName,
|
|
446
|
+
parallel: config.parallel,
|
|
447
|
+
parallelNonce: config.parallelNonce,
|
|
448
|
+
screenshotKeys: Array.from(new Set(screenshots.map((screenshot)=>screenshot.hash)))
|
|
449
|
+
});
|
|
450
|
+
debug("Got screenshots", result);
|
|
451
|
+
// Upload screenshots
|
|
452
|
+
debug("Uploading screenshots");
|
|
453
|
+
await Promise.all(result.screenshots.map(async ({ key , putUrl })=>{
|
|
454
|
+
const screenshot = screenshots.find((s)=>s.hash === key);
|
|
455
|
+
if (!screenshot) {
|
|
456
|
+
throw new Error(`Invariant: screenshot with hash ${key} not found`);
|
|
457
|
+
}
|
|
458
|
+
await upload$1({
|
|
459
|
+
url: putUrl,
|
|
460
|
+
path: screenshot.optimizedPath,
|
|
461
|
+
format: screenshot.format
|
|
462
|
+
});
|
|
463
|
+
}));
|
|
464
|
+
// Update build
|
|
465
|
+
debug("Updating build");
|
|
466
|
+
await apiClient.updateBuild({
|
|
467
|
+
buildId: result.build.id,
|
|
468
|
+
screenshots: screenshots.map((screenshot)=>({
|
|
469
|
+
key: screenshot.hash,
|
|
470
|
+
name: screenshot.name
|
|
471
|
+
})),
|
|
472
|
+
parallel: config.parallel,
|
|
473
|
+
parallelTotal: config.parallelTotal
|
|
474
|
+
});
|
|
475
|
+
return {
|
|
476
|
+
build: result.build,
|
|
477
|
+
screenshots
|
|
478
|
+
};
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
const __dirname = fileURLToPath(new URL(".", import.meta.url));
|
|
482
|
+
const rawPkg = await readFile(resolve(__dirname, "..", "package.json"), "utf8");
|
|
7
483
|
const pkg = JSON.parse(rawPkg);
|
|
8
484
|
program.name(pkg.name).description("Interact with and upload screenshots to argos-ci.com via command line.").version(pkg.version);
|
|
9
485
|
program.command("upload").argument("<directory>", "Directory to upload").description("Upload screenshots to argos-ci.com").option("-f, --files <patterns...>", "One or more globs matching image file paths to upload", "**/*.{png,jpg,jpeg}").option("-i, --ignore <patterns...>", 'One or more globs matching image file paths to ignore (ex: "**/*.png **/diff.jpg")').option("--token <token>", "Repository token").option("--build-name <string>", "Name of the build, in case you want to run multiple Argos builds in a single CI job").option("--parallel", "Enable parallel mode. Run multiple Argos builds and combine them at the end").option("--parallel-total <number>", "The number of parallel nodes being ran").option("--parallel-nonce <string>", "A unique ID for this parallel build").action(async (directory, options)=>{
|
package/package.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@argos-ci/cli",
|
|
3
3
|
"description": "Visual testing solution to avoid visual regression. Argos CLI is used to interact with and upload screenshots to argos-ci.com via command line.",
|
|
4
|
-
"version": "0.2.4
|
|
4
|
+
"version": "0.2.4",
|
|
5
5
|
"bin": {
|
|
6
6
|
"argos": "./bin/argos-cli.js"
|
|
7
7
|
},
|
|
8
8
|
"scripts": {
|
|
9
9
|
"prebuild": "rm -rf dist",
|
|
10
10
|
"build": "rollup -c",
|
|
11
|
-
"e2e": "npx @argos-ci/cli upload ../../__fixtures__ --build-name \"argos-cli-e2e-node-$NODE_VERSION\""
|
|
11
|
+
"e2e": "npx @argos-ci/cli upload ../../__fixtures__ --build-name \"argos-cli-e2e-node-$NODE_VERSION-$OS\""
|
|
12
12
|
},
|
|
13
13
|
"type": "module",
|
|
14
14
|
"exports": {
|
|
@@ -40,14 +40,14 @@
|
|
|
40
40
|
"access": "public"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@argos-ci/core": "^0.
|
|
44
|
-
"commander": "^9.4.
|
|
43
|
+
"@argos-ci/core": "^0.5.0",
|
|
44
|
+
"commander": "^9.4.1",
|
|
45
45
|
"ora": "^6.1.2",
|
|
46
46
|
"update-notifier": "^6.0.2"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"rollup": "^2.
|
|
50
|
-
"rollup-plugin-swc3": "^0.
|
|
49
|
+
"rollup": "^2.79.1",
|
|
50
|
+
"rollup-plugin-swc3": "^0.6.0"
|
|
51
51
|
},
|
|
52
|
-
"gitHead": "
|
|
52
|
+
"gitHead": "c085c7e514623e54a86b2f311ff988709be391d0"
|
|
53
53
|
}
|