@argos-ci/core 2.4.1 → 2.4.2-alpha.6

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 (2) hide show
  1. package/dist/index.mjs +167 -75
  2. package/package.json +8 -7
package/dist/index.mjs CHANGED
@@ -1,3 +1,4 @@
1
+ import { createClient } from '@argos-ci/api-client';
1
2
  import convict from 'convict';
2
3
  import { execSync } from 'node:child_process';
3
4
  import { existsSync, readFileSync, createReadStream } from 'node:fs';
@@ -13,52 +14,27 @@ import { readFile } from 'node:fs/promises';
13
14
  import { readVersionFromPackage, readMetadata, getPlaywrightTracePath } from '@argos-ci/util';
14
15
  import { createRequire } from 'node:module';
15
16
 
16
- const getPrNumber$2 = ({ env })=>{
17
- return env.BITRISE_PULL_REQUEST ? Number(env.BITRISE_PULL_REQUEST) : null;
18
- };
19
- const service$7 = {
20
- name: "Bitrise",
21
- key: "bitrise",
22
- detect: ({ env })=>Boolean(env.BITRISE_IO),
23
- config: ({ env })=>{
24
- return {
25
- commit: env.BITRISE_GIT_COMMIT || null,
26
- branch: env.BITRISE_GIT_BRANCH || null,
27
- owner: env.BITRISEIO_GIT_REPOSITORY_OWNER || null,
28
- repository: env.BITRISEIO_GIT_REPOSITORY_SLUG || null,
29
- jobId: null,
30
- runId: null,
31
- runAttempt: null,
32
- prNumber: getPrNumber$2({
33
- env
34
- }),
35
- prHeadCommit: null,
36
- nonce: env.BITRISEIO_PIPELINE_ID || null
37
- };
38
- }
39
- };
40
-
41
17
  /**
42
18
  * Check if the current directory is a git repository.
43
- */ const checkIsGitRepository = ()=>{
19
+ */ function checkIsGitRepository() {
44
20
  try {
45
21
  return execSync("git rev-parse --is-inside-work-tree").toString().trim() === "true";
46
22
  } catch {
47
23
  return false;
48
24
  }
49
- };
25
+ }
50
26
  /**
51
27
  * Returns the head commit.
52
- */ const head = ()=>{
28
+ */ function head() {
53
29
  try {
54
30
  return execSync("git rev-parse HEAD").toString().trim();
55
31
  } catch {
56
32
  return null;
57
33
  }
58
- };
34
+ }
59
35
  /**
60
36
  * Returns the current branch.
61
- */ const branch = ()=>{
37
+ */ function branch() {
62
38
  try {
63
39
  const headRef = execSync("git rev-parse --abbrev-ref HEAD").toString().trim();
64
40
  if (headRef === "HEAD") {
@@ -68,6 +44,57 @@ const service$7 = {
68
44
  } catch {
69
45
  return null;
70
46
  }
47
+ }
48
+ function getMergeBaseCommitShaWithDepth(input) {
49
+ const head = input.head || `HEAD`;
50
+ try {
51
+ execSync(`git fetch origin ${head} --depth ${input.depth}`);
52
+ execSync(`git fetch origin ${input.base}:${input.base} --depth ${input.depth}`);
53
+ const mergeBase = execSync(`git merge-base ${head} ${input.base}`).toString().trim();
54
+ return mergeBase || null;
55
+ } catch {
56
+ return null;
57
+ }
58
+ }
59
+ function getMergeBaseCommitSha$1(input) {
60
+ let depth = 50;
61
+ while(depth < 1000){
62
+ const mergeBase = getMergeBaseCommitShaWithDepth({
63
+ ...input,
64
+ depth
65
+ });
66
+ if (mergeBase) {
67
+ return mergeBase;
68
+ }
69
+ depth += 50;
70
+ }
71
+ return null;
72
+ }
73
+
74
+ const getPrNumber$2 = ({ env })=>{
75
+ return env.BITRISE_PULL_REQUEST ? Number(env.BITRISE_PULL_REQUEST) : null;
76
+ };
77
+ const service$7 = {
78
+ name: "Bitrise",
79
+ key: "bitrise",
80
+ detect: ({ env })=>Boolean(env.BITRISE_IO),
81
+ config: ({ env })=>{
82
+ return {
83
+ commit: env.BITRISE_GIT_COMMIT || null,
84
+ branch: env.BITRISE_GIT_BRANCH || null,
85
+ owner: env.BITRISEIO_GIT_REPOSITORY_OWNER || null,
86
+ repository: env.BITRISEIO_GIT_REPOSITORY_SLUG || null,
87
+ jobId: null,
88
+ runId: null,
89
+ runAttempt: null,
90
+ prNumber: getPrNumber$2({
91
+ env
92
+ }),
93
+ prHeadCommit: null,
94
+ nonce: env.BITRISEIO_PIPELINE_ID || null
95
+ };
96
+ },
97
+ getMergeBaseCommitSha: getMergeBaseCommitSha$1
71
98
  };
72
99
 
73
100
  const service$6 = {
@@ -88,7 +115,8 @@ const service$6 = {
88
115
  prHeadCommit: null,
89
116
  nonce: env.BUILDKITE_BUILD_ID || null
90
117
  };
91
- }
118
+ },
119
+ getMergeBaseCommitSha: getMergeBaseCommitSha$1
92
120
  };
93
121
 
94
122
  const service$5 = {
@@ -106,7 +134,8 @@ const service$5 = {
106
134
  prNumber: null,
107
135
  prHeadCommit: null,
108
136
  nonce: env.HEROKU_TEST_RUN_ID || null
109
- })
137
+ }),
138
+ getMergeBaseCommitSha: getMergeBaseCommitSha$1
110
139
  };
111
140
 
112
141
  const KEY = "@argos-ci/core";
@@ -179,34 +208,37 @@ To disable this warning, add \`DISABLE_GITHUB_TOKEN_WARNING: true\` as environme
179
208
  return null;
180
209
  }
181
210
  }
182
- const getBranch = ({ env })=>{
211
+ function getBranch(context, eventPayload) {
212
+ if (eventPayload?.pull_request?.head.ref) {
213
+ return eventPayload.pull_request.head.ref;
214
+ }
215
+ const { env } = context;
183
216
  if (env.GITHUB_HEAD_REF) {
184
217
  return env.GITHUB_HEAD_REF;
185
218
  }
186
- const branchRegex = /refs\/heads\/(.*)/;
187
219
  if (!env.GITHUB_REF) {
188
220
  return null;
189
221
  }
222
+ const branchRegex = /refs\/heads\/(.*)/;
190
223
  const matches = branchRegex.exec(env.GITHUB_REF);
191
224
  return matches?.[1] ?? null;
192
- };
193
- const getRepository$1 = ({ env })=>{
225
+ }
226
+ function getRepository$1({ env }) {
194
227
  if (!env.GITHUB_REPOSITORY) return null;
195
228
  return env.GITHUB_REPOSITORY.split("/")[1] || null;
196
- };
197
- const readEventPayload = ({ env })=>{
229
+ }
230
+ function readEventPayload({ env }) {
198
231
  if (!env.GITHUB_EVENT_PATH) return null;
199
232
  if (!existsSync(env.GITHUB_EVENT_PATH)) return null;
200
233
  return JSON.parse(readFileSync(env.GITHUB_EVENT_PATH, "utf-8"));
201
- };
234
+ }
202
235
  const service$4 = {
203
236
  name: "GitHub Actions",
204
237
  key: "github-actions",
205
- detect: ({ env })=>Boolean(env.GITHUB_ACTIONS),
206
- config: async ({ env })=>{
207
- const payload = readEventPayload({
208
- env
209
- });
238
+ detect: (context)=>Boolean(context.env.GITHUB_ACTIONS),
239
+ config: async (context)=>{
240
+ const { env } = context;
241
+ const payload = readEventPayload(context);
210
242
  const sha = process.env.GITHUB_SHA || null;
211
243
  if (!sha) {
212
244
  throw new Error(`GITHUB_SHA is missing`);
@@ -214,9 +246,7 @@ const service$4 = {
214
246
  const commonConfig = {
215
247
  commit: sha,
216
248
  owner: env.GITHUB_REPOSITORY_OWNER || null,
217
- repository: getRepository$1({
218
- env
219
- }),
249
+ repository: getRepository$1(context),
220
250
  jobId: env.GITHUB_JOB || null,
221
251
  runId: env.GITHUB_RUN_ID || null,
222
252
  runAttempt: env.GITHUB_RUN_ATTEMPT ? Number(env.GITHUB_RUN_ATTEMPT) : null,
@@ -226,9 +256,7 @@ const service$4 = {
226
256
  if (payload?.deployment) {
227
257
  debug("Deployment event detected");
228
258
  // Try to find a relevant pull request for the sha
229
- const pullRequest = await getPullRequestFromHeadSha({
230
- env
231
- }, sha);
259
+ const pullRequest = await getPullRequestFromHeadSha(context, sha);
232
260
  return {
233
261
  ...commonConfig,
234
262
  // If no pull request is found, we fallback to the deployment environment as branch name
@@ -240,12 +268,20 @@ const service$4 = {
240
268
  }
241
269
  return {
242
270
  ...commonConfig,
243
- branch: payload?.pull_request?.head.ref || getBranch({
244
- env
245
- }) || null,
271
+ branch: payload?.pull_request?.head.ref || getBranch(context, payload) || null,
246
272
  prNumber: payload?.pull_request?.number || null,
247
273
  prHeadCommit: payload?.pull_request?.head.sha ?? null
248
274
  };
275
+ },
276
+ getMergeBaseCommitSha: (input, ctx)=>{
277
+ const payload = readEventPayload(ctx);
278
+ const branch = getBranch(ctx, payload);
279
+ // Unshallow the repository to get the merge base commit
280
+ execSync(`git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"`);
281
+ return getMergeBaseCommitSha$1({
282
+ base: input.base,
283
+ head: branch
284
+ });
249
285
  }
250
286
  };
251
287
 
@@ -276,7 +312,8 @@ const service$3 = {
276
312
  prHeadCommit: null,
277
313
  nonce: env.CIRCLE_WORKFLOW_ID || env.CIRCLE_BUILD_NUM || null
278
314
  };
279
- }
315
+ },
316
+ getMergeBaseCommitSha: getMergeBaseCommitSha$1
280
317
  };
281
318
 
282
319
  const getOwner = ({ env })=>{
@@ -309,7 +346,8 @@ const service$2 = {
309
346
  prHeadCommit: null,
310
347
  nonce: env.TRAVIS_BUILD_ID || null
311
348
  };
312
- }
349
+ },
350
+ getMergeBaseCommitSha: getMergeBaseCommitSha$1
313
351
  };
314
352
 
315
353
  const service$1 = {
@@ -329,7 +367,8 @@ const service$1 = {
329
367
  prHeadCommit: null,
330
368
  nonce: env.CI_PIPELINE_ID || null
331
369
  };
332
- }
370
+ },
371
+ getMergeBaseCommitSha: getMergeBaseCommitSha$1
333
372
  };
334
373
 
335
374
  const service = {
@@ -349,7 +388,8 @@ const service = {
349
388
  prHeadCommit: null,
350
389
  nonce: null
351
390
  };
352
- }
391
+ },
392
+ getMergeBaseCommitSha: getMergeBaseCommitSha$1
353
393
  };
354
394
 
355
395
  // List of services ordered by usage
@@ -364,18 +404,38 @@ const services = [
364
404
  service$7,
365
405
  service
366
406
  ];
367
- async function getCiEnvironment({ env = process.env } = {}) {
368
- const ctx = {
369
- env
407
+ /**
408
+ * Create the context for the CI service detection.
409
+ */ function createContext() {
410
+ return {
411
+ env: process.env
370
412
  };
371
- debug("Detecting CI environment", {
372
- env
373
- });
374
- const service = services.find((service)=>service.detect(ctx));
413
+ }
414
+ /**
415
+ * Get the CI service that is currently running.
416
+ */ function getCiService(context) {
417
+ return services.find((service)=>service.detect(context));
418
+ }
419
+ /**
420
+ * Get the merge base commit.
421
+ */ function getMergeBaseCommitSha(input) {
422
+ const context = createContext();
423
+ const service = getCiService(context);
424
+ if (!service) {
425
+ return null;
426
+ }
427
+ return service.getMergeBaseCommitSha(input, context);
428
+ }
429
+ /**
430
+ * Get the CI environment.
431
+ */ async function getCiEnvironment() {
432
+ const context = createContext();
433
+ debug("Detecting CI environment", context);
434
+ const service = getCiService(context);
375
435
  // Service matched
376
436
  if (service) {
377
437
  debug("Internal service matched", service.name);
378
- const variables = await service.config(ctx);
438
+ const variables = await service.config(context);
379
439
  const ciEnvironment = {
380
440
  name: service.name,
381
441
  key: service.key,
@@ -622,15 +682,17 @@ const hashFile = async (filepath)=>{
622
682
  };
623
683
 
624
684
  const base64Encode = (obj)=>Buffer.from(JSON.stringify(obj), "utf8").toString("base64");
625
- function getBearerToken({ token, ciProvider, owner, repository, jobId, runId, prNumber }) {
626
- if (token) return `Bearer ${token}`;
685
+ function getAuthToken({ token, ciProvider, owner, repository, jobId, runId, prNumber }) {
686
+ if (token) {
687
+ return token;
688
+ }
627
689
  switch(ciProvider){
628
690
  case "github-actions":
629
691
  {
630
692
  if (!owner || !repository || !jobId || !runId) {
631
693
  throw new Error(`Automatic GitHub Actions variables detection failed. Please add the 'ARGOS_TOKEN'`);
632
694
  }
633
- return `Bearer tokenless-github-${base64Encode({
695
+ return `tokenless-github-${base64Encode({
634
696
  owner,
635
697
  repository,
636
698
  jobId,
@@ -642,7 +704,7 @@ function getBearerToken({ token, ciProvider, owner, repository, jobId, runId, pr
642
704
  throw new Error("Missing Argos repository token 'ARGOS_TOKEN'");
643
705
  }
644
706
  }
645
- const createArgosApiClient = (options)=>{
707
+ const createArgosLegacyAPIClient = (options)=>{
646
708
  const axiosInstance = axios.create({
647
709
  baseURL: options.baseUrl,
648
710
  headers: {
@@ -771,9 +833,14 @@ async function uploadFilesToS3(files) {
771
833
  "**/*.{png,jpg,jpeg}"
772
834
  ];
773
835
  debug("Using config and files", config, files);
774
- const apiClient = createArgosApiClient({
836
+ const authToken = getAuthToken(config);
837
+ const apiClient = createClient({
838
+ baseUrl: config.apiBaseUrl,
839
+ authToken
840
+ });
841
+ const legacyApiClient = createArgosLegacyAPIClient({
775
842
  baseUrl: config.apiBaseUrl,
776
- bearerToken: getBearerToken(config)
843
+ bearerToken: `Bearer ${authToken}`
777
844
  });
778
845
  // Collect screenshots
779
846
  const foundScreenshots = await discoverScreenshots(files, {
@@ -810,6 +877,31 @@ async function uploadFilesToS3(files) {
810
877
  } : null
811
878
  };
812
879
  }));
880
+ debug("Fetch project");
881
+ const { data: project, error } = await apiClient.GET("/project");
882
+ if (error) {
883
+ throw new Error(error.error);
884
+ }
885
+ const { defaultBaseBranch, hasRemoteContentAccess } = project;
886
+ const referenceBranch = config.referenceBranch || defaultBaseBranch;
887
+ const referenceCommit = (()=>{
888
+ if (config.referenceCommit) {
889
+ debug("Found reference commit in config", config.referenceCommit);
890
+ return config.referenceCommit;
891
+ }
892
+ if (hasRemoteContentAccess) {
893
+ return null;
894
+ }
895
+ const sha = getMergeBaseCommitSha({
896
+ base: referenceBranch
897
+ });
898
+ if (sha) {
899
+ debug("Found reference commit from git", sha);
900
+ } else {
901
+ debug("No reference commit found in git");
902
+ }
903
+ return sha;
904
+ })();
813
905
  // Create build
814
906
  debug("Creating build");
815
907
  const [pwTraceKeys, screenshotKeys] = screenshots.reduce(([pwTraceKeys, screenshotKeys], screenshot)=>{
@@ -827,7 +919,7 @@ async function uploadFilesToS3(files) {
827
919
  [],
828
920
  []
829
921
  ]);
830
- const result = await apiClient.createBuild({
922
+ const result = await legacyApiClient.createBuild({
831
923
  commit: config.commit,
832
924
  branch: config.branch,
833
925
  name: config.buildName,
@@ -838,8 +930,8 @@ async function uploadFilesToS3(files) {
838
930
  pwTraceKeys,
839
931
  prNumber: config.prNumber,
840
932
  prHeadCommit: config.prHeadCommit,
841
- referenceBranch: config.referenceBranch,
842
- referenceCommit: config.referenceCommit,
933
+ referenceBranch,
934
+ referenceCommit,
843
935
  argosSdk,
844
936
  ciProvider: config.ciProvider,
845
937
  runId: config.runId,
@@ -873,7 +965,7 @@ async function uploadFilesToS3(files) {
873
965
  await uploadFilesToS3(uploadFiles);
874
966
  // Update build
875
967
  debug("Updating build");
876
- await apiClient.updateBuild({
968
+ await legacyApiClient.updateBuild({
877
969
  buildId: result.build.id,
878
970
  screenshots: screenshots.map((screenshot)=>({
879
971
  key: screenshot.hash,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@argos-ci/core",
3
3
  "description": "Visual testing solution to avoid visual regression. The core component of Argos SDK that handles build creation.",
4
- "version": "2.4.1",
4
+ "version": "2.4.2-alpha.6+6b6c15f",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
7
7
  "types": "./dist/index.d.ts",
@@ -40,24 +40,25 @@
40
40
  "access": "public"
41
41
  },
42
42
  "dependencies": {
43
- "@argos-ci/util": "2.1.0",
44
- "axios": "^1.6.8",
43
+ "@argos-ci/api-client": "0.1.1-alpha.34+6b6c15f",
44
+ "@argos-ci/util": "2.1.1-alpha.14+6b6c15f",
45
+ "axios": "^1.7.4",
45
46
  "convict": "^6.2.4",
46
- "debug": "^4.3.4",
47
+ "debug": "^4.3.6",
47
48
  "fast-glob": "^3.3.2",
48
- "sharp": "^0.33.3",
49
+ "sharp": "^0.33.5",
49
50
  "tmp": "^0.2.3"
50
51
  },
51
52
  "devDependencies": {
52
53
  "@types/convict": "^6.1.6",
53
54
  "@types/debug": "^4.1.12",
54
55
  "@types/tmp": "^0.2.6",
55
- "msw": "^2.2.13"
56
+ "msw": "^2.3.5"
56
57
  },
57
58
  "scripts": {
58
59
  "prebuild": "rm -rf dist",
59
60
  "build": "rollup -c",
60
61
  "e2e": "node ./e2e/upload.cjs && node ./e2e/upload.mjs"
61
62
  },
62
- "gitHead": "8fbd0bb85ba9df1e8ca39d46acfe9903264d0b51"
63
+ "gitHead": "6b6c15f62882eb38e36a59f80f5ad2aa6d7ee3ff"
63
64
  }