@capraconsulting/cals-cli 3.6.0 → 3.7.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.
- package/lib/{cals-cli.js → cals-cli.mjs} +226 -304
- package/lib/{cals-cli.js.map → cals-cli.mjs.map} +1 -1
- package/lib/definition/index.d.ts +1 -1
- package/lib/github/index.d.ts +3 -2
- package/lib/index.es.js +79 -86
- package/lib/index.es.js.map +1 -1
- package/lib/index.js +153 -223
- package/lib/index.js.map +1 -1
- package/lib/snyk/index.d.ts +1 -1
- package/lib/sonarcloud/index.d.ts +2 -1
- package/package.json +16 -12
package/lib/index.js
CHANGED
|
@@ -1,88 +1,48 @@
|
|
|
1
|
-
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import rimraf from 'rimraf';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import readline from 'readline';
|
|
6
|
+
import 'util';
|
|
7
|
+
import cachedir from 'cachedir';
|
|
8
|
+
import https from 'https';
|
|
9
|
+
import os from 'os';
|
|
10
|
+
import AJV from 'ajv';
|
|
11
|
+
import yaml from 'js-yaml';
|
|
12
|
+
import { uniq } from 'lodash-es';
|
|
13
|
+
import { Octokit } from '@octokit/rest';
|
|
14
|
+
import fetch from 'node-fetch';
|
|
15
|
+
import pLimit from 'p-limit';
|
|
16
|
+
import keytar from 'keytar';
|
|
17
|
+
import * as process$1 from 'process';
|
|
18
|
+
import { performance } from 'perf_hooks';
|
|
19
|
+
import { strict } from 'assert';
|
|
20
|
+
import execa from 'execa';
|
|
21
|
+
import read from 'read';
|
|
22
|
+
import { Transform } from 'stream';
|
|
2
23
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
var fs = require('fs');
|
|
6
|
-
var path = require('path');
|
|
7
|
-
var rimraf = require('rimraf');
|
|
8
|
-
var chalk = require('chalk');
|
|
9
|
-
var readline = require('readline');
|
|
10
|
-
require('util');
|
|
11
|
-
var cachedir = require('cachedir');
|
|
12
|
-
var https = require('https');
|
|
13
|
-
var os = require('os');
|
|
14
|
-
var AJV = require('ajv');
|
|
15
|
-
var yaml = require('js-yaml');
|
|
16
|
-
var lodash = require('lodash');
|
|
17
|
-
var rest = require('@octokit/rest');
|
|
18
|
-
var fetch = require('node-fetch');
|
|
19
|
-
var pLimit = require('p-limit');
|
|
20
|
-
var keytar = require('keytar');
|
|
21
|
-
var process$1 = require('process');
|
|
22
|
-
var perf_hooks = require('perf_hooks');
|
|
23
|
-
var assert = require('assert');
|
|
24
|
-
var execa = require('execa');
|
|
25
|
-
var read = require('read');
|
|
26
|
-
var stream = require('stream');
|
|
27
|
-
|
|
28
|
-
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
29
|
-
|
|
30
|
-
function _interopNamespace(e) {
|
|
31
|
-
if (e && e.__esModule) return e;
|
|
32
|
-
var n = Object.create(null);
|
|
33
|
-
if (e) {
|
|
34
|
-
Object.keys(e).forEach(function (k) {
|
|
35
|
-
if (k !== 'default') {
|
|
36
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
37
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
38
|
-
enumerable: true,
|
|
39
|
-
get: function () { return e[k]; }
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
n["default"] = e;
|
|
45
|
-
return Object.freeze(n);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
|
|
49
|
-
var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
|
|
50
|
-
var rimraf__default = /*#__PURE__*/_interopDefaultLegacy(rimraf);
|
|
51
|
-
var chalk__default = /*#__PURE__*/_interopDefaultLegacy(chalk);
|
|
52
|
-
var readline__default = /*#__PURE__*/_interopDefaultLegacy(readline);
|
|
53
|
-
var cachedir__default = /*#__PURE__*/_interopDefaultLegacy(cachedir);
|
|
54
|
-
var https__default = /*#__PURE__*/_interopDefaultLegacy(https);
|
|
55
|
-
var os__default = /*#__PURE__*/_interopDefaultLegacy(os);
|
|
56
|
-
var AJV__default = /*#__PURE__*/_interopDefaultLegacy(AJV);
|
|
57
|
-
var yaml__default = /*#__PURE__*/_interopDefaultLegacy(yaml);
|
|
58
|
-
var fetch__default = /*#__PURE__*/_interopDefaultLegacy(fetch);
|
|
59
|
-
var pLimit__default = /*#__PURE__*/_interopDefaultLegacy(pLimit);
|
|
60
|
-
var keytar__default = /*#__PURE__*/_interopDefaultLegacy(keytar);
|
|
61
|
-
var process__namespace = /*#__PURE__*/_interopNamespace(process$1);
|
|
62
|
-
var execa__default = /*#__PURE__*/_interopDefaultLegacy(execa);
|
|
63
|
-
var read__default = /*#__PURE__*/_interopDefaultLegacy(read);
|
|
64
|
-
|
|
65
|
-
var version = "3.6.0";
|
|
24
|
+
var version = "3.7.1";
|
|
66
25
|
|
|
67
26
|
class CacheProvider {
|
|
68
27
|
constructor(config) {
|
|
69
|
-
this.mustValidate = false;
|
|
70
|
-
this.defaultCacheTime = 1800;
|
|
71
28
|
this.config = config;
|
|
72
29
|
}
|
|
30
|
+
mustValidate = false;
|
|
31
|
+
config;
|
|
32
|
+
defaultCacheTime = 1800;
|
|
73
33
|
/**
|
|
74
34
|
* Retrieve cache if existent, ignoring the time.
|
|
75
35
|
*
|
|
76
36
|
* The caller is responsible for handling proper validation,
|
|
77
37
|
*/
|
|
78
38
|
retrieveJson(cachekey) {
|
|
79
|
-
const cachefile =
|
|
80
|
-
if (!
|
|
39
|
+
const cachefile = path.join(this.config.cacheDir, `${cachekey}.json`);
|
|
40
|
+
if (!fs.existsSync(cachefile)) {
|
|
81
41
|
return undefined;
|
|
82
42
|
}
|
|
83
|
-
const data =
|
|
43
|
+
const data = fs.readFileSync(cachefile, "utf-8");
|
|
84
44
|
return {
|
|
85
|
-
cacheTime:
|
|
45
|
+
cacheTime: fs.statSync(cachefile).mtime.getTime(),
|
|
86
46
|
data: (data === "undefined" ? undefined : JSON.parse(data)),
|
|
87
47
|
};
|
|
88
48
|
}
|
|
@@ -90,11 +50,11 @@ class CacheProvider {
|
|
|
90
50
|
* Save data to cache.
|
|
91
51
|
*/
|
|
92
52
|
storeJson(cachekey, data) {
|
|
93
|
-
const cachefile =
|
|
94
|
-
if (!
|
|
95
|
-
|
|
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 });
|
|
96
56
|
}
|
|
97
|
-
|
|
57
|
+
fs.writeFileSync(cachefile, data === undefined ? "undefined" : JSON.stringify(data));
|
|
98
58
|
}
|
|
99
59
|
async json(cachekey, block, cachetime = this.defaultCacheTime) {
|
|
100
60
|
const cacheItem = this.mustValidate
|
|
@@ -112,26 +72,28 @@ class CacheProvider {
|
|
|
112
72
|
* Delete all cached data.
|
|
113
73
|
*/
|
|
114
74
|
cleanup() {
|
|
115
|
-
|
|
75
|
+
rimraf.sync(this.config.cacheDir);
|
|
116
76
|
}
|
|
117
77
|
}
|
|
118
78
|
|
|
119
79
|
const CLEAR_WHOLE_LINE = 0;
|
|
120
80
|
function clearLine(stdout) {
|
|
121
|
-
|
|
122
|
-
|
|
81
|
+
readline.clearLine(stdout, CLEAR_WHOLE_LINE);
|
|
82
|
+
readline.cursorTo(stdout, 0);
|
|
123
83
|
}
|
|
124
84
|
class Reporter {
|
|
125
85
|
constructor(opts = {}) {
|
|
126
|
-
this.stdout = process.stdout;
|
|
127
|
-
this.stderr = process.stderr;
|
|
128
|
-
this.stdin = process.stdin;
|
|
129
|
-
this.isTTY = this.stdout.isTTY;
|
|
130
|
-
this.format = chalk__default["default"];
|
|
131
|
-
this.startTime = Date.now();
|
|
132
86
|
this.nonInteractive = !!opts.nonInteractive;
|
|
133
87
|
this.isVerbose = !!opts.verbose;
|
|
134
88
|
}
|
|
89
|
+
stdout = process.stdout;
|
|
90
|
+
stderr = process.stderr;
|
|
91
|
+
stdin = process.stdin;
|
|
92
|
+
isTTY = this.stdout.isTTY;
|
|
93
|
+
nonInteractive;
|
|
94
|
+
isVerbose;
|
|
95
|
+
format = chalk;
|
|
96
|
+
startTime = Date.now();
|
|
135
97
|
error(msg) {
|
|
136
98
|
clearLine(this.stderr);
|
|
137
99
|
this.stderr.write(`${this.format.red("error")} ${msg}\n`);
|
|
@@ -155,15 +117,13 @@ class Reporter {
|
|
|
155
117
|
}
|
|
156
118
|
|
|
157
119
|
class Config {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
this.configCached = undefined;
|
|
166
|
-
}
|
|
120
|
+
cwd = path.resolve(process.cwd());
|
|
121
|
+
configFile = path.join(os.homedir(), ".cals-config.json");
|
|
122
|
+
cacheDir = cachedir("cals-cli");
|
|
123
|
+
agent = new https.Agent({
|
|
124
|
+
keepAlive: true,
|
|
125
|
+
});
|
|
126
|
+
configCached = undefined;
|
|
167
127
|
get config() {
|
|
168
128
|
const existingConfig = this.configCached;
|
|
169
129
|
if (existingConfig !== undefined) {
|
|
@@ -174,12 +134,12 @@ class Config {
|
|
|
174
134
|
return config;
|
|
175
135
|
}
|
|
176
136
|
readConfig() {
|
|
177
|
-
if (!
|
|
137
|
+
if (!fs.existsSync(this.configFile)) {
|
|
178
138
|
return {};
|
|
179
139
|
}
|
|
180
140
|
try {
|
|
181
141
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
182
|
-
return JSON.parse(
|
|
142
|
+
return JSON.parse(fs.readFileSync(this.configFile, "utf-8"));
|
|
183
143
|
}
|
|
184
144
|
catch (e) {
|
|
185
145
|
console.error("Failed", e);
|
|
@@ -201,7 +161,7 @@ class Config {
|
|
|
201
161
|
...this.readConfig(),
|
|
202
162
|
[key]: value, // undefined will remove
|
|
203
163
|
};
|
|
204
|
-
|
|
164
|
+
fs.writeFileSync(this.configFile, JSON.stringify(updatedConfig, null, " "));
|
|
205
165
|
this.configCached = updatedConfig;
|
|
206
166
|
}
|
|
207
167
|
}
|
|
@@ -507,12 +467,11 @@ function getRepoId(orgName, repoName) {
|
|
|
507
467
|
return `${orgName}/${repoName}`;
|
|
508
468
|
}
|
|
509
469
|
function checkAgainstSchema(value) {
|
|
510
|
-
|
|
511
|
-
const ajv = new AJV__default["default"]({ allErrors: true });
|
|
470
|
+
const ajv = new AJV({ allErrors: true });
|
|
512
471
|
const valid = ajv.validate(schema, value);
|
|
513
472
|
return valid
|
|
514
473
|
? { definition: value }
|
|
515
|
-
: { error:
|
|
474
|
+
: { error: ajv.errorsText() ?? "Unknown error" };
|
|
516
475
|
}
|
|
517
476
|
function requireValidDefinition(definition) {
|
|
518
477
|
// Verify no duplicates in users and extract known logins.
|
|
@@ -557,7 +516,8 @@ function requireValidDefinition(definition) {
|
|
|
557
516
|
if (!teamIdList.includes(id)) {
|
|
558
517
|
throw new Error(`Project team ${id} in project ${project.name} is not registered in team list`);
|
|
559
518
|
}
|
|
560
|
-
})
|
|
519
|
+
}) // Verify repo teams exists as teams.
|
|
520
|
+
;
|
|
561
521
|
(org.repos || []).forEach((repo) => {
|
|
562
522
|
(repo.teams || []).forEach((team) => {
|
|
563
523
|
const id = getTeamId(org.organization, team.name);
|
|
@@ -581,11 +541,12 @@ function requireValidDefinition(definition) {
|
|
|
581
541
|
}, []);
|
|
582
542
|
}
|
|
583
543
|
class DefinitionFile {
|
|
544
|
+
path;
|
|
584
545
|
constructor(path) {
|
|
585
546
|
this.path = path;
|
|
586
547
|
}
|
|
587
548
|
async getContents() {
|
|
588
|
-
return new Promise((resolve, reject) =>
|
|
549
|
+
return new Promise((resolve, reject) => fs.readFile(this.path, "utf-8", (err, data) => {
|
|
589
550
|
if (err)
|
|
590
551
|
reject(err);
|
|
591
552
|
else
|
|
@@ -597,7 +558,7 @@ class DefinitionFile {
|
|
|
597
558
|
}
|
|
598
559
|
}
|
|
599
560
|
function parseDefinition(value) {
|
|
600
|
-
const result = checkAgainstSchema(
|
|
561
|
+
const result = checkAgainstSchema(yaml.load(value));
|
|
601
562
|
if ("error" in result) {
|
|
602
563
|
throw new Error("Definition content invalid: " + result.error);
|
|
603
564
|
}
|
|
@@ -615,7 +576,7 @@ function getRepos(definition) {
|
|
|
615
576
|
.flat());
|
|
616
577
|
}
|
|
617
578
|
function getGitHubOrgs(definition) {
|
|
618
|
-
return
|
|
579
|
+
return uniq(definition.projects.flatMap((project) => project.github.map((it) => it.organization)));
|
|
619
580
|
}
|
|
620
581
|
|
|
621
582
|
function createReporter(argv) {
|
|
@@ -626,15 +587,13 @@ function createReporter(argv) {
|
|
|
626
587
|
}
|
|
627
588
|
|
|
628
589
|
class GitHubTokenCliProvider {
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
this.keyringAccount = "github-token";
|
|
632
|
-
}
|
|
590
|
+
keyringService = "cals";
|
|
591
|
+
keyringAccount = "github-token";
|
|
633
592
|
async getToken() {
|
|
634
593
|
if (process.env.CALS_GITHUB_TOKEN) {
|
|
635
594
|
return process.env.CALS_GITHUB_TOKEN;
|
|
636
595
|
}
|
|
637
|
-
const result = await
|
|
596
|
+
const result = await keytar.getPassword(this.keyringService, this.keyringAccount);
|
|
638
597
|
if (result == null) {
|
|
639
598
|
process.stderr.write("No token found. Register using `cals github set-token`\n");
|
|
640
599
|
return undefined;
|
|
@@ -642,10 +601,10 @@ class GitHubTokenCliProvider {
|
|
|
642
601
|
return result;
|
|
643
602
|
}
|
|
644
603
|
async markInvalid() {
|
|
645
|
-
await
|
|
604
|
+
await keytar.deletePassword(this.keyringService, this.keyringAccount);
|
|
646
605
|
}
|
|
647
606
|
async setToken(value) {
|
|
648
|
-
await
|
|
607
|
+
await keytar.setPassword(this.keyringService, this.keyringAccount, value);
|
|
649
608
|
}
|
|
650
609
|
}
|
|
651
610
|
|
|
@@ -665,15 +624,19 @@ async function undefinedForNotFound(value) {
|
|
|
665
624
|
}
|
|
666
625
|
|
|
667
626
|
class GitHubService {
|
|
627
|
+
config;
|
|
628
|
+
octokit;
|
|
629
|
+
cache;
|
|
630
|
+
tokenProvider;
|
|
631
|
+
semaphore;
|
|
668
632
|
constructor(props) {
|
|
669
|
-
this._requestCount = 0;
|
|
670
633
|
this.config = props.config;
|
|
671
634
|
this.octokit = props.octokit;
|
|
672
635
|
this.cache = props.cache;
|
|
673
636
|
this.tokenProvider = props.tokenProvider;
|
|
674
637
|
// Control concurrency to GitHub API at service level so we
|
|
675
638
|
// can maximize concurrency all other places.
|
|
676
|
-
this.semaphore =
|
|
639
|
+
this.semaphore = pLimit(6);
|
|
677
640
|
this.octokit.hook.wrap("request", async (request, options) => {
|
|
678
641
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
679
642
|
this._requestCount++;
|
|
@@ -739,6 +702,7 @@ class GitHubService {
|
|
|
739
702
|
/* eslint-enable @typescript-eslint/no-unsafe-member-access */
|
|
740
703
|
});
|
|
741
704
|
}
|
|
705
|
+
_requestCount = 0;
|
|
742
706
|
get requestCount() {
|
|
743
707
|
return this._requestCount;
|
|
744
708
|
}
|
|
@@ -753,18 +717,18 @@ class GitHubService {
|
|
|
753
717
|
};
|
|
754
718
|
let requestDuration = -1;
|
|
755
719
|
const response = await this.semaphore(() => {
|
|
756
|
-
const requestStart =
|
|
757
|
-
const result =
|
|
720
|
+
const requestStart = performance.now();
|
|
721
|
+
const result = fetch(url, {
|
|
758
722
|
method: "POST",
|
|
759
723
|
headers,
|
|
760
724
|
body: JSON.stringify({ query }),
|
|
761
725
|
agent: this.config.agent,
|
|
762
726
|
});
|
|
763
|
-
requestDuration =
|
|
727
|
+
requestDuration = performance.now() - requestStart;
|
|
764
728
|
return result;
|
|
765
729
|
});
|
|
766
730
|
if (response.status === 401) {
|
|
767
|
-
|
|
731
|
+
process$1.stderr.write("Unauthorized\n");
|
|
768
732
|
await this.tokenProvider.markInvalid();
|
|
769
733
|
}
|
|
770
734
|
// If you get 502 after 10s, it is a timeout.
|
|
@@ -857,15 +821,12 @@ class GitHubService {
|
|
|
857
821
|
login: it.login,
|
|
858
822
|
data: it,
|
|
859
823
|
})),
|
|
860
|
-
...(await this.getOrgMembersInvitedList(org)).map((it) => {
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
data: it,
|
|
867
|
-
});
|
|
868
|
-
}),
|
|
824
|
+
...(await this.getOrgMembersInvitedList(org)).map((it) => ({
|
|
825
|
+
type: "invited",
|
|
826
|
+
// TODO: Fix ?? case properly
|
|
827
|
+
login: it.login ?? "invalid",
|
|
828
|
+
data: it,
|
|
829
|
+
})),
|
|
869
830
|
];
|
|
870
831
|
}
|
|
871
832
|
async getRepository(owner, repo) {
|
|
@@ -934,15 +895,12 @@ class GitHubService {
|
|
|
934
895
|
login: it.login,
|
|
935
896
|
data: it,
|
|
936
897
|
})),
|
|
937
|
-
...(await this.getTeamMemberInvitedList(org, team)).map((it) => {
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
data: it,
|
|
944
|
-
});
|
|
945
|
-
}),
|
|
898
|
+
...(await this.getTeamMemberInvitedList(org, team)).map((it) => ({
|
|
899
|
+
type: "invited",
|
|
900
|
+
// TODO: Fix ?? case properly
|
|
901
|
+
login: it.login ?? "invalid",
|
|
902
|
+
data: it,
|
|
903
|
+
})),
|
|
946
904
|
];
|
|
947
905
|
}
|
|
948
906
|
async getSearchedPullRequestList(owner) {
|
|
@@ -1067,17 +1025,16 @@ class GitHubService {
|
|
|
1067
1025
|
}
|
|
1068
1026
|
}`;
|
|
1069
1027
|
return this.cache.json(`vulnerability-alerts-${owner}-${repo}`, async () => {
|
|
1070
|
-
var _a, _b, _c, _d, _e;
|
|
1071
1028
|
const result = [];
|
|
1072
1029
|
let after = null;
|
|
1073
1030
|
while (true) {
|
|
1074
1031
|
const query = getQuery(after);
|
|
1075
1032
|
const res = await this.runGraphqlQuery(query);
|
|
1076
|
-
result.push(...(
|
|
1077
|
-
if (!
|
|
1033
|
+
result.push(...(res.repository?.vulnerabilityAlerts.edges?.map((it) => it.node) ?? []));
|
|
1034
|
+
if (!res.repository?.vulnerabilityAlerts.pageInfo.hasNextPage) {
|
|
1078
1035
|
break;
|
|
1079
1036
|
}
|
|
1080
|
-
after =
|
|
1037
|
+
after = res.repository?.vulnerabilityAlerts.pageInfo.endCursor;
|
|
1081
1038
|
}
|
|
1082
1039
|
return result;
|
|
1083
1040
|
});
|
|
@@ -1119,27 +1076,23 @@ class GitHubService {
|
|
|
1119
1076
|
}
|
|
1120
1077
|
}`;
|
|
1121
1078
|
const issues = await this.cache.json(`renovate-bot-issues-${owner}-${repo}`, async () => {
|
|
1122
|
-
var _a, _b, _c, _d, _e;
|
|
1123
1079
|
const result = [];
|
|
1124
1080
|
let after = null;
|
|
1125
1081
|
while (true) {
|
|
1126
1082
|
const query = getQuery(after);
|
|
1127
1083
|
const res = await this.runGraphqlQuery(query);
|
|
1128
|
-
const nodes =
|
|
1084
|
+
const nodes = res.repository?.issues.edges?.map((it) => it.node) ?? [];
|
|
1129
1085
|
result.push(...nodes
|
|
1130
1086
|
.filter((it) => it.title === "Dependency Dashboard")
|
|
1131
|
-
.map((it) => {
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
});
|
|
1138
|
-
}));
|
|
1139
|
-
if (!((_d = res.repository) === null || _d === void 0 ? void 0 : _d.issues.pageInfo.hasNextPage)) {
|
|
1087
|
+
.map((it) => ({
|
|
1088
|
+
number: it.number,
|
|
1089
|
+
body: it.body,
|
|
1090
|
+
lastUpdatedByRenovate: it.userContentEdits?.nodes?.filter((it) => it.editor?.login === "renovate")?.[0]?.createdAt ?? null,
|
|
1091
|
+
})));
|
|
1092
|
+
if (!res.repository?.issues.pageInfo.hasNextPage) {
|
|
1140
1093
|
break;
|
|
1141
1094
|
}
|
|
1142
|
-
after =
|
|
1095
|
+
after = res.repository?.issues.pageInfo.endCursor;
|
|
1143
1096
|
}
|
|
1144
1097
|
return result;
|
|
1145
1098
|
});
|
|
@@ -1150,7 +1103,7 @@ class GitHubService {
|
|
|
1150
1103
|
}
|
|
1151
1104
|
}
|
|
1152
1105
|
async function createOctokit(config, tokenProvider) {
|
|
1153
|
-
return new
|
|
1106
|
+
return new Octokit({
|
|
1154
1107
|
auth: await tokenProvider.getToken(),
|
|
1155
1108
|
request: {
|
|
1156
1109
|
agent: config.agent,
|
|
@@ -1158,8 +1111,7 @@ async function createOctokit(config, tokenProvider) {
|
|
|
1158
1111
|
});
|
|
1159
1112
|
}
|
|
1160
1113
|
async function createGitHubService(props) {
|
|
1161
|
-
|
|
1162
|
-
const tokenProvider = (_a = props.tokenProvider) !== null && _a !== void 0 ? _a : new GitHubTokenCliProvider();
|
|
1114
|
+
const tokenProvider = props.tokenProvider ?? new GitHubTokenCliProvider();
|
|
1163
1115
|
return new GitHubService({
|
|
1164
1116
|
config: props.config,
|
|
1165
1117
|
octokit: await createOctokit(props.config, tokenProvider),
|
|
@@ -1184,15 +1136,13 @@ var index$2 = /*#__PURE__*/Object.freeze({
|
|
|
1184
1136
|
});
|
|
1185
1137
|
|
|
1186
1138
|
class SnykTokenCliProvider {
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
this.keyringAccount = "snyk-token";
|
|
1190
|
-
}
|
|
1139
|
+
keyringService = "cals";
|
|
1140
|
+
keyringAccount = "snyk-token";
|
|
1191
1141
|
async getToken() {
|
|
1192
1142
|
if (process.env.CALS_SNYK_TOKEN) {
|
|
1193
1143
|
return process.env.CALS_SNYK_TOKEN;
|
|
1194
1144
|
}
|
|
1195
|
-
const result = await
|
|
1145
|
+
const result = await keytar.getPassword(this.keyringService, this.keyringAccount);
|
|
1196
1146
|
if (result == null) {
|
|
1197
1147
|
process.stderr.write("No token found. Register using `cals snyk set-token`\n");
|
|
1198
1148
|
return undefined;
|
|
@@ -1200,21 +1150,22 @@ class SnykTokenCliProvider {
|
|
|
1200
1150
|
return result;
|
|
1201
1151
|
}
|
|
1202
1152
|
async markInvalid() {
|
|
1203
|
-
await
|
|
1153
|
+
await keytar.deletePassword(this.keyringService, this.keyringAccount);
|
|
1204
1154
|
}
|
|
1205
1155
|
async setToken(value) {
|
|
1206
|
-
await
|
|
1156
|
+
await keytar.setPassword(this.keyringService, this.keyringAccount, value);
|
|
1207
1157
|
}
|
|
1208
1158
|
}
|
|
1209
1159
|
|
|
1210
1160
|
class SnykService {
|
|
1161
|
+
config;
|
|
1162
|
+
tokenProvider;
|
|
1211
1163
|
constructor(props) {
|
|
1212
1164
|
this.config = props.config;
|
|
1213
1165
|
this.tokenProvider = props.tokenProvider;
|
|
1214
1166
|
}
|
|
1215
1167
|
async getProjects(definition) {
|
|
1216
|
-
|
|
1217
|
-
const snykAccountId = (_a = definition.snyk) === null || _a === void 0 ? void 0 : _a.accountId;
|
|
1168
|
+
const snykAccountId = definition.snyk?.accountId;
|
|
1218
1169
|
if (snykAccountId === undefined) {
|
|
1219
1170
|
return [];
|
|
1220
1171
|
}
|
|
@@ -1242,7 +1193,7 @@ class SnykService {
|
|
|
1242
1193
|
* We continue calling the Snyk API and retrieving more projects until links.next is null
|
|
1243
1194
|
* */
|
|
1244
1195
|
while (nextUrl) {
|
|
1245
|
-
const response = await
|
|
1196
|
+
const response = await fetch(`https://api.snyk.io/rest${nextUrl}`, {
|
|
1246
1197
|
method: "GET",
|
|
1247
1198
|
headers: {
|
|
1248
1199
|
Accept: "application/json",
|
|
@@ -1279,7 +1230,7 @@ class SnykService {
|
|
|
1279
1230
|
totalDependencies: project.meta.latest_dependency_total.total,
|
|
1280
1231
|
issueCountsBySeverity: project.meta.latest_issue_counts,
|
|
1281
1232
|
lastTestedDate: project.meta.latest_dependency_total.updated_at,
|
|
1282
|
-
browseUrl: `https://app.snyk.io/org/${snykOrgSlugId
|
|
1233
|
+
browseUrl: `https://app.snyk.io/org/${snykOrgSlugId ?? "it"}/project/${project.id}`,
|
|
1283
1234
|
};
|
|
1284
1235
|
}),
|
|
1285
1236
|
];
|
|
@@ -1291,10 +1242,9 @@ class SnykService {
|
|
|
1291
1242
|
}
|
|
1292
1243
|
}
|
|
1293
1244
|
function createSnykService(props) {
|
|
1294
|
-
var _a;
|
|
1295
1245
|
return new SnykService({
|
|
1296
1246
|
config: props.config,
|
|
1297
|
-
tokenProvider:
|
|
1247
|
+
tokenProvider: props.tokenProvider ?? new SnykTokenCliProvider(),
|
|
1298
1248
|
});
|
|
1299
1249
|
}
|
|
1300
1250
|
|
|
@@ -1352,6 +1302,8 @@ class SonarCloudTokenCliProvider {
|
|
|
1352
1302
|
}
|
|
1353
1303
|
|
|
1354
1304
|
class SonarCloudService {
|
|
1305
|
+
config;
|
|
1306
|
+
tokenProvider;
|
|
1355
1307
|
constructor(props) {
|
|
1356
1308
|
this.config = props.config;
|
|
1357
1309
|
this.tokenProvider = props.tokenProvider;
|
|
@@ -1365,7 +1317,7 @@ class SonarCloudService {
|
|
|
1365
1317
|
if (token === undefined) {
|
|
1366
1318
|
throw new Error("Missing token for SonarCloud");
|
|
1367
1319
|
}
|
|
1368
|
-
const response = await
|
|
1320
|
+
const response = await fetch(`https://sonarcloud.io/api/measures/component?component=${encodeURIComponent(sonarCloudProjectKey)}&metricKeys=coverage`, {
|
|
1369
1321
|
method: "GET",
|
|
1370
1322
|
headers: {
|
|
1371
1323
|
Accept: "application/json",
|
|
@@ -1388,10 +1340,9 @@ class SonarCloudService {
|
|
|
1388
1340
|
}
|
|
1389
1341
|
}
|
|
1390
1342
|
function createSonarCloudService(props) {
|
|
1391
|
-
var _a;
|
|
1392
1343
|
return new SonarCloudService({
|
|
1393
1344
|
config: props.config,
|
|
1394
|
-
tokenProvider:
|
|
1345
|
+
tokenProvider: props.tokenProvider ?? new SonarCloudTokenCliProvider(),
|
|
1395
1346
|
});
|
|
1396
1347
|
}
|
|
1397
1348
|
|
|
@@ -1403,12 +1354,10 @@ var index = /*#__PURE__*/Object.freeze({
|
|
|
1403
1354
|
});
|
|
1404
1355
|
|
|
1405
1356
|
class TestExecutor {
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
this.tasks = [];
|
|
1411
|
-
}
|
|
1357
|
+
shutdown = false;
|
|
1358
|
+
cleanupTask = null;
|
|
1359
|
+
usingWithCleanupTasks = false;
|
|
1360
|
+
tasks = [];
|
|
1412
1361
|
/**
|
|
1413
1362
|
* Check if we are currently in shutdown state due to user
|
|
1414
1363
|
* asking to abort (Ctrl+C).
|
|
@@ -1455,7 +1404,7 @@ class TestExecutor {
|
|
|
1455
1404
|
*/
|
|
1456
1405
|
async runWithCleanupTasks(body) {
|
|
1457
1406
|
try {
|
|
1458
|
-
|
|
1407
|
+
strict.strictEqual(this.usingWithCleanupTasks, false);
|
|
1459
1408
|
this.usingWithCleanupTasks = true;
|
|
1460
1409
|
// We capture Ctrl+C so that we can perform cleanup task,
|
|
1461
1410
|
// since the cleanup tasks involve async code which is not
|
|
@@ -1526,8 +1475,8 @@ function generateName(extra) {
|
|
|
1526
1475
|
async function createNetwork(executor) {
|
|
1527
1476
|
executor.checkCanContinue();
|
|
1528
1477
|
const networkName = generateName();
|
|
1529
|
-
await
|
|
1530
|
-
const lsRes = await
|
|
1478
|
+
await execa("docker", ["network", "create", networkName]);
|
|
1479
|
+
const lsRes = await execa("docker", [
|
|
1531
1480
|
"network",
|
|
1532
1481
|
"ls",
|
|
1533
1482
|
"-q",
|
|
@@ -1537,7 +1486,7 @@ async function createNetwork(executor) {
|
|
|
1537
1486
|
const networkId = lsRes.stdout.trim();
|
|
1538
1487
|
console.log(`Network ${networkName} (${networkId}) created`);
|
|
1539
1488
|
executor.registerCleanupTask(async () => {
|
|
1540
|
-
await
|
|
1489
|
+
await execa("docker", ["network", "rm", networkId]);
|
|
1541
1490
|
console.log(`Network ${networkName} (${networkId}) deleted`);
|
|
1542
1491
|
});
|
|
1543
1492
|
return {
|
|
@@ -1549,7 +1498,7 @@ async function createNetwork(executor) {
|
|
|
1549
1498
|
*/
|
|
1550
1499
|
async function curl(executor, network, ...args) {
|
|
1551
1500
|
executor.checkCanContinue();
|
|
1552
|
-
const result = await
|
|
1501
|
+
const result = await execa("docker", [
|
|
1553
1502
|
"run",
|
|
1554
1503
|
"-i",
|
|
1555
1504
|
"--rm",
|
|
@@ -1572,9 +1521,9 @@ async function pollForCondition({ container, attempts, waitIntervalSec, conditio
|
|
|
1572
1521
|
}
|
|
1573
1522
|
container.executor.checkCanContinue();
|
|
1574
1523
|
log(`Waiting for condition.. Checking ${attempts} times by ${waitIntervalSec} sec`);
|
|
1575
|
-
const start =
|
|
1524
|
+
const start = performance.now();
|
|
1576
1525
|
const duration = () => {
|
|
1577
|
-
const end =
|
|
1526
|
+
const end = performance.now();
|
|
1578
1527
|
return Math.round((end - start) / 1000);
|
|
1579
1528
|
};
|
|
1580
1529
|
for (let i = 0; i < attempts; i++) {
|
|
@@ -1614,7 +1563,7 @@ async function waitForPostgresAvailable({ container, attempts = 30, waitInterval
|
|
|
1614
1563
|
attempts,
|
|
1615
1564
|
waitIntervalSec,
|
|
1616
1565
|
condition: async () => {
|
|
1617
|
-
await
|
|
1566
|
+
await execa("docker", [
|
|
1618
1567
|
"exec",
|
|
1619
1568
|
"-e",
|
|
1620
1569
|
`PGPASSWORD=${password}`,
|
|
@@ -1635,7 +1584,7 @@ async function waitForPostgresAvailable({ container, attempts = 30, waitInterval
|
|
|
1635
1584
|
async function isRunning(executor, container) {
|
|
1636
1585
|
executor.checkCanContinue();
|
|
1637
1586
|
try {
|
|
1638
|
-
await
|
|
1587
|
+
await execa("docker", ["inspect", container.name]);
|
|
1639
1588
|
return true;
|
|
1640
1589
|
}
|
|
1641
1590
|
catch {
|
|
@@ -1647,7 +1596,7 @@ async function isRunning(executor, container) {
|
|
|
1647
1596
|
* and also forces every chunk to end with a newline so that
|
|
1648
1597
|
* it can be interleaved with other output.
|
|
1649
1598
|
*/
|
|
1650
|
-
class OutputPrefixTransform extends
|
|
1599
|
+
class OutputPrefixTransform extends Transform {
|
|
1651
1600
|
constructor(prefix) {
|
|
1652
1601
|
super({
|
|
1653
1602
|
objectMode: true,
|
|
@@ -1670,9 +1619,12 @@ class OutputPrefixTransform extends stream.Transform {
|
|
|
1670
1619
|
}
|
|
1671
1620
|
}
|
|
1672
1621
|
function pipeToConsole(result, name) {
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1622
|
+
result.stdout
|
|
1623
|
+
?.pipe(new OutputPrefixTransform(`${name}: `))
|
|
1624
|
+
.pipe(process.stdout);
|
|
1625
|
+
result.stderr
|
|
1626
|
+
?.pipe(new OutputPrefixTransform(`${name} (stderr): `))
|
|
1627
|
+
.pipe(process.stderr);
|
|
1676
1628
|
}
|
|
1677
1629
|
function checkPidRunning(pid) {
|
|
1678
1630
|
try {
|
|
@@ -1690,14 +1642,14 @@ async function getContainerId({ executor, name, hasFailed, pid, }) {
|
|
|
1690
1642
|
async function check() {
|
|
1691
1643
|
let result;
|
|
1692
1644
|
try {
|
|
1693
|
-
result = (await
|
|
1645
|
+
result = (await execa("docker", ["inspect", name, "-f", "{{.Id}}"]))
|
|
1694
1646
|
.stdout;
|
|
1695
1647
|
}
|
|
1696
1648
|
catch {
|
|
1697
1649
|
result = null;
|
|
1698
1650
|
}
|
|
1699
1651
|
// Debugging to help us solve CALS-366.
|
|
1700
|
-
const ps =
|
|
1652
|
+
const ps = execa("docker", ["ps"]);
|
|
1701
1653
|
pipeToConsole(ps, `${name} (ps)`);
|
|
1702
1654
|
await ps;
|
|
1703
1655
|
// Debugging to help us solve CALS-366.
|
|
@@ -1730,12 +1682,12 @@ async function getContainerId({ executor, name, hasFailed, pid, }) {
|
|
|
1730
1682
|
}
|
|
1731
1683
|
async function pullImage({ imageId }) {
|
|
1732
1684
|
console.log(`Pulling ${imageId}`);
|
|
1733
|
-
const process =
|
|
1685
|
+
const process = execa("docker", ["pull", imageId]);
|
|
1734
1686
|
pipeToConsole(process, `pull-image (${imageId})`);
|
|
1735
1687
|
await process;
|
|
1736
1688
|
}
|
|
1737
1689
|
async function checkImageExistsLocally({ imageId, }) {
|
|
1738
|
-
const result = await
|
|
1690
|
+
const result = await execa("docker", ["images", "-q", imageId]);
|
|
1739
1691
|
const found = result.stdout != "";
|
|
1740
1692
|
console.log(`image ${imageId} ${found ? "was present locally" : "was not found locally"}`);
|
|
1741
1693
|
return found;
|
|
@@ -1771,8 +1723,8 @@ async function startContainer({ executor, network, imageId, alias, env, dockerAr
|
|
|
1771
1723
|
}
|
|
1772
1724
|
args.push(imageId);
|
|
1773
1725
|
console.log(`Starting ${imageId}`);
|
|
1774
|
-
const process =
|
|
1775
|
-
pipeToConsole(process, alias
|
|
1726
|
+
const process = execa("docker", args);
|
|
1727
|
+
pipeToConsole(process, alias ?? containerName);
|
|
1776
1728
|
let failed = false;
|
|
1777
1729
|
process.catch(() => {
|
|
1778
1730
|
failed = true;
|
|
@@ -1788,8 +1740,8 @@ async function startContainer({ executor, network, imageId, alias, env, dockerAr
|
|
|
1788
1740
|
});
|
|
1789
1741
|
executor.registerCleanupTask(async () => {
|
|
1790
1742
|
console.log(`Stopping container ${containerName}`);
|
|
1791
|
-
const r =
|
|
1792
|
-
pipeToConsole(r, (alias
|
|
1743
|
+
const r = execa("docker", ["stop", containerName]);
|
|
1744
|
+
pipeToConsole(r, (alias ?? containerName) + " (stop)");
|
|
1793
1745
|
try {
|
|
1794
1746
|
await r;
|
|
1795
1747
|
}
|
|
@@ -1809,8 +1761,8 @@ async function startContainer({ executor, network, imageId, alias, env, dockerAr
|
|
|
1809
1761
|
};
|
|
1810
1762
|
}
|
|
1811
1763
|
async function runNpmRunScript(name, options) {
|
|
1812
|
-
const result =
|
|
1813
|
-
env: options
|
|
1764
|
+
const result = execa("npm", ["run", name], {
|
|
1765
|
+
env: options?.env,
|
|
1814
1766
|
});
|
|
1815
1767
|
pipeToConsole(result, `npm run ${name}`);
|
|
1816
1768
|
await result;
|
|
@@ -1822,8 +1774,8 @@ async function getDockerHostAddress() {
|
|
|
1822
1774
|
if (process.platform === "darwin" || process.platform === "win32") {
|
|
1823
1775
|
return "host.docker.internal";
|
|
1824
1776
|
}
|
|
1825
|
-
if (
|
|
1826
|
-
const process =
|
|
1777
|
+
if (fs.existsSync("/.dockerenv")) {
|
|
1778
|
+
const process = execa("ip", ["route"]);
|
|
1827
1779
|
pipeToConsole(process, "ip route");
|
|
1828
1780
|
const res = await process;
|
|
1829
1781
|
try {
|
|
@@ -1840,7 +1792,7 @@ async function getDockerHostAddress() {
|
|
|
1840
1792
|
}
|
|
1841
1793
|
async function waitForEnterToContinue(prompt = "Press enter to continue") {
|
|
1842
1794
|
return new Promise((resolve, reject) => {
|
|
1843
|
-
|
|
1795
|
+
read({
|
|
1844
1796
|
prompt,
|
|
1845
1797
|
silent: true,
|
|
1846
1798
|
}, (err) => {
|
|
@@ -1855,27 +1807,5 @@ async function waitForEnterToContinue(prompt = "Press enter to continue") {
|
|
|
1855
1807
|
|
|
1856
1808
|
const VERSION = version;
|
|
1857
1809
|
|
|
1858
|
-
|
|
1859
|
-
exports.Config = Config;
|
|
1860
|
-
exports.DefinitionFile = DefinitionFile;
|
|
1861
|
-
exports.GitHubService = GitHubService;
|
|
1862
|
-
exports.Reporter = Reporter;
|
|
1863
|
-
exports.TestExecutor = TestExecutor;
|
|
1864
|
-
exports.VERSION = VERSION;
|
|
1865
|
-
exports.createGitHubService = createGitHubService;
|
|
1866
|
-
exports.createNetwork = createNetwork;
|
|
1867
|
-
exports.createReporter = createReporter;
|
|
1868
|
-
exports.createTestExecutor = createTestExecutor;
|
|
1869
|
-
exports.curl = curl;
|
|
1870
|
-
exports.definition = index$3;
|
|
1871
|
-
exports.getDockerHostAddress = getDockerHostAddress;
|
|
1872
|
-
exports.github = index$2;
|
|
1873
|
-
exports.pollForCondition = pollForCondition;
|
|
1874
|
-
exports.runNpmRunScript = runNpmRunScript;
|
|
1875
|
-
exports.snyk = index$1;
|
|
1876
|
-
exports.sonarCloud = index;
|
|
1877
|
-
exports.startContainer = startContainer;
|
|
1878
|
-
exports.waitForEnterToContinue = waitForEnterToContinue;
|
|
1879
|
-
exports.waitForHttpOk = waitForHttpOk;
|
|
1880
|
-
exports.waitForPostgresAvailable = waitForPostgresAvailable;
|
|
1810
|
+
export { CacheProvider, Config, DefinitionFile, GitHubService, Reporter, TestExecutor, VERSION, createGitHubService, createNetwork, createReporter, createTestExecutor, curl, index$3 as definition, getDockerHostAddress, index$2 as github, pollForCondition, runNpmRunScript, index$1 as snyk, index as sonarCloud, startContainer, waitForEnterToContinue, waitForHttpOk, waitForPostgresAvailable };
|
|
1881
1811
|
//# sourceMappingURL=index.js.map
|