@argos-ci/cli 0.3.1 → 0.3.3-alpha.1

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/README.md +1 -1
  2. package/dist/index.mjs +104 -62
  3. package/package.json +3 -3
package/README.md CHANGED
@@ -16,4 +16,4 @@ Argos CLI is used to interact with and upload screenshots to [argos-ci.com](http
16
16
 
17
17
  ## Links
18
18
 
19
- - [Official CLI Docs](https://docs.argos-ci.com)
19
+ - [Official CLI Docs](https://argos-ci.com/docs)
package/dist/index.mjs CHANGED
@@ -96,6 +96,11 @@ const schema = {
96
96
  default: null,
97
97
  nullable: true
98
98
  },
99
+ prNumber: {
100
+ format: String,
101
+ default: null,
102
+ nullable: true
103
+ },
99
104
  owner: {
100
105
  format: String,
101
106
  default: null,
@@ -125,7 +130,7 @@ const createConfig = ()=>{
125
130
  return result;
126
131
  };
127
132
 
128
- const service$1 = {
133
+ const service$3 = {
129
134
  detect: ({ env })=>Boolean(env.HEROKU_TEST_RUN_ID),
130
135
  config: ({ env })=>({
131
136
  name: "Heroku",
@@ -134,7 +139,8 @@ const service$1 = {
134
139
  owner: null,
135
140
  repository: null,
136
141
  jobId: env.HEROKU_TEST_RUN_ID || null,
137
- runId: null
142
+ runId: null,
143
+ prNumber: null
138
144
  })
139
145
  };
140
146
 
@@ -186,7 +192,15 @@ function getRepository({ env }) {
186
192
  if (!env.GITHUB_REPOSITORY) return null;
187
193
  return env.GITHUB_REPOSITORY.split("/")[1];
188
194
  }
189
- const service = {
195
+ const getPrNumber$1 = ({ env })=>{
196
+ const branchRegex = /refs\/pull\/(\d+)/;
197
+ const branchMatches = branchRegex.exec(env.GITHUB_REF || "");
198
+ if (branchMatches) {
199
+ branchMatches[1];
200
+ }
201
+ return null;
202
+ };
203
+ const service$2 = {
190
204
  detect: ({ env })=>Boolean(env.GITHUB_ACTIONS),
191
205
  config: ({ env })=>({
192
206
  name: "GitHub Actions",
@@ -201,24 +215,68 @@ const service = {
201
215
  env
202
216
  }),
203
217
  jobId: env.GITHUB_JOB || null,
204
- runId: env.GITHUB_RUN_ID || null
218
+ runId: env.GITHUB_RUN_ID || null,
219
+ prNumber: getPrNumber$1({
220
+ env
221
+ })
205
222
  })
206
223
  };
207
224
 
225
+ const getPrNumber = ({ env })=>{
226
+ const branchRegex = /pull\/(\d+)/;
227
+ const branchMatches = branchRegex.exec(env.CIRCLE_PULL_REQUEST || "");
228
+ if (branchMatches) {
229
+ branchMatches[1];
230
+ }
231
+ return null;
232
+ };
233
+ const service$1 = {
234
+ detect: ({ env })=>Boolean(env.CIRCLECI),
235
+ config: ({ env })=>{
236
+ const ciProps = envCiDetection({
237
+ env
238
+ });
239
+ return {
240
+ name: "CircleCI",
241
+ commit: ciProps?.commit || null,
242
+ branch: ciProps?.branch || null,
243
+ owner: ciProps?.owner || null,
244
+ repository: ciProps?.repository || null,
245
+ jobId: ciProps?.jobId || null,
246
+ runId: ciProps?.runId || null,
247
+ prNumber: getPrNumber({
248
+ env
249
+ })
250
+ };
251
+ }
252
+ };
253
+
254
+ const service = {
255
+ detect: ({ env })=>Boolean(env.TRAVIS),
256
+ config: ({ env })=>{
257
+ const ciProps = envCiDetection({
258
+ env
259
+ });
260
+ return {
261
+ name: "Travis CI",
262
+ commit: ciProps?.commit || null,
263
+ branch: ciProps?.branch || null,
264
+ owner: ciProps?.owner || null,
265
+ repository: ciProps?.repository || null,
266
+ jobId: ciProps?.jobId || null,
267
+ runId: ciProps?.runId || null,
268
+ prNumber: env.TRAVIS_PULL_REQUEST || null
269
+ };
270
+ }
271
+ };
272
+
208
273
  const services = [
274
+ service$3,
275
+ service$2,
209
276
  service$1,
210
277
  service
211
278
  ];
212
- const getCiEnvironment = ({ env =process.env } = {})=>{
213
- const ctx = {
214
- env
215
- };
216
- const service = services.find((service)=>service.detect(ctx));
217
- // Internal service matched
218
- if (service) {
219
- return service.config(ctx);
220
- }
221
- // Fallback on env-ci detection
279
+ const envCiDetection = (ctx)=>{
222
280
  const ciContext = envCi(ctx);
223
281
  const name = ciContext.isCi ? ciContext.name ?? null : ciContext.commit ? "Git" : null;
224
282
  const commit = ciContext.commit ?? null;
@@ -228,6 +286,7 @@ const getCiEnvironment = ({ env =process.env } = {})=>{
228
286
  const repository = slug ? slug[1] : null;
229
287
  const jobId = ciContext.job ?? null;
230
288
  const runId = null;
289
+ const prNumber = null;
231
290
  return commit ? {
232
291
  name,
233
292
  commit,
@@ -235,9 +294,21 @@ const getCiEnvironment = ({ env =process.env } = {})=>{
235
294
  owner,
236
295
  repository,
237
296
  jobId,
238
- runId
297
+ runId,
298
+ prNumber
239
299
  } : null;
240
300
  };
301
+ const getCiEnvironment = ({ env =process.env } = {})=>{
302
+ const ctx = {
303
+ env
304
+ };
305
+ const service = services.find((service)=>service.detect(ctx));
306
+ // Internal service matched
307
+ if (service) {
308
+ return service.config(ctx);
309
+ }
310
+ return envCiDetection(ctx);
311
+ };
241
312
 
242
313
  const discoverScreenshots = async (patterns, { root =process.cwd() , ignore } = {})=>{
243
314
  const matches = await glob(patterns, {
@@ -252,33 +323,14 @@ const discoverScreenshots = async (patterns, { root =process.cwd() , ignore } =
252
323
  };
253
324
 
254
325
  const tmpFile = promisify(tmp.file);
255
- const getImageFormat = async (filepath)=>{
256
- const metadata = await sharp(filepath).metadata();
257
- if (!metadata.format) {
258
- throw new Error(`Could not get image format for ${filepath}`);
259
- }
260
- return metadata.format;
261
- };
262
- const optimizeScreenshot = async (filepath, format)=>{
326
+ const optimizeScreenshot = async (filepath)=>{
263
327
  const resultFilePath = await tmpFile();
264
- const optimization = sharp(filepath).resize(2048, 20480, {
328
+ await sharp(filepath).resize(2048, 20480, {
265
329
  fit: "inside",
266
330
  withoutEnlargement: true
267
- });
268
- switch(format){
269
- case "jpeg":
270
- case "jpg":
271
- {
272
- optimization.jpeg();
273
- break;
274
- }
275
- case "png":
276
- {
277
- optimization.png();
278
- break;
279
- }
280
- }
281
- await optimization.toFile(resultFilePath);
331
+ }).png({
332
+ force: true
333
+ }).toFile(resultFilePath);
282
334
  return resultFilePath;
283
335
  };
284
336
 
@@ -291,11 +343,11 @@ const hashFile = async (filepath)=>{
291
343
  hash.on("finish", resolve);
292
344
  fileStream.pipe(hash);
293
345
  });
294
- return hash.read().toString("hex");
346
+ return hash.digest("hex");
295
347
  };
296
348
 
297
349
  const base64Encode = (obj)=>Buffer.from(JSON.stringify(obj), "utf8").toString("base64");
298
- const getBearerToken = ({ token , ciService , owner , repository , jobId , runId })=>{
350
+ const getBearerToken = ({ token , ciService , owner , repository , jobId , runId , prNumber })=>{
299
351
  if (token) return `Bearer ${token}`;
300
352
  switch(ciService){
301
353
  case "GitHub Actions":
@@ -307,7 +359,8 @@ const getBearerToken = ({ token , ciService , owner , repository , jobId , runId
307
359
  owner,
308
360
  repository,
309
361
  jobId,
310
- runId
362
+ runId,
363
+ prNumber
311
364
  })}`;
312
365
  }
313
366
  default:
@@ -352,17 +405,6 @@ const createArgosApiClient = (options)=>{
352
405
  };
353
406
  };
354
407
 
355
- const formatToContentType = (format)=>{
356
- switch(format){
357
- case "jpeg":
358
- case "jpg":
359
- return "image/jpeg";
360
- case "png":
361
- return "image/png";
362
- default:
363
- throw new Error(`Unsupported format ${format}`);
364
- }
365
- };
366
408
  const upload$1 = async (input)=>{
367
409
  const file = await readFile(input.path);
368
410
  await axios({
@@ -370,7 +412,7 @@ const upload$1 = async (input)=>{
370
412
  url: input.url,
371
413
  data: file,
372
414
  headers: {
373
- "Content-Type": formatToContentType(input.format)
415
+ "Content-Type": "image/png"
374
416
  }
375
417
  });
376
418
  };
@@ -378,13 +420,14 @@ const upload$1 = async (input)=>{
378
420
  const debug = createDebug("@argos-ci/core");
379
421
 
380
422
  const getConfigFromOptions = (options)=>{
381
- const { apiBaseUrl , commit , branch , token , buildName , parallel } = options;
423
+ const { apiBaseUrl , commit , branch , token , buildName , parallel , prNumber } = options;
382
424
  const config = createConfig();
383
425
  config.load(omitUndefined({
384
426
  apiBaseUrl,
385
427
  commit,
386
428
  branch,
387
429
  token,
430
+ prNumber,
388
431
  buildName,
389
432
  parallel: Boolean(parallel),
390
433
  parallelNonce: parallel ? parallel.nonce : null,
@@ -400,7 +443,8 @@ const getConfigFromOptions = (options)=>{
400
443
  owner: ciEnv.owner,
401
444
  repository: ciEnv.repository,
402
445
  jobId: ciEnv.jobId,
403
- runId: ciEnv.runId
446
+ runId: ciEnv.runId,
447
+ prNumber: ciEnv.prNumber
404
448
  }));
405
449
  }
406
450
  }
@@ -426,13 +470,11 @@ const getConfigFromOptions = (options)=>{
426
470
  });
427
471
  // Optimize & compute hashes
428
472
  const screenshots = await Promise.all(foundScreenshots.map(async (screenshot)=>{
429
- const format = await getImageFormat(screenshot.path);
430
- const optimizedPath = await optimizeScreenshot(screenshot.path, format);
473
+ const optimizedPath = await optimizeScreenshot(screenshot.path);
431
474
  const hash = await hashFile(optimizedPath);
432
475
  return {
433
476
  ...screenshot,
434
477
  optimizedPath,
435
- format,
436
478
  hash
437
479
  };
438
480
  }));
@@ -456,8 +498,7 @@ const getConfigFromOptions = (options)=>{
456
498
  }
457
499
  await upload$1({
458
500
  url: putUrl,
459
- path: screenshot.optimizedPath,
460
- format: screenshot.format
501
+ path: screenshot.optimizedPath
461
502
  });
462
503
  }));
463
504
  // Update build
@@ -481,7 +522,7 @@ const __dirname = fileURLToPath(new URL(".", import.meta.url));
481
522
  const rawPkg = await readFile(resolve(__dirname, "..", "package.json"), "utf8");
482
523
  const pkg = JSON.parse(rawPkg);
483
524
  program.name(pkg.name).description("Interact with and upload screenshots to argos-ci.com via command line.").version(pkg.version);
484
- 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)=>{
525
+ 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("--prNumber <number>", "Pull-request number").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)=>{
485
526
  const spinner = ora("Uploading screenshots").start();
486
527
  try {
487
528
  const result = await upload({
@@ -489,6 +530,7 @@ program.command("upload").argument("<directory>", "Directory to upload").descrip
489
530
  buildName: options.buildName,
490
531
  files: options.files,
491
532
  ignore: options.ignore,
533
+ prNumber: options.prNumber,
492
534
  parallel: options.parallel ? {
493
535
  nonce: options.parallelNonce,
494
536
  total: options.parallelTotal
package/package.json CHANGED
@@ -1,7 +1,7 @@
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.3.1",
4
+ "version": "0.3.3-alpha.1+46d7443",
5
5
  "bin": {
6
6
  "argos": "./bin/argos-cli.js"
7
7
  },
@@ -40,7 +40,7 @@
40
40
  "access": "public"
41
41
  },
42
42
  "dependencies": {
43
- "@argos-ci/core": "^0.6.1",
43
+ "@argos-ci/core": "^0.6.3-alpha.1+46d7443",
44
44
  "commander": "^9.4.1",
45
45
  "ora": "^6.1.2",
46
46
  "update-notifier": "^6.0.2"
@@ -49,5 +49,5 @@
49
49
  "rollup": "^2.79.1",
50
50
  "rollup-plugin-swc3": "^0.6.0"
51
51
  },
52
- "gitHead": "653c9799ae22607b6bc8442c94ceb98ae1eaf0d5"
52
+ "gitHead": "46d7443fe360fe5d42482e404bd3ab5c05116567"
53
53
  }