@capraconsulting/cals-cli 3.13.1 → 3.14.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.
Files changed (45) hide show
  1. package/lib/cals-cli.mjs +588 -2450
  2. package/lib/cals-cli.mjs.map +1 -1
  3. package/lib/cli/reporter.d.ts +5 -6
  4. package/lib/cli/util.d.ts +1 -6
  5. package/lib/config.d.ts +0 -2
  6. package/lib/definition/index.d.ts +1 -1
  7. package/lib/definition/types.d.ts +0 -52
  8. package/lib/github/index.d.ts +0 -2
  9. package/lib/github/service.d.ts +2 -67
  10. package/lib/github/types.d.ts +0 -63
  11. package/lib/github/util.d.ts +0 -1
  12. package/lib/index.d.ts +0 -9
  13. package/lib/index.es.js +8 -1323
  14. package/lib/index.es.js.map +1 -1
  15. package/lib/index.js +8 -1323
  16. package/lib/index.js.map +1 -1
  17. package/package.json +7 -19
  18. package/lib/cli/commands/definition/dump-setup.d.ts +0 -3
  19. package/lib/cli/commands/definition/util.d.ts +0 -6
  20. package/lib/cli/commands/definition/util.test.d.ts +0 -1
  21. package/lib/cli/commands/definition/validate.d.ts +0 -3
  22. package/lib/cli/commands/definition.d.ts +0 -3
  23. package/lib/cli/commands/delete-cache.d.ts +0 -3
  24. package/lib/cli/commands/getting-started.d.ts +0 -3
  25. package/lib/cli/commands/github/analyze-directory.d.ts +0 -3
  26. package/lib/cli/commands/github/configure.d.ts +0 -3
  27. package/lib/cli/commands/github/list-pull-requests-stats.d.ts +0 -3
  28. package/lib/cli/commands/github/list-webhooks.d.ts +0 -3
  29. package/lib/cli/commands/github/util.d.ts +0 -3
  30. package/lib/cli/commands/snyk/report.d.ts +0 -3
  31. package/lib/cli/commands/snyk/set-token.d.ts +0 -3
  32. package/lib/cli/commands/snyk/sync.d.ts +0 -3
  33. package/lib/cli/commands/snyk.d.ts +0 -3
  34. package/lib/github/changeset/changeset.d.ts +0 -21
  35. package/lib/github/changeset/execute.d.ts +0 -10
  36. package/lib/github/changeset/types.d.ts +0 -88
  37. package/lib/snyk/index.d.ts +0 -3
  38. package/lib/snyk/service.d.ts +0 -30
  39. package/lib/snyk/token.d.ts +0 -11
  40. package/lib/snyk/types.d.ts +0 -62
  41. package/lib/snyk/util.d.ts +0 -3
  42. package/lib/snyk/util.test.d.ts +0 -1
  43. package/lib/testing/executor.d.ts +0 -25
  44. package/lib/testing/index.d.ts +0 -2
  45. package/lib/testing/lib.d.ts +0 -63
package/lib/index.js CHANGED
@@ -1,162 +1,15 @@
1
1
  import fs from 'node:fs';
2
- import path from 'node:path';
3
- import * as process from 'node:process';
4
- import process__default from 'node:process';
5
- import readline from 'node:readline';
6
- import chalk from 'chalk';
7
- import 'node:util';
8
- import https from 'node:https';
9
- import os from 'node:os';
10
- import cachedir from 'cachedir';
11
2
  import AJV from 'ajv';
12
3
  import yaml from 'js-yaml';
13
4
  import { Buffer } from 'node:buffer';
14
5
  import { performance } from 'node:perf_hooks';
6
+ import * as process from 'node:process';
7
+ import process__default from 'node:process';
15
8
  import { Octokit } from '@octokit/rest';
16
- import fetch from 'node-fetch';
17
9
  import pLimit from 'p-limit';
18
10
  import keytar from 'keytar';
19
- import { strict } from 'node:assert';
20
- import { Transform } from 'node:stream';
21
- import { execa } from 'execa';
22
- import { read } from 'read';
23
11
 
24
- var version = "3.13.1";
25
-
26
- class CacheProvider {
27
- constructor(config) {
28
- this.config = config;
29
- }
30
- mustValidate = false;
31
- config;
32
- defaultCacheTime = 1800;
33
- /**
34
- * Retrieve cache if existent, ignoring the time.
35
- *
36
- * The caller is responsible for handling proper validation,
37
- */
38
- retrieveJson(cachekey) {
39
- const cachefile = path.join(this.config.cacheDir, `${cachekey}.json`);
40
- if (!fs.existsSync(cachefile)) {
41
- return undefined;
42
- }
43
- const data = fs.readFileSync(cachefile, "utf-8");
44
- return {
45
- cacheTime: fs.statSync(cachefile).mtime.getTime(),
46
- data: (data === "undefined" ? undefined : JSON.parse(data)),
47
- };
48
- }
49
- /**
50
- * Save data to cache.
51
- */
52
- storeJson(cachekey, data) {
53
- const cachefile = path.join(this.config.cacheDir, `${cachekey}.json`);
54
- if (!fs.existsSync(this.config.cacheDir)) {
55
- fs.mkdirSync(this.config.cacheDir, { recursive: true });
56
- }
57
- fs.writeFileSync(cachefile, data === undefined ? "undefined" : JSON.stringify(data));
58
- }
59
- async json(cachekey, block, cachetime = this.defaultCacheTime) {
60
- const cacheItem = this.mustValidate
61
- ? undefined
62
- : this.retrieveJson(cachekey);
63
- const expire = new Date(Date.now() - cachetime * 1000).getTime();
64
- if (cacheItem !== undefined && cacheItem.cacheTime > expire) {
65
- return cacheItem.data;
66
- }
67
- const result = await block();
68
- this.storeJson(cachekey, result);
69
- return result;
70
- }
71
- /**
72
- * Delete all cached data.
73
- */
74
- cleanup() {
75
- fs.rmSync(this.config.cacheDir, { recursive: true, force: true });
76
- }
77
- }
78
-
79
- const CLEAR_WHOLE_LINE = 0;
80
- function clearLine(stdout) {
81
- readline.clearLine(stdout, CLEAR_WHOLE_LINE);
82
- readline.cursorTo(stdout, 0);
83
- }
84
- class Reporter {
85
- constructor(opts = {}) {
86
- this.nonInteractive = !!opts.nonInteractive;
87
- this.isVerbose = !!opts.verbose;
88
- }
89
- stdout = process__default.stdout;
90
- stderr = process__default.stderr;
91
- nonInteractive;
92
- isVerbose;
93
- format = chalk;
94
- error(msg) {
95
- clearLine(this.stderr);
96
- this.stderr.write(`${this.format.red("error")} ${msg}\n`);
97
- }
98
- log(msg) {
99
- clearLine(this.stdout);
100
- this.stdout.write(`${msg}\n`);
101
- }
102
- warn(msg) {
103
- clearLine(this.stderr);
104
- this.stderr.write(`${this.format.yellow("warning")} ${msg}\n`);
105
- }
106
- info(msg) {
107
- clearLine(this.stdout);
108
- this.stdout.write(`${this.format.blue("info")} ${msg}\n`);
109
- }
110
- }
111
-
112
- class Config {
113
- cwd = path.resolve(process__default.cwd());
114
- configFile = path.join(os.homedir(), ".cals-config.json");
115
- cacheDir = cachedir("cals-cli");
116
- agent = new https.Agent({
117
- keepAlive: true,
118
- });
119
- configCached = undefined;
120
- get config() {
121
- const existingConfig = this.configCached;
122
- if (existingConfig !== undefined) {
123
- return existingConfig;
124
- }
125
- const config = this.readConfig();
126
- this.configCached = config;
127
- return config;
128
- }
129
- readConfig() {
130
- if (!fs.existsSync(this.configFile)) {
131
- return {};
132
- }
133
- try {
134
- return JSON.parse(fs.readFileSync(this.configFile, "utf-8"));
135
- }
136
- catch (e) {
137
- console.error("Failed", e);
138
- throw new Error("Failed to read config");
139
- }
140
- }
141
- getConfig(key) {
142
- return this.config[key];
143
- }
144
- requireConfig(key) {
145
- const result = this.config[key];
146
- if (result === undefined) {
147
- throw Error(`Configuration for ${key} missing. Add manually to ${this.configFile}`);
148
- }
149
- return result;
150
- }
151
- updateConfig(key, value) {
152
- const updatedConfig = {
153
- ...this.readConfig(),
154
- [key]: value, // undefined will remove
155
- };
156
- fs.writeFileSync(this.configFile, JSON.stringify(updatedConfig, null, " "));
157
- this.configCached = updatedConfig;
158
- }
159
- }
12
+ var version = "3.14.0";
160
13
 
161
14
  function uniq(array) {
162
15
  return Array.from(new Set(array));
@@ -164,53 +17,6 @@ function uniq(array) {
164
17
 
165
18
  var type = "object";
166
19
  var properties = {
167
- snyk: {
168
- type: "object",
169
- properties: {
170
- accountId: {
171
- type: "string"
172
- }
173
- },
174
- required: [
175
- "accountId"
176
- ]
177
- },
178
- github: {
179
- type: "object",
180
- properties: {
181
- users: {
182
- type: "array",
183
- items: {
184
- $ref: "#/definitions/User"
185
- }
186
- },
187
- teams: {
188
- type: "array",
189
- items: {
190
- type: "object",
191
- properties: {
192
- organization: {
193
- type: "string"
194
- },
195
- teams: {
196
- type: "array",
197
- items: {
198
- $ref: "#/definitions/Team"
199
- }
200
- }
201
- },
202
- required: [
203
- "organization",
204
- "teams"
205
- ]
206
- }
207
- }
208
- },
209
- required: [
210
- "teams",
211
- "users"
212
- ]
213
- },
214
20
  projects: {
215
21
  type: "array",
216
22
  items: {
@@ -219,105 +25,9 @@ var properties = {
219
25
  }
220
26
  };
221
27
  var required = [
222
- "github",
223
28
  "projects"
224
29
  ];
225
30
  var definitions = {
226
- User: {
227
- anyOf: [
228
- {
229
- $ref: "#/definitions/UserBot"
230
- },
231
- {
232
- $ref: "#/definitions/UserEmployee"
233
- },
234
- {
235
- $ref: "#/definitions/UserExternal"
236
- }
237
- ]
238
- },
239
- UserBot: {
240
- type: "object",
241
- properties: {
242
- type: {
243
- type: "string",
244
- "const": "bot"
245
- },
246
- login: {
247
- type: "string"
248
- },
249
- name: {
250
- type: "string"
251
- }
252
- },
253
- required: [
254
- "login",
255
- "name",
256
- "type"
257
- ]
258
- },
259
- UserEmployee: {
260
- type: "object",
261
- properties: {
262
- type: {
263
- type: "string",
264
- "const": "employee"
265
- },
266
- login: {
267
- type: "string"
268
- },
269
- capraUsername: {
270
- type: "string"
271
- },
272
- name: {
273
- type: "string"
274
- }
275
- },
276
- required: [
277
- "capraUsername",
278
- "login",
279
- "name",
280
- "type"
281
- ]
282
- },
283
- UserExternal: {
284
- type: "object",
285
- properties: {
286
- type: {
287
- type: "string",
288
- "const": "external"
289
- },
290
- login: {
291
- type: "string"
292
- },
293
- name: {
294
- type: "string"
295
- }
296
- },
297
- required: [
298
- "login",
299
- "name",
300
- "type"
301
- ]
302
- },
303
- Team: {
304
- type: "object",
305
- properties: {
306
- name: {
307
- type: "string"
308
- },
309
- members: {
310
- type: "array",
311
- items: {
312
- type: "string"
313
- }
314
- }
315
- },
316
- required: [
317
- "members",
318
- "name"
319
- ]
320
- },
321
31
  Project: {
322
32
  type: "object",
323
33
  properties: {
@@ -337,12 +47,6 @@ var definitions = {
337
47
  items: {
338
48
  $ref: "#/definitions/DefinitionRepo"
339
49
  }
340
- },
341
- teams: {
342
- type: "array",
343
- items: {
344
- $ref: "#/definitions/RepoTeam"
345
- }
346
50
  }
347
51
  },
348
52
  required: [
@@ -355,10 +59,6 @@ var definitions = {
355
59
  items: {
356
60
  type: "string"
357
61
  }
358
- },
359
- responsible: {
360
- description: "Some external-defined entity being responsible for the project.",
361
- type: "string"
362
62
  }
363
63
  },
364
64
  required: [
@@ -380,28 +80,6 @@ var definitions = {
380
80
  },
381
81
  archived: {
382
82
  type: "boolean"
383
- },
384
- issues: {
385
- type: "boolean"
386
- },
387
- wiki: {
388
- type: "boolean"
389
- },
390
- teams: {
391
- type: "array",
392
- items: {
393
- $ref: "#/definitions/RepoTeam"
394
- }
395
- },
396
- snyk: {
397
- type: "boolean"
398
- },
399
- "public": {
400
- type: "boolean"
401
- },
402
- responsible: {
403
- description: "Some external-defined entity being responsible for the repository.\n\nWill override the project-defined responsible.",
404
- type: "string"
405
83
  }
406
84
  },
407
85
  required: [
@@ -422,29 +100,6 @@ var definitions = {
422
100
  "name",
423
101
  "project"
424
102
  ]
425
- },
426
- RepoTeam: {
427
- type: "object",
428
- properties: {
429
- name: {
430
- type: "string"
431
- },
432
- permission: {
433
- $ref: "#/definitions/Permission"
434
- }
435
- },
436
- required: [
437
- "name",
438
- "permission"
439
- ]
440
- },
441
- Permission: {
442
- "enum": [
443
- "admin",
444
- "pull",
445
- "push"
446
- ],
447
- type: "string"
448
103
  }
449
104
  };
450
105
  var $schema = "http://json-schema.org/draft-07/schema#";
@@ -456,9 +111,6 @@ var schema = {
456
111
  $schema: $schema
457
112
  };
458
113
 
459
- function getTeamId(org, teamName) {
460
- return `${org}/${teamName}`;
461
- }
462
114
  function getRepoId(orgName, repoName) {
463
115
  return `${orgName}/${repoName}`;
464
116
  }
@@ -470,33 +122,6 @@ function checkAgainstSchema(value) {
470
122
  : { error: ajv.errorsText() ?? "Unknown error" };
471
123
  }
472
124
  function requireValidDefinition(definition) {
473
- // Verify no duplicates in users and extract known logins.
474
- const loginList = definition.github.users.reduce((acc, user) => {
475
- if (acc.includes(user.login)) {
476
- throw new Error(`Duplicate login: ${user.login}`);
477
- }
478
- return [...acc, user.login];
479
- }, []);
480
- // Verify no duplicates in teams and extract team names.
481
- const teamIdList = definition.github.teams.reduce((acc, orgTeams) => {
482
- return orgTeams.teams.reduce((acc1, team) => {
483
- const id = getTeamId(orgTeams.organization, team.name);
484
- if (acc1.includes(id)) {
485
- throw new Error(`Duplicate team: ${id}`);
486
- }
487
- return [...acc1, id];
488
- }, acc);
489
- }, []);
490
- // Verify team members exists as users.
491
- definition.github.teams
492
- .flatMap((it) => it.teams)
493
- .forEach((team) => {
494
- team.members.forEach((login) => {
495
- if (!loginList.includes(login)) {
496
- throw new Error(`Team member ${login} in team ${team.name} is not registered in user list`);
497
- }
498
- });
499
- });
500
125
  // Verify no duplicates in project names.
501
126
  definition.projects.reduce((acc, project) => {
502
127
  if (acc.includes(project.name)) {
@@ -504,25 +129,6 @@ function requireValidDefinition(definition) {
504
129
  }
505
130
  return [...acc, project.name];
506
131
  }, []);
507
- definition.projects.forEach((project) => {
508
- project.github.forEach((org) => {
509
- (org.teams || []).forEach((team) => {
510
- const id = getTeamId(org.organization, team.name);
511
- if (!teamIdList.includes(id)) {
512
- throw new Error(`Project team ${id} in project ${project.name} is not registered in team list`);
513
- }
514
- }) // Verify repo teams exists as teams.
515
- ;
516
- (org.repos || []).forEach((repo) => {
517
- (repo.teams || []).forEach((team) => {
518
- const id = getTeamId(org.organization, team.name);
519
- if (!teamIdList.includes(id)) {
520
- throw new Error(`Repo team ${id} for repo ${repo.name} in project ${project.name} is not registered in team list`);
521
- }
522
- });
523
- });
524
- });
525
- });
526
132
  // Verify no duplicates in repos.
527
133
  definition.projects
528
134
  .flatMap((project) => project.github.flatMap((org) => (org.repos || []).map((repo) => getRepoId(org.organization, repo.name))))
@@ -571,7 +177,7 @@ function getGitHubOrgs(definition) {
571
177
  return uniq(githubOrganizations);
572
178
  }
573
179
 
574
- var index$2 = /*#__PURE__*/Object.freeze({
180
+ var index$1 = /*#__PURE__*/Object.freeze({
575
181
  __proto__: null,
576
182
  DefinitionFile: DefinitionFile,
577
183
  getGitHubOrgs: getGitHubOrgs,
@@ -580,13 +186,6 @@ var index$2 = /*#__PURE__*/Object.freeze({
580
186
  parseDefinition: parseDefinition
581
187
  });
582
188
 
583
- function createReporter(argv) {
584
- return new Reporter({
585
- verbose: !!argv.verbose,
586
- nonInteractive: !!argv.nonInteractive,
587
- });
588
- }
589
-
590
189
  class GitHubTokenCliProvider {
591
190
  keyringService = "cals";
592
191
  keyringAccount = "github-token";
@@ -609,26 +208,12 @@ class GitHubTokenCliProvider {
609
208
  }
610
209
  }
611
210
 
612
- async function undefinedForNotFound(value) {
613
- try {
614
- return await value;
615
- }
616
- catch (e) {
617
- if (e.name === "HttpError" && e.status === 404) {
618
- return undefined;
619
- }
620
- throw e;
621
- }
622
- }
623
-
624
211
  class GitHubService {
625
- config;
626
212
  octokit;
627
213
  cache;
628
214
  tokenProvider;
629
215
  semaphore;
630
216
  constructor(props) {
631
- this.config = props.config;
632
217
  this.octokit = props.octokit;
633
218
  this.cache = props.cache;
634
219
  this.tokenProvider = props.tokenProvider;
@@ -636,7 +221,6 @@ class GitHubService {
636
221
  // can maximize concurrency all other places.
637
222
  this.semaphore = pLimit(6);
638
223
  this.octokit.hook.wrap("request", async (request, options) => {
639
- this._requestCount++;
640
224
  if (options.method !== "GET") {
641
225
  return this.semaphore(() => request(options));
642
226
  }
@@ -696,10 +280,6 @@ class GitHubService {
696
280
  return response;
697
281
  });
698
282
  }
699
- _requestCount = 0;
700
- get requestCount() {
701
- return this._requestCount;
702
- }
703
283
  async runGraphqlQuery(query) {
704
284
  const token = await this.tokenProvider.getToken();
705
285
  if (token === undefined) {
@@ -716,7 +296,6 @@ class GitHubService {
716
296
  method: "POST",
717
297
  headers,
718
298
  body: JSON.stringify({ query }),
719
- agent: this.config.agent,
720
299
  });
721
300
  requestDuration = performance.now() - requestStart;
722
301
  return result;
@@ -796,922 +375,28 @@ class GitHubService {
796
375
  return repos.sort((a, b) => a.name.localeCompare(b.name));
797
376
  });
798
377
  }
799
- async getOrgMembersList(org) {
800
- const options = this.octokit.orgs.listMembers.endpoint.merge({
801
- org,
802
- });
803
- return ((await undefinedForNotFound(this.octokit.paginate(options))) || []);
804
- }
805
- async getOrgMembersInvitedList(org) {
806
- const options = this.octokit.orgs.listPendingInvitations.endpoint.merge({
807
- org,
808
- });
809
- return ((await undefinedForNotFound(this.octokit.paginate(options))) || []);
810
- }
811
- async getOrgMembersListIncludingInvited(org) {
812
- return [
813
- ...(await this.getOrgMembersList(org)).map((it) => ({
814
- type: "member",
815
- login: it.login,
816
- data: it,
817
- })),
818
- ...(await this.getOrgMembersInvitedList(org)).map((it) => ({
819
- type: "invited",
820
- // TODO: Fix ?? case properly
821
- login: it.login ?? "invalid",
822
- data: it,
823
- })),
824
- ];
825
- }
826
- async getRepository(owner, repo) {
827
- return this.cache.json(`get-repository-${owner}-${repo}`, async () => {
828
- const response = await undefinedForNotFound(this.octokit.repos.get({
829
- owner,
830
- repo,
831
- }));
832
- return response === undefined ? undefined : response.data;
833
- });
834
- }
835
- async getRepositoryTeamsList(repo) {
836
- return this.cache.json(`repository-teams-list-${repo.id}`, async () => {
837
- const options = this.octokit.repos.listTeams.endpoint.merge({
838
- owner: repo.owner.login,
839
- repo: repo.name,
840
- });
841
- return ((await undefinedForNotFound(this.octokit.paginate(options))) || []);
842
- });
843
- }
844
- async getRepositoryHooks(owner, repo) {
845
- return this.cache.json(`repository-hooks-${owner}-${repo}`, async () => {
846
- const options = this.octokit.repos.listWebhooks.endpoint.merge({
847
- owner,
848
- repo,
849
- });
850
- return ((await undefinedForNotFound(this.octokit.paginate(options))) || []);
851
- });
852
- }
853
- async getOrg(org) {
854
- const orgResponse = await this.octokit.orgs.get({
855
- org,
856
- });
857
- return orgResponse.data;
858
- }
859
- async getTeamList(org) {
860
- return this.cache.json(`team-list-${org.login}`, async () => {
861
- const options = this.octokit.teams.list.endpoint.merge({
862
- org: org.login,
863
- });
864
- return (await this.octokit.paginate(options));
865
- });
866
- }
867
- async getTeamMemberList(org, team) {
868
- return this.cache.json(`team-member-list-${team.id}`, async () => {
869
- const options = this.octokit.teams.listMembersInOrg.endpoint.merge({
870
- org: org.login,
871
- team_slug: team.slug,
872
- });
873
- return (await this.octokit.paginate(options));
874
- });
875
- }
876
- async getTeamMemberInvitedList(org, team) {
877
- return this.cache.json(`team-member-invited-list-${team.id}`, async () => {
878
- const options = this.octokit.teams.listPendingInvitationsInOrg.endpoint.merge({
879
- org: org.login,
880
- team_slug: team.slug,
881
- });
882
- return (await this.octokit.paginate(options));
883
- });
884
- }
885
- async getTeamMemberListIncludingInvited(org, team) {
886
- return [
887
- ...(await this.getTeamMemberList(org, team)).map((it) => ({
888
- type: "member",
889
- login: it.login,
890
- data: it,
891
- })),
892
- ...(await this.getTeamMemberInvitedList(org, team)).map((it) => ({
893
- type: "invited",
894
- // TODO: Fix ?? case properly
895
- login: it.login ?? "invalid",
896
- data: it,
897
- })),
898
- ];
899
- }
900
- async getSearchedPullRequestList(owner) {
901
- // NOTE: Changes to this must by synced with SearchedPullRequestListQueryResult.
902
- const getQuery = (after) => `{
903
- search(
904
- query: "is:open is:pr user:${owner} owner:${owner} archived:false",
905
- type: ISSUE,
906
- first: 50${after === null
907
- ? ""
908
- : `,
909
- after: "${after}"`}
910
- ) {
911
- pageInfo {
912
- hasNextPage
913
- endCursor
914
- }
915
- edges {
916
- node {
917
- __typename
918
- ... on PullRequest {
919
- number
920
- baseRepository {
921
- name
922
- owner {
923
- login
924
- }
925
- defaultBranchRef {
926
- name
927
- }
928
- }
929
- author {
930
- login
931
- }
932
- title
933
- commits(first: 3) {
934
- nodes {
935
- commit {
936
- messageHeadline
937
- }
938
- }
939
- }
940
- createdAt
941
- updatedAt
942
- }
943
- }
944
- }
945
- }
946
- }`;
947
- const pulls = [];
948
- let after = null;
949
- while (true) {
950
- const query = getQuery(after);
951
- const res = await this.runGraphqlQuery(query);
952
- pulls.push(...res.search.edges.map((it) => it.node));
953
- if (!res.search.pageInfo.hasNextPage) {
954
- break;
955
- }
956
- after = res.search.pageInfo.endCursor;
957
- }
958
- return pulls.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
959
- }
960
- async getHasVulnerabilityAlertsEnabled(owner, repo) {
961
- try {
962
- const response = await this.octokit.repos.checkVulnerabilityAlerts({
963
- owner: owner,
964
- repo: repo,
965
- });
966
- if (response.status !== 204) {
967
- console.log(response);
968
- throw new Error("Unknown response - see previous log line");
969
- }
970
- return true;
971
- }
972
- catch (e) {
973
- if (e.status === 404) {
974
- return false;
975
- }
976
- throw e;
977
- }
978
- }
979
- async enableVulnerabilityAlerts(owner, repo) {
980
- await this.octokit.repos.enableVulnerabilityAlerts({
981
- owner: owner,
982
- repo: repo,
983
- });
984
- }
985
- /**
986
- * Get the vulnerability alerts for a repository.
987
- */
988
- async getVulnerabilityAlerts(owner, repo) {
989
- // NOTE: Changes to this must by synced with VulnerabilityAlertsQueryResult.
990
- const getQuery = (after) => `{
991
- repository(owner: "${owner}", name: "${repo}") {
992
- vulnerabilityAlerts(first: 100${after === null ? "" : `, after: "${after}"`}) {
993
- pageInfo {
994
- hasNextPage
995
- endCursor
996
- }
997
- edges {
998
- node {
999
- state
1000
- dismissReason
1001
- vulnerableManifestFilename
1002
- vulnerableManifestPath
1003
- vulnerableRequirements
1004
- securityAdvisory {
1005
- description
1006
- identifiers { type value }
1007
- references { url }
1008
- severity
1009
- }
1010
- securityVulnerability {
1011
- package { name ecosystem }
1012
- firstPatchedVersion { identifier }
1013
- vulnerableVersionRange
1014
- }
1015
- }
1016
- }
1017
- }
1018
- }
1019
- }`;
1020
- return this.cache.json(`vulnerability-alerts-${owner}-${repo}`, async () => {
1021
- const result = [];
1022
- let after = null;
1023
- while (true) {
1024
- const query = getQuery(after);
1025
- const res = await this.runGraphqlQuery(query);
1026
- result.push(...(res.repository?.vulnerabilityAlerts.edges?.map((it) => it.node) ?? []));
1027
- if (!res.repository?.vulnerabilityAlerts.pageInfo.hasNextPage) {
1028
- break;
1029
- }
1030
- after = res.repository?.vulnerabilityAlerts.pageInfo.endCursor;
1031
- }
1032
- return result;
1033
- });
1034
- }
1035
- /**
1036
- * Get the Renovate Dependency Dashboard issue.
1037
- */
1038
- async getRenovateDependencyDashboardIssue(owner, repo) {
1039
- // NOTE: Changes to this must by synced with RenovateDependencyDashboardIssueQueryResult.
1040
- const getQuery = (after) => `{
1041
- repository(owner: "${owner}", name: "${repo}") {
1042
- issues(
1043
- orderBy: {field: UPDATED_AT, direction: DESC},
1044
- filterBy: {createdBy: "renovate[bot]"},
1045
- states: [OPEN],
1046
- first: 100${after === null ? "" : `, after: "${after}"`}
1047
- ) {
1048
- pageInfo {
1049
- hasNextPage
1050
- endCursor
1051
- }
1052
- edges {
1053
- node {
1054
- number
1055
- state
1056
- title
1057
- body
1058
- userContentEdits(first: 5) {
1059
- nodes {
1060
- createdAt
1061
- editor {
1062
- login
1063
- }
1064
- }
1065
- }
1066
- }
1067
- }
1068
- }
1069
- }
1070
- }`;
1071
- const issues = await this.cache.json(`renovate-bot-issues-${owner}-${repo}`, async () => {
1072
- const result = [];
1073
- let after = null;
1074
- while (true) {
1075
- const query = getQuery(after);
1076
- const res = await this.runGraphqlQuery(query);
1077
- const nodes = res.repository?.issues.edges?.map((it) => it.node) ?? [];
1078
- result.push(...nodes
1079
- .filter((it) => it.title === "Dependency Dashboard")
1080
- .map((it) => ({
1081
- number: it.number,
1082
- body: it.body,
1083
- lastUpdatedByRenovate: it.userContentEdits?.nodes?.filter((it) => it.editor?.login === "renovate")?.[0]?.createdAt ?? null,
1084
- })));
1085
- if (!res.repository?.issues.pageInfo.hasNextPage) {
1086
- break;
1087
- }
1088
- after = res.repository?.issues.pageInfo.endCursor;
1089
- }
1090
- return result;
1091
- });
1092
- if (issues.length == 0) {
1093
- return undefined;
1094
- }
1095
- return issues[0];
1096
- }
1097
378
  }
1098
- async function createOctokit(config, tokenProvider) {
379
+ async function createOctokit(tokenProvider) {
1099
380
  return new Octokit({
1100
381
  auth: await tokenProvider.getToken(),
1101
- request: {
1102
- agent: config.agent,
1103
- },
1104
382
  });
1105
383
  }
1106
384
  async function createGitHubService(props) {
1107
385
  const tokenProvider = props.tokenProvider ?? new GitHubTokenCliProvider();
1108
386
  return new GitHubService({
1109
- config: props.config,
1110
- octokit: await createOctokit(props.config, tokenProvider),
387
+ octokit: await createOctokit(tokenProvider),
1111
388
  cache: props.cache,
1112
389
  tokenProvider,
1113
390
  });
1114
391
  }
1115
392
 
1116
- var index$1 = /*#__PURE__*/Object.freeze({
393
+ var index = /*#__PURE__*/Object.freeze({
1117
394
  __proto__: null,
1118
395
  GitHubService: GitHubService,
1119
396
  createGitHubService: createGitHubService
1120
397
  });
1121
398
 
1122
- class SnykTokenCliProvider {
1123
- keyringService = "cals";
1124
- keyringAccount = "snyk-token";
1125
- async getToken() {
1126
- if (process__default.env.CALS_SNYK_TOKEN) {
1127
- return process__default.env.CALS_SNYK_TOKEN;
1128
- }
1129
- const result = await keytar.getPassword(this.keyringService, this.keyringAccount);
1130
- if (result == null) {
1131
- process__default.stderr.write("No token found. Register using `cals snyk set-token`\n");
1132
- return undefined;
1133
- }
1134
- return result;
1135
- }
1136
- async markInvalid() {
1137
- await keytar.deletePassword(this.keyringService, this.keyringAccount);
1138
- }
1139
- async setToken(value) {
1140
- await keytar.setPassword(this.keyringService, this.keyringAccount, value);
1141
- }
1142
- }
1143
-
1144
- class SnykService {
1145
- config;
1146
- tokenProvider;
1147
- constructor(props) {
1148
- this.config = props.config;
1149
- this.tokenProvider = props.tokenProvider;
1150
- }
1151
- async getProjects(definition) {
1152
- const snykAccountId = definition.snyk?.accountId;
1153
- if (snykAccountId === undefined) {
1154
- return [];
1155
- }
1156
- return this.getProjectsByAccountId(snykAccountId);
1157
- }
1158
- async getProjectsByAccountId(snykAccountId,
1159
- /**
1160
- * The slug name of a Snyk organization.
1161
- *
1162
- * NOTE: This is only used to construct the browsable URL for a given project, and is not being used
1163
- * in API calls to Snyk.
1164
- *
1165
- * @default - the slug corresponding to Lifligs Snyk organization ("it").
1166
- */
1167
- snykOrgSlugId) {
1168
- const token = await this.tokenProvider.getToken();
1169
- if (token === undefined) {
1170
- throw new Error("Missing token for Snyk");
1171
- }
1172
- let backportedProjects = [];
1173
- const snykRestApiVersion = "2025-11-05";
1174
- let nextUrl = `/rest/orgs/${encodeURIComponent(snykAccountId)}/projects?version=${snykRestApiVersion}&meta.latest_dependency_total=true&meta.latest_issue_counts=true&limit=100`;
1175
- /* The Snyk REST API only allows us to retrieve 100 projects at a time.
1176
- * The "links.next" value in the response gives us a pointer to the next 100 results.
1177
- * We continue calling the Snyk API and retrieving more projects until links.next is null
1178
- * */
1179
- while (nextUrl) {
1180
- const response = await fetch(`https://api.snyk.io${nextUrl}`, {
1181
- method: "GET",
1182
- headers: {
1183
- Accept: "application/json",
1184
- Authorization: `token ${token}`,
1185
- },
1186
- agent: this.config.agent,
1187
- });
1188
- if (response.status === 401) {
1189
- process__default.stderr.write("Unauthorized - removing token\n");
1190
- await this.tokenProvider.markInvalid();
1191
- }
1192
- if (!response.ok) {
1193
- throw new Error(`Response from Snyk not OK (${response.status}): ${JSON.stringify(response)}`);
1194
- }
1195
- // Check if the Sunset header is present in the response
1196
- const sunsetHeader = response.headers.get("Sunset") || response.headers.get("sunset");
1197
- if (sunsetHeader) {
1198
- console.warn(`Snyk endpoint with version ${snykRestApiVersion} has been marked as deprecated with deprecation date ${sunsetHeader}`);
1199
- }
1200
- const jsonResponse = (await response.json());
1201
- /* We transform the data to a standard format that we used for data from Snyk API v1 in order for
1202
- the data to be backover compatible with existing consuments */
1203
- backportedProjects = [
1204
- ...backportedProjects,
1205
- ...jsonResponse.data.map((project) => {
1206
- return {
1207
- id: project.id,
1208
- name: project.attributes.name,
1209
- type: project.attributes.type,
1210
- created: project.attributes.created,
1211
- origin: project.attributes.origin,
1212
- testFrequency: project.attributes.settings.recurring_tests.frequency,
1213
- isMonitored: project.attributes.status === "active",
1214
- totalDependencies: project.meta.latest_dependency_total.total,
1215
- issueCountsBySeverity: project.meta.latest_issue_counts,
1216
- lastTestedDate: project.meta.latest_dependency_total.updated_at,
1217
- browseUrl: `https://app.snyk.io/org/${snykOrgSlugId ?? "it"}/project/${project.id}`,
1218
- };
1219
- }),
1220
- ];
1221
- /* Update nextUrl with pointer to the next page of results based
1222
- * on the "links.next" field in the JSON response */
1223
- nextUrl = jsonResponse.links.next;
1224
- }
1225
- return backportedProjects;
1226
- }
1227
- }
1228
- function createSnykService(props) {
1229
- return new SnykService({
1230
- config: props.config,
1231
- tokenProvider: props.tokenProvider ?? new SnykTokenCliProvider(),
1232
- });
1233
- }
1234
-
1235
- function getGitHubRepo(snykProject) {
1236
- if (snykProject.origin === "github") {
1237
- const match = /^([^/]+)\/([^:]+)(:(.+))?$/.exec(snykProject.name);
1238
- if (match === null) {
1239
- throw Error(`Could not extract components from Snyk project name: ${snykProject.name} (id: ${snykProject.id})`);
1240
- }
1241
- return {
1242
- owner: match[1],
1243
- name: match[2],
1244
- };
1245
- }
1246
- if (snykProject.origin === "cli" && snykProject.remoteRepoUrl != null) {
1247
- // The remoteRepoUrl can be overridden when using the CLI, so don't
1248
- // fail if we cannot extract the value.
1249
- const match = /github.com\/([^/]+)\/(.+)\.git$/.exec(snykProject.remoteRepoUrl);
1250
- if (match === null) {
1251
- return undefined;
1252
- }
1253
- return {
1254
- owner: match[1],
1255
- name: match[2],
1256
- };
1257
- }
1258
- return undefined;
1259
- }
1260
- function getGitHubRepoId(repo) {
1261
- return repo ? `${repo.owner}/${repo.name}` : undefined;
1262
- }
1263
-
1264
- var index = /*#__PURE__*/Object.freeze({
1265
- __proto__: null,
1266
- SnykService: SnykService,
1267
- createSnykService: createSnykService,
1268
- getGitHubRepo: getGitHubRepo,
1269
- getGitHubRepoId: getGitHubRepoId
1270
- });
1271
-
1272
- class TestExecutor {
1273
- shutdown = false;
1274
- cleanupTask = null;
1275
- usingWithCleanupTasks = false;
1276
- tasks = [];
1277
- /**
1278
- * Check if we are currently in shutdown state due to user
1279
- * asking to abort (Ctrl+C).
1280
- */
1281
- checkCanContinue() {
1282
- if (this.shutdown) {
1283
- throw new Error("In shutdown mode - aborting");
1284
- }
1285
- }
1286
- async runTasks() {
1287
- console.warn("Running cleanup tasks");
1288
- while (true) {
1289
- // We must run tasks in reverse order due to dependencies.
1290
- // E.g. we cannot delete a Docker network before deleting
1291
- // the container using it.
1292
- const task = this.tasks.pop();
1293
- if (task === undefined) {
1294
- return;
1295
- }
1296
- try {
1297
- await task();
1298
- }
1299
- catch (error) {
1300
- console.error(error);
1301
- }
1302
- }
1303
- }
1304
- /**
1305
- * Register a task that will be run during cleanup phase.
1306
- */
1307
- registerCleanupTask(task) {
1308
- if (!this.usingWithCleanupTasks) {
1309
- throw new Error("registerCleanupTask run outside runWithCleanupTasks");
1310
- }
1311
- this.tasks.push(task);
1312
- this.checkCanContinue();
1313
- }
1314
- /**
1315
- * Run the code block while ensuring we can run cleanup tasks
1316
- * after the execution or if the process is interrupted.
1317
- *
1318
- * The main method of the program should be executed by using
1319
- * this method.
1320
- */
1321
- async runWithCleanupTasks(body) {
1322
- try {
1323
- strict.strictEqual(this.usingWithCleanupTasks, false);
1324
- this.usingWithCleanupTasks = true;
1325
- // We capture Ctrl+C so that we can perform cleanup task,
1326
- // since the cleanup tasks involve async code which is not
1327
- // supported during NodeJS normal exit handling.
1328
- //
1329
- // This will not abort the running tasks until after
1330
- // we have completed the cleanup tasks. The running tasks
1331
- // can stop earlier by calling checkCanContinue.
1332
- process__default.on("SIGINT", () => {
1333
- console.warn("Caught interrupt signal - forcing termination");
1334
- if (this.cleanupTask != null) {
1335
- return;
1336
- }
1337
- this.shutdown = true;
1338
- this.cleanupTask = this.runTasks().then(() => {
1339
- process__default.exit(1);
1340
- });
1341
- });
1342
- await body(this);
1343
- }
1344
- catch (error) {
1345
- console.error(error.stack || error.message || error);
1346
- process__default.exitCode = 1;
1347
- }
1348
- finally {
1349
- console.log("Reached finally block");
1350
- this.usingWithCleanupTasks = false;
1351
- if (this.cleanupTask == null) {
1352
- this.cleanupTask = this.runTasks();
1353
- }
1354
- await this.cleanupTask;
1355
- }
1356
- }
1357
- }
1358
- function createTestExecutor() {
1359
- return new TestExecutor();
1360
- }
1361
-
1362
- /**
1363
- * Generate a value that can be used as part of resource names.
1364
- *
1365
- * Gives a value formatted as "yyyymmdd-xxxxxx", e.g. "20200523-3f2c87".
1366
- */
1367
- function generateRunId() {
1368
- const low = 0x100000;
1369
- const high = 0xffffff;
1370
- const range = high - low + 1;
1371
- const now = new Date();
1372
- return [
1373
- now.getUTCFullYear(),
1374
- (now.getUTCMonth() + 1).toString().padStart(2, "0"),
1375
- now.getUTCDate().toString().padStart(2, "0"),
1376
- "-",
1377
- (Math.floor(Math.random() * range) + low).toString(16),
1378
- ].join("");
1379
- }
1380
- /**
1381
- * Generate a name that can be used for a resource.
1382
- */
1383
- function generateName(extra) {
1384
- const s = extra === undefined ? "" : `-${extra}`;
1385
- return `autotest-${generateRunId()}${s}`;
1386
- }
1387
- /**
1388
- * Create a new Docker network.
1389
- */
1390
- async function createNetwork(executor) {
1391
- executor.checkCanContinue();
1392
- const networkName = generateName();
1393
- await execa("docker", ["network", "create", networkName]);
1394
- const lsRes = await execa("docker", [
1395
- "network",
1396
- "ls",
1397
- "-q",
1398
- "-f",
1399
- `name=${networkName}`,
1400
- ]);
1401
- const networkId = lsRes.stdout.trim();
1402
- console.log(`Network ${networkName} (${networkId}) created`);
1403
- executor.registerCleanupTask(async () => {
1404
- await execa("docker", ["network", "rm", networkId]);
1405
- console.log(`Network ${networkName} (${networkId}) deleted`);
1406
- });
1407
- return {
1408
- id: networkId,
1409
- };
1410
- }
1411
- /**
1412
- * Execute curl within the Docker network.
1413
- */
1414
- async function curl(executor, network, ...args) {
1415
- executor.checkCanContinue();
1416
- const result = await execa("docker", [
1417
- "run",
1418
- "-i",
1419
- "--rm",
1420
- "--network",
1421
- network.id,
1422
- "byrnedo/alpine-curl",
1423
- ...args,
1424
- ]);
1425
- return result.stdout;
1426
- }
1427
- /**
1428
- * Repeatedly check for a condition until timeout.
1429
- *
1430
- * The condition can throw an error without aborting the loop.
1431
- * To abort the condition must return false.
1432
- */
1433
- async function pollForCondition({ container, attempts, waitIntervalSec, condition, }) {
1434
- function log(value) {
1435
- console.log(`${container.name} (poll): ${value}`);
1436
- }
1437
- container.executor.checkCanContinue();
1438
- log(`Waiting for condition.. Checking ${attempts} times by ${waitIntervalSec} sec`);
1439
- const start = performance.now();
1440
- const duration = () => {
1441
- const end = performance.now();
1442
- return Math.round((end - start) / 1000);
1443
- };
1444
- for (let i = 0; i < attempts; i++) {
1445
- container.executor.checkCanContinue();
1446
- if (!(await isRunning(container.executor, container))) {
1447
- throw new Error(`Container ${container.name} not running as expected`);
1448
- }
1449
- try {
1450
- const result = await condition();
1451
- if (!result) {
1452
- break;
1453
- }
1454
- log(`Took ${duration()} seconds for condition`);
1455
- return;
1456
- }
1457
- catch {
1458
- log("Still waiting...");
1459
- await new Promise((resolve) => setTimeout(resolve, waitIntervalSec * 1000));
1460
- }
1461
- }
1462
- throw new Error(`Failed to wait for container ${container.name}`);
1463
- }
1464
- async function waitForHttpOk({ container, url, attempts = 30, waitIntervalSec = 1, }) {
1465
- await pollForCondition({
1466
- container,
1467
- attempts,
1468
- waitIntervalSec,
1469
- condition: async () => {
1470
- await curl(container.executor, container.network, "-fsS", url);
1471
- return true;
1472
- },
1473
- });
1474
- }
1475
- async function waitForPostgresAvailable({ container, attempts = 30, waitIntervalSec = 1, username = "user", password = "password", dbname, }) {
1476
- await pollForCondition({
1477
- container,
1478
- attempts,
1479
- waitIntervalSec,
1480
- condition: async () => {
1481
- await execa("docker", [
1482
- "exec",
1483
- "-e",
1484
- `PGPASSWORD=${password}`,
1485
- container.name,
1486
- "psql",
1487
- "-h",
1488
- "localhost",
1489
- "-U",
1490
- username,
1491
- "-c",
1492
- "select 1",
1493
- dbname,
1494
- ]);
1495
- return true;
1496
- },
1497
- });
1498
- }
1499
- async function isRunning(executor, container) {
1500
- executor.checkCanContinue();
1501
- try {
1502
- await execa("docker", ["inspect", container.name]);
1503
- return true;
1504
- }
1505
- catch {
1506
- return false;
1507
- }
1508
- }
1509
- /**
1510
- * A stream transform that injects a prefix into every line
1511
- * and also forces every chunk to end with a newline so that
1512
- * it can be interleaved with other output.
1513
- */
1514
- class OutputPrefixTransform extends Transform {
1515
- constructor(prefix) {
1516
- super({
1517
- objectMode: true,
1518
- transform: (chunk, encoding, callback) => {
1519
- let result = chunk.toString(encoding);
1520
- if (result.endsWith("\n")) {
1521
- result = result.slice(0, -1);
1522
- }
1523
- // Some loggers emit newline then ANSI reset code causing
1524
- // blank lines if we do not remove the newline.
1525
- // TODO: Consider removing all ANSI escape codes as it causes
1526
- // some confusing output when interleaved.
1527
- if (result.endsWith("\n\u001B[0m")) {
1528
- result = result.slice(0, -5) + result.slice(-4);
1529
- }
1530
- result = `${prefix + result.replace(/\n/g, `\n${prefix}`)}\n`;
1531
- callback(null, result);
1532
- },
1533
- });
1534
- }
1535
- }
1536
- function pipeToConsole(result, name) {
1537
- result.stdout
1538
- ?.pipe(new OutputPrefixTransform(`${name}: `))
1539
- .pipe(process__default.stdout);
1540
- result.stderr
1541
- ?.pipe(new OutputPrefixTransform(`${name} (stderr): `))
1542
- .pipe(process__default.stderr);
1543
- }
1544
- function checkPidRunning(pid) {
1545
- try {
1546
- process__default.kill(pid, 0);
1547
- return true;
1548
- }
1549
- catch {
1550
- return false;
1551
- }
1552
- }
1553
- async function getContainerId({ executor, name, hasFailed, pid, }) {
1554
- function log(value) {
1555
- console.log(`${name} (get-container-id): ${value}`);
1556
- }
1557
- async function check() {
1558
- let result;
1559
- try {
1560
- result = (await execa("docker", ["inspect", name, "-f", "{{.Id}}"]))
1561
- .stdout;
1562
- }
1563
- catch {
1564
- result = null;
1565
- }
1566
- // Debugging to help us solve CALS-366.
1567
- const ps = execa("docker", ["ps"]);
1568
- pipeToConsole(ps, `${name} (ps)`);
1569
- await ps;
1570
- // Debugging to help us solve CALS-366.
1571
- if (!checkPidRunning(pid)) {
1572
- log("Process not running");
1573
- }
1574
- return result;
1575
- }
1576
- // If the container is not running, retry a few times to cover
1577
- // the initial starting where we might check before the container
1578
- // is running.
1579
- // Increased from 25 to 100 to see if it helps for solving CALS-366.
1580
- for (let i = 0; i < 100; i++) {
1581
- if (i > 0) {
1582
- // Delay a bit before checking again.
1583
- log("Retrying in a bit...");
1584
- await new Promise((resolve) => setTimeout(resolve, 200));
1585
- }
1586
- executor.checkCanContinue();
1587
- if (hasFailed()) {
1588
- break;
1589
- }
1590
- const id = await check();
1591
- if (id !== null) {
1592
- log(`Resolved to ${id}`);
1593
- return id;
1594
- }
1595
- }
1596
- throw new Error(`Could not find ID for container with name ${name}`);
1597
- }
1598
- async function pullImage({ imageId }) {
1599
- console.log(`Pulling ${imageId}`);
1600
- const process = execa("docker", ["pull", imageId]);
1601
- pipeToConsole(process, `pull-image (${imageId})`);
1602
- await process;
1603
- }
1604
- async function checkImageExistsLocally({ imageId, }) {
1605
- const result = await execa("docker", ["images", "-q", imageId]);
1606
- const found = result.stdout != "";
1607
- console.log(`image ${imageId} ${found ? "was present locally" : "was not found locally"}`);
1608
- return found;
1609
- }
1610
- async function startContainer({ executor, network, imageId, alias, env, dockerArgs = [], pull = false, }) {
1611
- executor.checkCanContinue();
1612
- const containerName = generateName(alias);
1613
- // Prefer pulling image here so that the call on getContainerId
1614
- // will not time out due to pulling the image.
1615
- // If pull is false, we will still fallback to pulling if we cannot
1616
- // find the image locally.
1617
- if (pull || !(await checkImageExistsLocally({ imageId }))) {
1618
- await pullImage({
1619
- imageId,
1620
- });
1621
- }
1622
- const args = [
1623
- "run",
1624
- "--rm",
1625
- "--network",
1626
- network.id,
1627
- "--name",
1628
- containerName,
1629
- ...dockerArgs,
1630
- ];
1631
- if (alias != null) {
1632
- args.push(`--network-alias=${alias}`);
1633
- }
1634
- if (env != null) {
1635
- for (const [key, value] of Object.entries(env)) {
1636
- args.push("-e", `${key}=${value}`);
1637
- }
1638
- }
1639
- args.push(imageId);
1640
- console.log(`Starting ${imageId}`);
1641
- const process = execa("docker", args);
1642
- pipeToConsole(process, alias ?? containerName);
1643
- let failed = false;
1644
- process.catch(() => {
1645
- failed = true;
1646
- });
1647
- if (!process.pid) {
1648
- throw new Error("No process identifier (PID) was returned for the process that was started when running trying to run Docker container");
1649
- }
1650
- const id = await getContainerId({
1651
- executor,
1652
- name: containerName,
1653
- hasFailed: () => failed,
1654
- pid: process.pid,
1655
- });
1656
- executor.registerCleanupTask(async () => {
1657
- console.log(`Stopping container ${containerName}`);
1658
- const r = execa("docker", ["stop", containerName]);
1659
- pipeToConsole(r, `${alias ?? containerName} (stop)`);
1660
- try {
1661
- await r;
1662
- }
1663
- catch (e) {
1664
- if (!(e.stderr || "").includes("No such container")) {
1665
- throw e;
1666
- }
1667
- }
1668
- });
1669
- return {
1670
- id,
1671
- name: containerName,
1672
- network,
1673
- process,
1674
- executor,
1675
- };
1676
- }
1677
- async function runNpmRunScript(name, options) {
1678
- const result = execa("npm", ["run", name], {
1679
- env: options?.env,
1680
- });
1681
- pipeToConsole(result, `npm run ${name}`);
1682
- await result;
1683
- }
1684
- /**
1685
- * This likely does not cover all situations.
1686
- */
1687
- async function getDockerHostAddress() {
1688
- if (process__default.platform === "darwin" || process__default.platform === "win32") {
1689
- return "host.docker.internal";
1690
- }
1691
- if (fs.existsSync("/.dockerenv")) {
1692
- const process = execa("ip", ["route"]);
1693
- pipeToConsole(process, "ip route");
1694
- const res = await process;
1695
- try {
1696
- return res.stdout
1697
- .split("\n")
1698
- .filter((it) => it.includes("default via"))
1699
- .map((it) => /default via ([\d.]+) /.exec(it)[1])[0];
1700
- }
1701
- catch {
1702
- throw new Error("Failed to extract docker host address");
1703
- }
1704
- }
1705
- return "localhost";
1706
- }
1707
- async function waitForEnterToContinue(prompt = "Press enter to continue") {
1708
- await read({
1709
- prompt,
1710
- silent: true,
1711
- });
1712
- }
1713
-
1714
399
  const VERSION = version;
1715
400
 
1716
- export { CacheProvider, Config, DefinitionFile, GitHubService, Reporter, TestExecutor, VERSION, createGitHubService, createNetwork, createReporter, createTestExecutor, curl, index$2 as definition, getDockerHostAddress, index$1 as github, pollForCondition, runNpmRunScript, index as snyk, startContainer, waitForEnterToContinue, waitForHttpOk, waitForPostgresAvailable };
401
+ export { VERSION, index$1 as definition, index as github };
1717
402
  //# sourceMappingURL=index.js.map