@capraconsulting/cals-cli 3.5.2 → 3.7.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.
- package/lib/{cals-cli.js → cals-cli.mjs} +230 -309
- 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.d.ts +0 -1
- package/lib/index.es.js +91 -427
- package/lib/index.es.js.map +1 -1
- package/lib/index.js +163 -563
- 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 +21 -17
- package/lib/load-secrets/index.d.ts +0 -2
- package/lib/load-secrets/load-secrets.d.ts +0 -7
- package/lib/load-secrets/types.d.ts +0 -34
package/lib/index.js
CHANGED
|
@@ -1,90 +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 clientSecretsManager = require('@aws-sdk/client-secrets-manager');
|
|
24
|
-
var clientSts = require('@aws-sdk/client-sts');
|
|
25
|
-
var read = require('read');
|
|
26
|
-
var assert = require('assert');
|
|
27
|
-
var execa = require('execa');
|
|
28
|
-
var stream = require('stream');
|
|
29
|
-
|
|
30
|
-
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
31
|
-
|
|
32
|
-
function _interopNamespace(e) {
|
|
33
|
-
if (e && e.__esModule) return e;
|
|
34
|
-
var n = Object.create(null);
|
|
35
|
-
if (e) {
|
|
36
|
-
Object.keys(e).forEach(function (k) {
|
|
37
|
-
if (k !== 'default') {
|
|
38
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
39
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
40
|
-
enumerable: true,
|
|
41
|
-
get: function () { return e[k]; }
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
n["default"] = e;
|
|
47
|
-
return Object.freeze(n);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
|
|
51
|
-
var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
|
|
52
|
-
var rimraf__default = /*#__PURE__*/_interopDefaultLegacy(rimraf);
|
|
53
|
-
var chalk__default = /*#__PURE__*/_interopDefaultLegacy(chalk);
|
|
54
|
-
var readline__default = /*#__PURE__*/_interopDefaultLegacy(readline);
|
|
55
|
-
var cachedir__default = /*#__PURE__*/_interopDefaultLegacy(cachedir);
|
|
56
|
-
var https__default = /*#__PURE__*/_interopDefaultLegacy(https);
|
|
57
|
-
var os__default = /*#__PURE__*/_interopDefaultLegacy(os);
|
|
58
|
-
var AJV__default = /*#__PURE__*/_interopDefaultLegacy(AJV);
|
|
59
|
-
var yaml__default = /*#__PURE__*/_interopDefaultLegacy(yaml);
|
|
60
|
-
var fetch__default = /*#__PURE__*/_interopDefaultLegacy(fetch);
|
|
61
|
-
var pLimit__default = /*#__PURE__*/_interopDefaultLegacy(pLimit);
|
|
62
|
-
var keytar__default = /*#__PURE__*/_interopDefaultLegacy(keytar);
|
|
63
|
-
var process__namespace = /*#__PURE__*/_interopNamespace(process$1);
|
|
64
|
-
var read__default = /*#__PURE__*/_interopDefaultLegacy(read);
|
|
65
|
-
var execa__default = /*#__PURE__*/_interopDefaultLegacy(execa);
|
|
66
|
-
|
|
67
|
-
var version = "3.5.2";
|
|
24
|
+
var version = "3.7.0";
|
|
68
25
|
|
|
69
26
|
class CacheProvider {
|
|
70
27
|
constructor(config) {
|
|
71
|
-
this.mustValidate = false;
|
|
72
|
-
this.defaultCacheTime = 1800;
|
|
73
28
|
this.config = config;
|
|
74
29
|
}
|
|
30
|
+
mustValidate = false;
|
|
31
|
+
config;
|
|
32
|
+
defaultCacheTime = 1800;
|
|
75
33
|
/**
|
|
76
34
|
* Retrieve cache if existent, ignoring the time.
|
|
77
35
|
*
|
|
78
36
|
* The caller is responsible for handling proper validation,
|
|
79
37
|
*/
|
|
80
38
|
retrieveJson(cachekey) {
|
|
81
|
-
const cachefile =
|
|
82
|
-
if (!
|
|
39
|
+
const cachefile = path.join(this.config.cacheDir, `${cachekey}.json`);
|
|
40
|
+
if (!fs.existsSync(cachefile)) {
|
|
83
41
|
return undefined;
|
|
84
42
|
}
|
|
85
|
-
const data =
|
|
43
|
+
const data = fs.readFileSync(cachefile, "utf-8");
|
|
86
44
|
return {
|
|
87
|
-
cacheTime:
|
|
45
|
+
cacheTime: fs.statSync(cachefile).mtime.getTime(),
|
|
88
46
|
data: (data === "undefined" ? undefined : JSON.parse(data)),
|
|
89
47
|
};
|
|
90
48
|
}
|
|
@@ -92,11 +50,11 @@ class CacheProvider {
|
|
|
92
50
|
* Save data to cache.
|
|
93
51
|
*/
|
|
94
52
|
storeJson(cachekey, data) {
|
|
95
|
-
const cachefile =
|
|
96
|
-
if (!
|
|
97
|
-
|
|
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 });
|
|
98
56
|
}
|
|
99
|
-
|
|
57
|
+
fs.writeFileSync(cachefile, data === undefined ? "undefined" : JSON.stringify(data));
|
|
100
58
|
}
|
|
101
59
|
async json(cachekey, block, cachetime = this.defaultCacheTime) {
|
|
102
60
|
const cacheItem = this.mustValidate
|
|
@@ -114,26 +72,28 @@ class CacheProvider {
|
|
|
114
72
|
* Delete all cached data.
|
|
115
73
|
*/
|
|
116
74
|
cleanup() {
|
|
117
|
-
|
|
75
|
+
rimraf.sync(this.config.cacheDir);
|
|
118
76
|
}
|
|
119
77
|
}
|
|
120
78
|
|
|
121
79
|
const CLEAR_WHOLE_LINE = 0;
|
|
122
80
|
function clearLine(stdout) {
|
|
123
|
-
|
|
124
|
-
|
|
81
|
+
readline.clearLine(stdout, CLEAR_WHOLE_LINE);
|
|
82
|
+
readline.cursorTo(stdout, 0);
|
|
125
83
|
}
|
|
126
84
|
class Reporter {
|
|
127
85
|
constructor(opts = {}) {
|
|
128
|
-
this.stdout = process.stdout;
|
|
129
|
-
this.stderr = process.stderr;
|
|
130
|
-
this.stdin = process.stdin;
|
|
131
|
-
this.isTTY = this.stdout.isTTY;
|
|
132
|
-
this.format = chalk__default["default"];
|
|
133
|
-
this.startTime = Date.now();
|
|
134
86
|
this.nonInteractive = !!opts.nonInteractive;
|
|
135
87
|
this.isVerbose = !!opts.verbose;
|
|
136
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();
|
|
137
97
|
error(msg) {
|
|
138
98
|
clearLine(this.stderr);
|
|
139
99
|
this.stderr.write(`${this.format.red("error")} ${msg}\n`);
|
|
@@ -157,15 +117,13 @@ class Reporter {
|
|
|
157
117
|
}
|
|
158
118
|
|
|
159
119
|
class Config {
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
this.configCached = undefined;
|
|
168
|
-
}
|
|
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;
|
|
169
127
|
get config() {
|
|
170
128
|
const existingConfig = this.configCached;
|
|
171
129
|
if (existingConfig !== undefined) {
|
|
@@ -176,12 +134,12 @@ class Config {
|
|
|
176
134
|
return config;
|
|
177
135
|
}
|
|
178
136
|
readConfig() {
|
|
179
|
-
if (!
|
|
137
|
+
if (!fs.existsSync(this.configFile)) {
|
|
180
138
|
return {};
|
|
181
139
|
}
|
|
182
140
|
try {
|
|
183
141
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
184
|
-
return JSON.parse(
|
|
142
|
+
return JSON.parse(fs.readFileSync(this.configFile, "utf-8"));
|
|
185
143
|
}
|
|
186
144
|
catch (e) {
|
|
187
145
|
console.error("Failed", e);
|
|
@@ -203,7 +161,7 @@ class Config {
|
|
|
203
161
|
...this.readConfig(),
|
|
204
162
|
[key]: value, // undefined will remove
|
|
205
163
|
};
|
|
206
|
-
|
|
164
|
+
fs.writeFileSync(this.configFile, JSON.stringify(updatedConfig, null, " "));
|
|
207
165
|
this.configCached = updatedConfig;
|
|
208
166
|
}
|
|
209
167
|
}
|
|
@@ -509,12 +467,11 @@ function getRepoId(orgName, repoName) {
|
|
|
509
467
|
return `${orgName}/${repoName}`;
|
|
510
468
|
}
|
|
511
469
|
function checkAgainstSchema(value) {
|
|
512
|
-
|
|
513
|
-
const ajv = new AJV__default["default"]({ allErrors: true });
|
|
470
|
+
const ajv = new AJV({ allErrors: true });
|
|
514
471
|
const valid = ajv.validate(schema, value);
|
|
515
472
|
return valid
|
|
516
473
|
? { definition: value }
|
|
517
|
-
: { error:
|
|
474
|
+
: { error: ajv.errorsText() ?? "Unknown error" };
|
|
518
475
|
}
|
|
519
476
|
function requireValidDefinition(definition) {
|
|
520
477
|
// Verify no duplicates in users and extract known logins.
|
|
@@ -559,7 +516,8 @@ function requireValidDefinition(definition) {
|
|
|
559
516
|
if (!teamIdList.includes(id)) {
|
|
560
517
|
throw new Error(`Project team ${id} in project ${project.name} is not registered in team list`);
|
|
561
518
|
}
|
|
562
|
-
})
|
|
519
|
+
}) // Verify repo teams exists as teams.
|
|
520
|
+
;
|
|
563
521
|
(org.repos || []).forEach((repo) => {
|
|
564
522
|
(repo.teams || []).forEach((team) => {
|
|
565
523
|
const id = getTeamId(org.organization, team.name);
|
|
@@ -583,11 +541,12 @@ function requireValidDefinition(definition) {
|
|
|
583
541
|
}, []);
|
|
584
542
|
}
|
|
585
543
|
class DefinitionFile {
|
|
544
|
+
path;
|
|
586
545
|
constructor(path) {
|
|
587
546
|
this.path = path;
|
|
588
547
|
}
|
|
589
548
|
async getContents() {
|
|
590
|
-
return new Promise((resolve, reject) =>
|
|
549
|
+
return new Promise((resolve, reject) => fs.readFile(this.path, "utf-8", (err, data) => {
|
|
591
550
|
if (err)
|
|
592
551
|
reject(err);
|
|
593
552
|
else
|
|
@@ -599,7 +558,7 @@ class DefinitionFile {
|
|
|
599
558
|
}
|
|
600
559
|
}
|
|
601
560
|
function parseDefinition(value) {
|
|
602
|
-
const result = checkAgainstSchema(
|
|
561
|
+
const result = checkAgainstSchema(yaml.load(value));
|
|
603
562
|
if ("error" in result) {
|
|
604
563
|
throw new Error("Definition content invalid: " + result.error);
|
|
605
564
|
}
|
|
@@ -617,7 +576,7 @@ function getRepos(definition) {
|
|
|
617
576
|
.flat());
|
|
618
577
|
}
|
|
619
578
|
function getGitHubOrgs(definition) {
|
|
620
|
-
return
|
|
579
|
+
return uniq(definition.projects.flatMap((project) => project.github.map((it) => it.organization)));
|
|
621
580
|
}
|
|
622
581
|
|
|
623
582
|
function createReporter(argv) {
|
|
@@ -628,15 +587,13 @@ function createReporter(argv) {
|
|
|
628
587
|
}
|
|
629
588
|
|
|
630
589
|
class GitHubTokenCliProvider {
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
this.keyringAccount = "github-token";
|
|
634
|
-
}
|
|
590
|
+
keyringService = "cals";
|
|
591
|
+
keyringAccount = "github-token";
|
|
635
592
|
async getToken() {
|
|
636
593
|
if (process.env.CALS_GITHUB_TOKEN) {
|
|
637
594
|
return process.env.CALS_GITHUB_TOKEN;
|
|
638
595
|
}
|
|
639
|
-
const result = await
|
|
596
|
+
const result = await keytar.getPassword(this.keyringService, this.keyringAccount);
|
|
640
597
|
if (result == null) {
|
|
641
598
|
process.stderr.write("No token found. Register using `cals github set-token`\n");
|
|
642
599
|
return undefined;
|
|
@@ -644,10 +601,10 @@ class GitHubTokenCliProvider {
|
|
|
644
601
|
return result;
|
|
645
602
|
}
|
|
646
603
|
async markInvalid() {
|
|
647
|
-
await
|
|
604
|
+
await keytar.deletePassword(this.keyringService, this.keyringAccount);
|
|
648
605
|
}
|
|
649
606
|
async setToken(value) {
|
|
650
|
-
await
|
|
607
|
+
await keytar.setPassword(this.keyringService, this.keyringAccount, value);
|
|
651
608
|
}
|
|
652
609
|
}
|
|
653
610
|
|
|
@@ -667,20 +624,23 @@ async function undefinedForNotFound(value) {
|
|
|
667
624
|
}
|
|
668
625
|
|
|
669
626
|
class GitHubService {
|
|
627
|
+
config;
|
|
628
|
+
octokit;
|
|
629
|
+
cache;
|
|
630
|
+
tokenProvider;
|
|
631
|
+
semaphore;
|
|
670
632
|
constructor(props) {
|
|
671
|
-
this._requestCount = 0;
|
|
672
633
|
this.config = props.config;
|
|
673
634
|
this.octokit = props.octokit;
|
|
674
635
|
this.cache = props.cache;
|
|
675
636
|
this.tokenProvider = props.tokenProvider;
|
|
676
637
|
// Control concurrency to GitHub API at service level so we
|
|
677
638
|
// can maximize concurrency all other places.
|
|
678
|
-
this.semaphore =
|
|
639
|
+
this.semaphore = pLimit(6);
|
|
679
640
|
this.octokit.hook.wrap("request", async (request, options) => {
|
|
680
641
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
681
642
|
this._requestCount++;
|
|
682
643
|
if (options.method !== "GET") {
|
|
683
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
684
644
|
return this.semaphore(() => request(options));
|
|
685
645
|
}
|
|
686
646
|
// Try to cache ETag for GET requests to save on rate limiting.
|
|
@@ -704,7 +664,6 @@ class GitHubService {
|
|
|
704
664
|
}
|
|
705
665
|
const getResponse = async (allowRetry = true) => {
|
|
706
666
|
try {
|
|
707
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
708
667
|
return await request(options);
|
|
709
668
|
}
|
|
710
669
|
catch (e) {
|
|
@@ -743,6 +702,7 @@ class GitHubService {
|
|
|
743
702
|
/* eslint-enable @typescript-eslint/no-unsafe-member-access */
|
|
744
703
|
});
|
|
745
704
|
}
|
|
705
|
+
_requestCount = 0;
|
|
746
706
|
get requestCount() {
|
|
747
707
|
return this._requestCount;
|
|
748
708
|
}
|
|
@@ -757,18 +717,18 @@ class GitHubService {
|
|
|
757
717
|
};
|
|
758
718
|
let requestDuration = -1;
|
|
759
719
|
const response = await this.semaphore(() => {
|
|
760
|
-
const requestStart =
|
|
761
|
-
const result =
|
|
720
|
+
const requestStart = performance.now();
|
|
721
|
+
const result = fetch(url, {
|
|
762
722
|
method: "POST",
|
|
763
723
|
headers,
|
|
764
724
|
body: JSON.stringify({ query }),
|
|
765
725
|
agent: this.config.agent,
|
|
766
726
|
});
|
|
767
|
-
requestDuration =
|
|
727
|
+
requestDuration = performance.now() - requestStart;
|
|
768
728
|
return result;
|
|
769
729
|
});
|
|
770
730
|
if (response.status === 401) {
|
|
771
|
-
|
|
731
|
+
process$1.stderr.write("Unauthorized\n");
|
|
772
732
|
await this.tokenProvider.markInvalid();
|
|
773
733
|
}
|
|
774
734
|
// If you get 502 after 10s, it is a timeout.
|
|
@@ -833,7 +793,6 @@ class GitHubService {
|
|
|
833
793
|
if (res.organization.repositories.nodes == null) {
|
|
834
794
|
throw new Error("Missing organization nodes");
|
|
835
795
|
}
|
|
836
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
837
796
|
repos.push(...res.organization.repositories.nodes);
|
|
838
797
|
if (!res.organization.repositories.pageInfo.hasNextPage) {
|
|
839
798
|
break;
|
|
@@ -862,15 +821,12 @@ class GitHubService {
|
|
|
862
821
|
login: it.login,
|
|
863
822
|
data: it,
|
|
864
823
|
})),
|
|
865
|
-
...(await this.getOrgMembersInvitedList(org)).map((it) => {
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
data: it,
|
|
872
|
-
});
|
|
873
|
-
}),
|
|
824
|
+
...(await this.getOrgMembersInvitedList(org)).map((it) => ({
|
|
825
|
+
type: "invited",
|
|
826
|
+
// TODO: Fix ?? case properly
|
|
827
|
+
login: it.login ?? "invalid",
|
|
828
|
+
data: it,
|
|
829
|
+
})),
|
|
874
830
|
];
|
|
875
831
|
}
|
|
876
832
|
async getRepository(owner, repo) {
|
|
@@ -939,15 +895,12 @@ class GitHubService {
|
|
|
939
895
|
login: it.login,
|
|
940
896
|
data: it,
|
|
941
897
|
})),
|
|
942
|
-
...(await this.getTeamMemberInvitedList(org, team)).map((it) => {
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
data: it,
|
|
949
|
-
});
|
|
950
|
-
}),
|
|
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
|
+
})),
|
|
951
904
|
];
|
|
952
905
|
}
|
|
953
906
|
async getSearchedPullRequestList(owner) {
|
|
@@ -1072,17 +1025,16 @@ class GitHubService {
|
|
|
1072
1025
|
}
|
|
1073
1026
|
}`;
|
|
1074
1027
|
return this.cache.json(`vulnerability-alerts-${owner}-${repo}`, async () => {
|
|
1075
|
-
var _a, _b, _c, _d, _e;
|
|
1076
1028
|
const result = [];
|
|
1077
1029
|
let after = null;
|
|
1078
1030
|
while (true) {
|
|
1079
1031
|
const query = getQuery(after);
|
|
1080
1032
|
const res = await this.runGraphqlQuery(query);
|
|
1081
|
-
result.push(...(
|
|
1082
|
-
if (!
|
|
1033
|
+
result.push(...(res.repository?.vulnerabilityAlerts.edges?.map((it) => it.node) ?? []));
|
|
1034
|
+
if (!res.repository?.vulnerabilityAlerts.pageInfo.hasNextPage) {
|
|
1083
1035
|
break;
|
|
1084
1036
|
}
|
|
1085
|
-
after =
|
|
1037
|
+
after = res.repository?.vulnerabilityAlerts.pageInfo.endCursor;
|
|
1086
1038
|
}
|
|
1087
1039
|
return result;
|
|
1088
1040
|
});
|
|
@@ -1124,27 +1076,23 @@ class GitHubService {
|
|
|
1124
1076
|
}
|
|
1125
1077
|
}`;
|
|
1126
1078
|
const issues = await this.cache.json(`renovate-bot-issues-${owner}-${repo}`, async () => {
|
|
1127
|
-
var _a, _b, _c, _d, _e;
|
|
1128
1079
|
const result = [];
|
|
1129
1080
|
let after = null;
|
|
1130
1081
|
while (true) {
|
|
1131
1082
|
const query = getQuery(after);
|
|
1132
1083
|
const res = await this.runGraphqlQuery(query);
|
|
1133
|
-
const nodes =
|
|
1084
|
+
const nodes = res.repository?.issues.edges?.map((it) => it.node) ?? [];
|
|
1134
1085
|
result.push(...nodes
|
|
1135
1086
|
.filter((it) => it.title === "Dependency Dashboard")
|
|
1136
|
-
.map((it) => {
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
});
|
|
1143
|
-
}));
|
|
1144
|
-
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) {
|
|
1145
1093
|
break;
|
|
1146
1094
|
}
|
|
1147
|
-
after =
|
|
1095
|
+
after = res.repository?.issues.pageInfo.endCursor;
|
|
1148
1096
|
}
|
|
1149
1097
|
return result;
|
|
1150
1098
|
});
|
|
@@ -1155,7 +1103,7 @@ class GitHubService {
|
|
|
1155
1103
|
}
|
|
1156
1104
|
}
|
|
1157
1105
|
async function createOctokit(config, tokenProvider) {
|
|
1158
|
-
return new
|
|
1106
|
+
return new Octokit({
|
|
1159
1107
|
auth: await tokenProvider.getToken(),
|
|
1160
1108
|
request: {
|
|
1161
1109
|
agent: config.agent,
|
|
@@ -1163,8 +1111,7 @@ async function createOctokit(config, tokenProvider) {
|
|
|
1163
1111
|
});
|
|
1164
1112
|
}
|
|
1165
1113
|
async function createGitHubService(props) {
|
|
1166
|
-
|
|
1167
|
-
const tokenProvider = (_a = props.tokenProvider) !== null && _a !== void 0 ? _a : new GitHubTokenCliProvider();
|
|
1114
|
+
const tokenProvider = props.tokenProvider ?? new GitHubTokenCliProvider();
|
|
1168
1115
|
return new GitHubService({
|
|
1169
1116
|
config: props.config,
|
|
1170
1117
|
octokit: await createOctokit(props.config, tokenProvider),
|
|
@@ -1173,7 +1120,7 @@ async function createGitHubService(props) {
|
|
|
1173
1120
|
});
|
|
1174
1121
|
}
|
|
1175
1122
|
|
|
1176
|
-
var index$
|
|
1123
|
+
var index$3 = /*#__PURE__*/Object.freeze({
|
|
1177
1124
|
__proto__: null,
|
|
1178
1125
|
DefinitionFile: DefinitionFile,
|
|
1179
1126
|
getGitHubOrgs: getGitHubOrgs,
|
|
@@ -1182,346 +1129,20 @@ var index$4 = /*#__PURE__*/Object.freeze({
|
|
|
1182
1129
|
parseDefinition: parseDefinition
|
|
1183
1130
|
});
|
|
1184
1131
|
|
|
1185
|
-
var index$
|
|
1132
|
+
var index$2 = /*#__PURE__*/Object.freeze({
|
|
1186
1133
|
__proto__: null,
|
|
1187
1134
|
createGitHubService: createGitHubService,
|
|
1188
1135
|
GitHubService: GitHubService
|
|
1189
1136
|
});
|
|
1190
1137
|
|
|
1191
|
-
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
1192
|
-
class LoadSecrets {
|
|
1193
|
-
constructor(props) {
|
|
1194
|
-
this.smClientForRegions = {};
|
|
1195
|
-
this.stsClient = new clientSts.STSClient({
|
|
1196
|
-
region: "eu-west-1",
|
|
1197
|
-
});
|
|
1198
|
-
this.reporter = props.reporter;
|
|
1199
|
-
this.silent = props.silent;
|
|
1200
|
-
}
|
|
1201
|
-
getSmClient(region) {
|
|
1202
|
-
if (!this.smClientForRegions[region]) {
|
|
1203
|
-
this.smClientForRegions[region] = new clientSecretsManager.SecretsManagerClient({
|
|
1204
|
-
region,
|
|
1205
|
-
});
|
|
1206
|
-
}
|
|
1207
|
-
return this.smClientForRegions[region];
|
|
1208
|
-
}
|
|
1209
|
-
async getInput(options) {
|
|
1210
|
-
return new Promise((resolve, reject) => {
|
|
1211
|
-
read__default["default"](options, (err, answer) => {
|
|
1212
|
-
if (err) {
|
|
1213
|
-
reject(err);
|
|
1214
|
-
}
|
|
1215
|
-
resolve(answer);
|
|
1216
|
-
});
|
|
1217
|
-
});
|
|
1218
|
-
}
|
|
1219
|
-
async getSecretDetails(client, secretId) {
|
|
1220
|
-
try {
|
|
1221
|
-
return await client.send(new clientSecretsManager.DescribeSecretCommand({ SecretId: secretId }));
|
|
1222
|
-
}
|
|
1223
|
-
catch (e) {
|
|
1224
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
1225
|
-
if (e.name && e.name === "ResourceNotFoundException") {
|
|
1226
|
-
return null;
|
|
1227
|
-
}
|
|
1228
|
-
throw e;
|
|
1229
|
-
}
|
|
1230
|
-
}
|
|
1231
|
-
async handleStringUpdate() {
|
|
1232
|
-
return await this.getInput({
|
|
1233
|
-
prompt: "Enter value (Ctrl+C to abort): ",
|
|
1234
|
-
silent: this.silent,
|
|
1235
|
-
});
|
|
1236
|
-
}
|
|
1237
|
-
async handleJsonUpdate(secret) {
|
|
1238
|
-
this.reporter.log("The secret is of type JSON with these expected fields:");
|
|
1239
|
-
for (const field of secret.fields) {
|
|
1240
|
-
const key = typeof field === "string" ? field : field.key;
|
|
1241
|
-
const desc = typeof field === "string"
|
|
1242
|
-
? ""
|
|
1243
|
-
: field.description
|
|
1244
|
-
? ` (${field.description})`
|
|
1245
|
-
: "";
|
|
1246
|
-
this.reporter.log(` - ${key}${desc}`);
|
|
1247
|
-
}
|
|
1248
|
-
this.reporter.log("");
|
|
1249
|
-
// TODO: Ability to specify full json value as one line.
|
|
1250
|
-
const collectedValues = {};
|
|
1251
|
-
for (const field of secret.fields) {
|
|
1252
|
-
const key = typeof field === "string" ? field : field.key;
|
|
1253
|
-
this.reporter.log(`Field: ${this.reporter.format.greenBright(key)}`);
|
|
1254
|
-
if (typeof field !== "string" && field.example != null) {
|
|
1255
|
-
this.reporter.log(`Example: ${this.reporter.format.magentaBright(field.example)}`);
|
|
1256
|
-
}
|
|
1257
|
-
const value = await this.getInput({
|
|
1258
|
-
prompt: "Enter value (Ctrl+C to abort): ",
|
|
1259
|
-
silent: this.silent,
|
|
1260
|
-
});
|
|
1261
|
-
collectedValues[key] = value;
|
|
1262
|
-
this.reporter.log("");
|
|
1263
|
-
}
|
|
1264
|
-
return JSON.stringify(collectedValues, undefined, " ");
|
|
1265
|
-
}
|
|
1266
|
-
getFullName(secretGroup, secret) {
|
|
1267
|
-
return `${secretGroup.namePrefix}${secret.name}`;
|
|
1268
|
-
}
|
|
1269
|
-
async syncTags(client, secret, tags) {
|
|
1270
|
-
const keysToRemove = secret
|
|
1271
|
-
.Tags.filter((existingTag) => !tags.some((it) => it.Key === existingTag.Key))
|
|
1272
|
-
.map((it) => it.Key);
|
|
1273
|
-
if (keysToRemove.length > 0) {
|
|
1274
|
-
this.reporter.log(`Removing obsolete tags: ${keysToRemove.join(", ")}`);
|
|
1275
|
-
await client.send(new clientSecretsManager.UntagResourceCommand({
|
|
1276
|
-
SecretId: secret.ARN,
|
|
1277
|
-
TagKeys: keysToRemove,
|
|
1278
|
-
}));
|
|
1279
|
-
}
|
|
1280
|
-
const tagsToUpdate = tags.filter((expectedTag) => {
|
|
1281
|
-
const existing = secret.Tags.find((it) => it.Key === expectedTag.Key);
|
|
1282
|
-
return existing == null || existing.Value != expectedTag.Value;
|
|
1283
|
-
});
|
|
1284
|
-
if (tagsToUpdate.length > 0) {
|
|
1285
|
-
this.reporter.log(`Storing tags: ${tagsToUpdate.map((it) => it.Key).join(", ")}`);
|
|
1286
|
-
await client.send(new clientSecretsManager.TagResourceCommand({
|
|
1287
|
-
SecretId: secret.ARN,
|
|
1288
|
-
Tags: tagsToUpdate,
|
|
1289
|
-
}));
|
|
1290
|
-
}
|
|
1291
|
-
}
|
|
1292
|
-
async getSecretValue(client, secretId) {
|
|
1293
|
-
const result = await client.send(new clientSecretsManager.GetSecretValueCommand({
|
|
1294
|
-
SecretId: secretId,
|
|
1295
|
-
}));
|
|
1296
|
-
if (result.SecretString == null) {
|
|
1297
|
-
throw new Error("Missing SecretString (is it a binary?)");
|
|
1298
|
-
}
|
|
1299
|
-
return result.SecretString;
|
|
1300
|
-
}
|
|
1301
|
-
async handleUpdate(secretGroup, secret) {
|
|
1302
|
-
var _a, _b, _c, _d, _e;
|
|
1303
|
-
const client = this.getSmClient(secretGroup.region);
|
|
1304
|
-
const fullName = this.getFullName(secretGroup, secret);
|
|
1305
|
-
const describeSecret = await this.getSecretDetails(client, fullName);
|
|
1306
|
-
this.reporter.log(`Secret: ${this.reporter.format.greenBright(fullName)}`);
|
|
1307
|
-
if (describeSecret == null) {
|
|
1308
|
-
this.reporter.log("The secret does not already exist and will be created");
|
|
1309
|
-
}
|
|
1310
|
-
else {
|
|
1311
|
-
this.reporter.log("Current value:");
|
|
1312
|
-
this.reporter.log(this.reporter.format.yellowBright((await this.getSecretValue(client, fullName)).replace(/^/gm, " ")));
|
|
1313
|
-
}
|
|
1314
|
-
this.reporter.log("");
|
|
1315
|
-
let secretValue;
|
|
1316
|
-
if (secret.type === "json") {
|
|
1317
|
-
try {
|
|
1318
|
-
secretValue = await this.handleJsonUpdate(secret);
|
|
1319
|
-
}
|
|
1320
|
-
catch (e) {
|
|
1321
|
-
if (e instanceof Error && e.message === "canceled") {
|
|
1322
|
-
this.reporter.log("Aborted");
|
|
1323
|
-
return;
|
|
1324
|
-
}
|
|
1325
|
-
throw e;
|
|
1326
|
-
}
|
|
1327
|
-
}
|
|
1328
|
-
else if (secret.type === "string") {
|
|
1329
|
-
secretValue = await this.handleStringUpdate();
|
|
1330
|
-
}
|
|
1331
|
-
else {
|
|
1332
|
-
throw new Error(`Unsupported type`);
|
|
1333
|
-
}
|
|
1334
|
-
this.reporter.log("Storing secret value:");
|
|
1335
|
-
this.reporter.log(this.reporter.format.yellowBright(secretValue.replace(/^/gm, " ")));
|
|
1336
|
-
const tags = [
|
|
1337
|
-
{
|
|
1338
|
-
Key: "Source",
|
|
1339
|
-
Value: "load-secrets script",
|
|
1340
|
-
},
|
|
1341
|
-
];
|
|
1342
|
-
let arn;
|
|
1343
|
-
let version;
|
|
1344
|
-
let newReplicaRegions = [];
|
|
1345
|
-
let removedReplicaRegions = [];
|
|
1346
|
-
if (describeSecret == null) {
|
|
1347
|
-
newReplicaRegions = (_a = secret.replicaRegions) !== null && _a !== void 0 ? _a : [];
|
|
1348
|
-
const createResult = await client.send(new clientSecretsManager.CreateSecretCommand({
|
|
1349
|
-
Name: fullName,
|
|
1350
|
-
AddReplicaRegions: secret.replicaRegions
|
|
1351
|
-
? secret.replicaRegions.map((replicaRegion) => ({
|
|
1352
|
-
Region: replicaRegion,
|
|
1353
|
-
}))
|
|
1354
|
-
: undefined,
|
|
1355
|
-
Description: "Created by load-secrets",
|
|
1356
|
-
SecretString: secretValue,
|
|
1357
|
-
Tags: tags,
|
|
1358
|
-
}));
|
|
1359
|
-
if (createResult.VersionId == null) {
|
|
1360
|
-
throw new Error("Expected versionId");
|
|
1361
|
-
}
|
|
1362
|
-
arn = createResult.ARN;
|
|
1363
|
-
version = createResult.VersionId;
|
|
1364
|
-
}
|
|
1365
|
-
else {
|
|
1366
|
-
if (describeSecret.DeletedDate != null) {
|
|
1367
|
-
await client.send(new clientSecretsManager.RestoreSecretCommand({
|
|
1368
|
-
SecretId: fullName,
|
|
1369
|
-
}));
|
|
1370
|
-
}
|
|
1371
|
-
const updateResult = await client.send(new clientSecretsManager.PutSecretValueCommand({
|
|
1372
|
-
SecretId: fullName,
|
|
1373
|
-
SecretString: secretValue,
|
|
1374
|
-
}));
|
|
1375
|
-
const currentReplicaRegions = (_c = (_b = describeSecret.ReplicationStatus) === null || _b === void 0 ? void 0 : _b.map((replicationStatus) => replicationStatus.Region)) !== null && _c !== void 0 ? _c : [];
|
|
1376
|
-
newReplicaRegions =
|
|
1377
|
-
(_e = (_d = secret.replicaRegions) === null || _d === void 0 ? void 0 : _d.filter((region) => !currentReplicaRegions.includes(region))) !== null && _e !== void 0 ? _e : [];
|
|
1378
|
-
removedReplicaRegions = currentReplicaRegions
|
|
1379
|
-
.filter((region) => !!region && typeof region === "string")
|
|
1380
|
-
.filter((region) => !(secret.replicaRegions || []).includes(region));
|
|
1381
|
-
if (newReplicaRegions.length > 0) {
|
|
1382
|
-
await client.send(new clientSecretsManager.ReplicateSecretToRegionsCommand({
|
|
1383
|
-
SecretId: fullName,
|
|
1384
|
-
AddReplicaRegions: newReplicaRegions.map((region) => ({
|
|
1385
|
-
Region: region,
|
|
1386
|
-
})),
|
|
1387
|
-
}));
|
|
1388
|
-
}
|
|
1389
|
-
if (removedReplicaRegions.length > 0) {
|
|
1390
|
-
await client.send(new clientSecretsManager.RemoveRegionsFromReplicationCommand({
|
|
1391
|
-
SecretId: fullName,
|
|
1392
|
-
RemoveReplicaRegions: removedReplicaRegions,
|
|
1393
|
-
}));
|
|
1394
|
-
}
|
|
1395
|
-
if (updateResult.VersionId == null) {
|
|
1396
|
-
throw new Error("Expected versionId");
|
|
1397
|
-
}
|
|
1398
|
-
await this.syncTags(client, describeSecret, tags);
|
|
1399
|
-
arn = updateResult.ARN;
|
|
1400
|
-
version = updateResult.VersionId;
|
|
1401
|
-
}
|
|
1402
|
-
this.reporter.log("");
|
|
1403
|
-
this.reporter.log("Secret stored:");
|
|
1404
|
-
this.reporter.log(`ARN: ${this.reporter.format.greenBright(arn)}`);
|
|
1405
|
-
this.reporter.log(`Version: ${this.reporter.format.greenBright(version)}`);
|
|
1406
|
-
if (newReplicaRegions.length > 0) {
|
|
1407
|
-
this.reporter.log(`Read replicas added to regions: ${newReplicaRegions
|
|
1408
|
-
.map((r) => this.reporter.format.greenBright(r))
|
|
1409
|
-
.join(", ")}`);
|
|
1410
|
-
}
|
|
1411
|
-
if (removedReplicaRegions.length > 0) {
|
|
1412
|
-
this.reporter.log(`Read replicas removed from regions: ${removedReplicaRegions
|
|
1413
|
-
.map((r) => this.reporter.format.redBright(r))
|
|
1414
|
-
.join(", ")}`);
|
|
1415
|
-
}
|
|
1416
|
-
}
|
|
1417
|
-
checkSecretGroup(secretGroup) {
|
|
1418
|
-
if (!secretGroup.namePrefix.startsWith("/") ||
|
|
1419
|
-
!secretGroup.namePrefix.endsWith("/")) {
|
|
1420
|
-
throw new Error(`namePrefix should start and end with /. Current value: ${secretGroup.namePrefix}`);
|
|
1421
|
-
}
|
|
1422
|
-
}
|
|
1423
|
-
getSecretDescription(details) {
|
|
1424
|
-
var _a, _b;
|
|
1425
|
-
return details == null
|
|
1426
|
-
? "not yet created"
|
|
1427
|
-
: (details === null || details === void 0 ? void 0 : details.DeletedDate) != null
|
|
1428
|
-
? `scheduled for deletion ${details.DeletedDate.toISOString()}`
|
|
1429
|
-
: `last changed ${(_b = (_a = details.LastChangedDate) === null || _a === void 0 ? void 0 : _a.toISOString()) !== null && _b !== void 0 ? _b : "unknown"}`;
|
|
1430
|
-
}
|
|
1431
|
-
/**
|
|
1432
|
-
* Returns false if aborted.
|
|
1433
|
-
*/
|
|
1434
|
-
async selectAndUpdate(secretGroups) {
|
|
1435
|
-
const secrets = [];
|
|
1436
|
-
this.reporter.log("Select secret to write:");
|
|
1437
|
-
this.reporter.log("");
|
|
1438
|
-
for (const secretGroup of secretGroups) {
|
|
1439
|
-
this.reporter.log(`${secretGroup.description} (prefix: ${secretGroup.namePrefix})`);
|
|
1440
|
-
for (let i = 0; i < secretGroup.secrets.length; i++) {
|
|
1441
|
-
const offset = secrets.length;
|
|
1442
|
-
const secret = secretGroup.secrets[i];
|
|
1443
|
-
secrets.push({
|
|
1444
|
-
secret: secret,
|
|
1445
|
-
secretGroup,
|
|
1446
|
-
});
|
|
1447
|
-
const client = this.getSmClient(secretGroup.region);
|
|
1448
|
-
const details = await this.getSecretDetails(client, this.getFullName(secretGroup, secret));
|
|
1449
|
-
const desc = this.getSecretDescription(details);
|
|
1450
|
-
this.reporter.log(` (${offset}) ${secret.name} (${desc})`);
|
|
1451
|
-
}
|
|
1452
|
-
this.reporter.log("");
|
|
1453
|
-
}
|
|
1454
|
-
let index;
|
|
1455
|
-
try {
|
|
1456
|
-
const answer = await this.getInput({
|
|
1457
|
-
prompt: "Enter index (or enter to quit): ",
|
|
1458
|
-
});
|
|
1459
|
-
if (answer.trim() === "") {
|
|
1460
|
-
return false;
|
|
1461
|
-
}
|
|
1462
|
-
index = parseInt(answer);
|
|
1463
|
-
if (!secrets[index]) {
|
|
1464
|
-
throw new Error();
|
|
1465
|
-
}
|
|
1466
|
-
}
|
|
1467
|
-
catch (e) {
|
|
1468
|
-
this.reporter.warn("Secret not found - aborting");
|
|
1469
|
-
return false;
|
|
1470
|
-
}
|
|
1471
|
-
this.reporter.log("");
|
|
1472
|
-
await this.handleUpdate(secrets[index].secretGroup, secrets[index].secret);
|
|
1473
|
-
this.reporter.log("");
|
|
1474
|
-
return true;
|
|
1475
|
-
}
|
|
1476
|
-
async process(secretGroups) {
|
|
1477
|
-
this.reporter.info("Checking account for current credentials");
|
|
1478
|
-
this.reporter.info("If any error is given, make sure you have valid credentials active");
|
|
1479
|
-
const currentAccount = await this.stsClient.send(new clientSts.GetCallerIdentityCommand({}));
|
|
1480
|
-
this.reporter.info(`Running for account ${currentAccount.Account}`);
|
|
1481
|
-
this.reporter.log("");
|
|
1482
|
-
const matchedSecretGroups = secretGroups.filter((it) => it.accountId === currentAccount.Account);
|
|
1483
|
-
if (matchedSecretGroups.length === 0) {
|
|
1484
|
-
this.reporter.error(`No secrets specified for this account - aborting`);
|
|
1485
|
-
return;
|
|
1486
|
-
}
|
|
1487
|
-
for (const secretGroup of matchedSecretGroups) {
|
|
1488
|
-
this.checkSecretGroup(secretGroup);
|
|
1489
|
-
}
|
|
1490
|
-
while (await this.selectAndUpdate(matchedSecretGroups)) { }
|
|
1491
|
-
}
|
|
1492
|
-
}
|
|
1493
|
-
/**
|
|
1494
|
-
* Load secrets interactively into Secrets Manager.
|
|
1495
|
-
*/
|
|
1496
|
-
function loadSecretsCli(props) {
|
|
1497
|
-
const loadSecrets = new LoadSecrets({
|
|
1498
|
-
reporter: createReporter({}),
|
|
1499
|
-
// For now we show the secrets, so that we get positive feedback that the value
|
|
1500
|
-
// is correctly entered.
|
|
1501
|
-
silent: false,
|
|
1502
|
-
});
|
|
1503
|
-
loadSecrets.process(props.secretGroups).catch((error) => {
|
|
1504
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
|
1505
|
-
console.error(error.stack || error.message || error);
|
|
1506
|
-
process.exitCode = 1;
|
|
1507
|
-
});
|
|
1508
|
-
}
|
|
1509
|
-
|
|
1510
|
-
var index$2 = /*#__PURE__*/Object.freeze({
|
|
1511
|
-
__proto__: null,
|
|
1512
|
-
loadSecretsCli: loadSecretsCli
|
|
1513
|
-
});
|
|
1514
|
-
|
|
1515
1138
|
class SnykTokenCliProvider {
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
this.keyringAccount = "snyk-token";
|
|
1519
|
-
}
|
|
1139
|
+
keyringService = "cals";
|
|
1140
|
+
keyringAccount = "snyk-token";
|
|
1520
1141
|
async getToken() {
|
|
1521
1142
|
if (process.env.CALS_SNYK_TOKEN) {
|
|
1522
1143
|
return process.env.CALS_SNYK_TOKEN;
|
|
1523
1144
|
}
|
|
1524
|
-
const result = await
|
|
1145
|
+
const result = await keytar.getPassword(this.keyringService, this.keyringAccount);
|
|
1525
1146
|
if (result == null) {
|
|
1526
1147
|
process.stderr.write("No token found. Register using `cals snyk set-token`\n");
|
|
1527
1148
|
return undefined;
|
|
@@ -1529,21 +1150,22 @@ class SnykTokenCliProvider {
|
|
|
1529
1150
|
return result;
|
|
1530
1151
|
}
|
|
1531
1152
|
async markInvalid() {
|
|
1532
|
-
await
|
|
1153
|
+
await keytar.deletePassword(this.keyringService, this.keyringAccount);
|
|
1533
1154
|
}
|
|
1534
1155
|
async setToken(value) {
|
|
1535
|
-
await
|
|
1156
|
+
await keytar.setPassword(this.keyringService, this.keyringAccount, value);
|
|
1536
1157
|
}
|
|
1537
1158
|
}
|
|
1538
1159
|
|
|
1539
1160
|
class SnykService {
|
|
1161
|
+
config;
|
|
1162
|
+
tokenProvider;
|
|
1540
1163
|
constructor(props) {
|
|
1541
1164
|
this.config = props.config;
|
|
1542
1165
|
this.tokenProvider = props.tokenProvider;
|
|
1543
1166
|
}
|
|
1544
1167
|
async getProjects(definition) {
|
|
1545
|
-
|
|
1546
|
-
const snykAccountId = (_a = definition.snyk) === null || _a === void 0 ? void 0 : _a.accountId;
|
|
1168
|
+
const snykAccountId = definition.snyk?.accountId;
|
|
1547
1169
|
if (snykAccountId === undefined) {
|
|
1548
1170
|
return [];
|
|
1549
1171
|
}
|
|
@@ -1571,7 +1193,7 @@ class SnykService {
|
|
|
1571
1193
|
* We continue calling the Snyk API and retrieving more projects until links.next is null
|
|
1572
1194
|
* */
|
|
1573
1195
|
while (nextUrl) {
|
|
1574
|
-
const response = await
|
|
1196
|
+
const response = await fetch(`https://api.snyk.io/rest${nextUrl}`, {
|
|
1575
1197
|
method: "GET",
|
|
1576
1198
|
headers: {
|
|
1577
1199
|
Accept: "application/json",
|
|
@@ -1608,7 +1230,7 @@ class SnykService {
|
|
|
1608
1230
|
totalDependencies: project.meta.latest_dependency_total.total,
|
|
1609
1231
|
issueCountsBySeverity: project.meta.latest_issue_counts,
|
|
1610
1232
|
lastTestedDate: project.meta.latest_dependency_total.updated_at,
|
|
1611
|
-
browseUrl: `https://app.snyk.io/org/${snykOrgSlugId
|
|
1233
|
+
browseUrl: `https://app.snyk.io/org/${snykOrgSlugId ?? "it"}/project/${project.id}`,
|
|
1612
1234
|
};
|
|
1613
1235
|
}),
|
|
1614
1236
|
];
|
|
@@ -1620,10 +1242,9 @@ class SnykService {
|
|
|
1620
1242
|
}
|
|
1621
1243
|
}
|
|
1622
1244
|
function createSnykService(props) {
|
|
1623
|
-
var _a;
|
|
1624
1245
|
return new SnykService({
|
|
1625
1246
|
config: props.config,
|
|
1626
|
-
tokenProvider:
|
|
1247
|
+
tokenProvider: props.tokenProvider ?? new SnykTokenCliProvider(),
|
|
1627
1248
|
});
|
|
1628
1249
|
}
|
|
1629
1250
|
|
|
@@ -1681,6 +1302,8 @@ class SonarCloudTokenCliProvider {
|
|
|
1681
1302
|
}
|
|
1682
1303
|
|
|
1683
1304
|
class SonarCloudService {
|
|
1305
|
+
config;
|
|
1306
|
+
tokenProvider;
|
|
1684
1307
|
constructor(props) {
|
|
1685
1308
|
this.config = props.config;
|
|
1686
1309
|
this.tokenProvider = props.tokenProvider;
|
|
@@ -1694,7 +1317,7 @@ class SonarCloudService {
|
|
|
1694
1317
|
if (token === undefined) {
|
|
1695
1318
|
throw new Error("Missing token for SonarCloud");
|
|
1696
1319
|
}
|
|
1697
|
-
const response = await
|
|
1320
|
+
const response = await fetch(`https://sonarcloud.io/api/measures/component?component=${encodeURIComponent(sonarCloudProjectKey)}&metricKeys=coverage`, {
|
|
1698
1321
|
method: "GET",
|
|
1699
1322
|
headers: {
|
|
1700
1323
|
Accept: "application/json",
|
|
@@ -1717,10 +1340,9 @@ class SonarCloudService {
|
|
|
1717
1340
|
}
|
|
1718
1341
|
}
|
|
1719
1342
|
function createSonarCloudService(props) {
|
|
1720
|
-
var _a;
|
|
1721
1343
|
return new SonarCloudService({
|
|
1722
1344
|
config: props.config,
|
|
1723
|
-
tokenProvider:
|
|
1345
|
+
tokenProvider: props.tokenProvider ?? new SonarCloudTokenCliProvider(),
|
|
1724
1346
|
});
|
|
1725
1347
|
}
|
|
1726
1348
|
|
|
@@ -1732,12 +1354,10 @@ var index = /*#__PURE__*/Object.freeze({
|
|
|
1732
1354
|
});
|
|
1733
1355
|
|
|
1734
1356
|
class TestExecutor {
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
this.tasks = [];
|
|
1740
|
-
}
|
|
1357
|
+
shutdown = false;
|
|
1358
|
+
cleanupTask = null;
|
|
1359
|
+
usingWithCleanupTasks = false;
|
|
1360
|
+
tasks = [];
|
|
1741
1361
|
/**
|
|
1742
1362
|
* Check if we are currently in shutdown state due to user
|
|
1743
1363
|
* asking to abort (Ctrl+C).
|
|
@@ -1784,7 +1404,7 @@ class TestExecutor {
|
|
|
1784
1404
|
*/
|
|
1785
1405
|
async runWithCleanupTasks(body) {
|
|
1786
1406
|
try {
|
|
1787
|
-
|
|
1407
|
+
strict.strictEqual(this.usingWithCleanupTasks, false);
|
|
1788
1408
|
this.usingWithCleanupTasks = true;
|
|
1789
1409
|
// We capture Ctrl+C so that we can perform cleanup task,
|
|
1790
1410
|
// since the cleanup tasks involve async code which is not
|
|
@@ -1855,8 +1475,8 @@ function generateName(extra) {
|
|
|
1855
1475
|
async function createNetwork(executor) {
|
|
1856
1476
|
executor.checkCanContinue();
|
|
1857
1477
|
const networkName = generateName();
|
|
1858
|
-
await
|
|
1859
|
-
const lsRes = await
|
|
1478
|
+
await execa("docker", ["network", "create", networkName]);
|
|
1479
|
+
const lsRes = await execa("docker", [
|
|
1860
1480
|
"network",
|
|
1861
1481
|
"ls",
|
|
1862
1482
|
"-q",
|
|
@@ -1866,7 +1486,7 @@ async function createNetwork(executor) {
|
|
|
1866
1486
|
const networkId = lsRes.stdout.trim();
|
|
1867
1487
|
console.log(`Network ${networkName} (${networkId}) created`);
|
|
1868
1488
|
executor.registerCleanupTask(async () => {
|
|
1869
|
-
await
|
|
1489
|
+
await execa("docker", ["network", "rm", networkId]);
|
|
1870
1490
|
console.log(`Network ${networkName} (${networkId}) deleted`);
|
|
1871
1491
|
});
|
|
1872
1492
|
return {
|
|
@@ -1878,7 +1498,7 @@ async function createNetwork(executor) {
|
|
|
1878
1498
|
*/
|
|
1879
1499
|
async function curl(executor, network, ...args) {
|
|
1880
1500
|
executor.checkCanContinue();
|
|
1881
|
-
const result = await
|
|
1501
|
+
const result = await execa("docker", [
|
|
1882
1502
|
"run",
|
|
1883
1503
|
"-i",
|
|
1884
1504
|
"--rm",
|
|
@@ -1901,9 +1521,9 @@ async function pollForCondition({ container, attempts, waitIntervalSec, conditio
|
|
|
1901
1521
|
}
|
|
1902
1522
|
container.executor.checkCanContinue();
|
|
1903
1523
|
log(`Waiting for condition.. Checking ${attempts} times by ${waitIntervalSec} sec`);
|
|
1904
|
-
const start =
|
|
1524
|
+
const start = performance.now();
|
|
1905
1525
|
const duration = () => {
|
|
1906
|
-
const end =
|
|
1526
|
+
const end = performance.now();
|
|
1907
1527
|
return Math.round((end - start) / 1000);
|
|
1908
1528
|
};
|
|
1909
1529
|
for (let i = 0; i < attempts; i++) {
|
|
@@ -1919,7 +1539,7 @@ async function pollForCondition({ container, attempts, waitIntervalSec, conditio
|
|
|
1919
1539
|
log(`Took ${duration()} seconds for condition`);
|
|
1920
1540
|
return;
|
|
1921
1541
|
}
|
|
1922
|
-
catch
|
|
1542
|
+
catch {
|
|
1923
1543
|
log("Still waiting...");
|
|
1924
1544
|
await new Promise((resolve) => setTimeout(resolve, waitIntervalSec * 1000));
|
|
1925
1545
|
}
|
|
@@ -1943,7 +1563,7 @@ async function waitForPostgresAvailable({ container, attempts = 30, waitInterval
|
|
|
1943
1563
|
attempts,
|
|
1944
1564
|
waitIntervalSec,
|
|
1945
1565
|
condition: async () => {
|
|
1946
|
-
await
|
|
1566
|
+
await execa("docker", [
|
|
1947
1567
|
"exec",
|
|
1948
1568
|
"-e",
|
|
1949
1569
|
`PGPASSWORD=${password}`,
|
|
@@ -1964,10 +1584,10 @@ async function waitForPostgresAvailable({ container, attempts = 30, waitInterval
|
|
|
1964
1584
|
async function isRunning(executor, container) {
|
|
1965
1585
|
executor.checkCanContinue();
|
|
1966
1586
|
try {
|
|
1967
|
-
await
|
|
1587
|
+
await execa("docker", ["inspect", container.name]);
|
|
1968
1588
|
return true;
|
|
1969
1589
|
}
|
|
1970
|
-
catch
|
|
1590
|
+
catch {
|
|
1971
1591
|
return false;
|
|
1972
1592
|
}
|
|
1973
1593
|
}
|
|
@@ -1976,7 +1596,7 @@ async function isRunning(executor, container) {
|
|
|
1976
1596
|
* and also forces every chunk to end with a newline so that
|
|
1977
1597
|
* it can be interleaved with other output.
|
|
1978
1598
|
*/
|
|
1979
|
-
class OutputPrefixTransform extends
|
|
1599
|
+
class OutputPrefixTransform extends Transform {
|
|
1980
1600
|
constructor(prefix) {
|
|
1981
1601
|
super({
|
|
1982
1602
|
objectMode: true,
|
|
@@ -1999,16 +1619,19 @@ class OutputPrefixTransform extends stream.Transform {
|
|
|
1999
1619
|
}
|
|
2000
1620
|
}
|
|
2001
1621
|
function pipeToConsole(result, name) {
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
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);
|
|
2005
1628
|
}
|
|
2006
1629
|
function checkPidRunning(pid) {
|
|
2007
1630
|
try {
|
|
2008
1631
|
process.kill(pid, 0);
|
|
2009
1632
|
return true;
|
|
2010
1633
|
}
|
|
2011
|
-
catch
|
|
1634
|
+
catch {
|
|
2012
1635
|
return false;
|
|
2013
1636
|
}
|
|
2014
1637
|
}
|
|
@@ -2019,14 +1642,14 @@ async function getContainerId({ executor, name, hasFailed, pid, }) {
|
|
|
2019
1642
|
async function check() {
|
|
2020
1643
|
let result;
|
|
2021
1644
|
try {
|
|
2022
|
-
result = (await
|
|
1645
|
+
result = (await execa("docker", ["inspect", name, "-f", "{{.Id}}"]))
|
|
2023
1646
|
.stdout;
|
|
2024
1647
|
}
|
|
2025
|
-
catch
|
|
1648
|
+
catch {
|
|
2026
1649
|
result = null;
|
|
2027
1650
|
}
|
|
2028
1651
|
// Debugging to help us solve CALS-366.
|
|
2029
|
-
const ps =
|
|
1652
|
+
const ps = execa("docker", ["ps"]);
|
|
2030
1653
|
pipeToConsole(ps, `${name} (ps)`);
|
|
2031
1654
|
await ps;
|
|
2032
1655
|
// Debugging to help us solve CALS-366.
|
|
@@ -2059,12 +1682,12 @@ async function getContainerId({ executor, name, hasFailed, pid, }) {
|
|
|
2059
1682
|
}
|
|
2060
1683
|
async function pullImage({ imageId }) {
|
|
2061
1684
|
console.log(`Pulling ${imageId}`);
|
|
2062
|
-
const process =
|
|
1685
|
+
const process = execa("docker", ["pull", imageId]);
|
|
2063
1686
|
pipeToConsole(process, `pull-image (${imageId})`);
|
|
2064
1687
|
await process;
|
|
2065
1688
|
}
|
|
2066
1689
|
async function checkImageExistsLocally({ imageId, }) {
|
|
2067
|
-
const result = await
|
|
1690
|
+
const result = await execa("docker", ["images", "-q", imageId]);
|
|
2068
1691
|
const found = result.stdout != "";
|
|
2069
1692
|
console.log(`image ${imageId} ${found ? "was present locally" : "was not found locally"}`);
|
|
2070
1693
|
return found;
|
|
@@ -2100,8 +1723,8 @@ async function startContainer({ executor, network, imageId, alias, env, dockerAr
|
|
|
2100
1723
|
}
|
|
2101
1724
|
args.push(imageId);
|
|
2102
1725
|
console.log(`Starting ${imageId}`);
|
|
2103
|
-
const process =
|
|
2104
|
-
pipeToConsole(process, alias
|
|
1726
|
+
const process = execa("docker", args);
|
|
1727
|
+
pipeToConsole(process, alias ?? containerName);
|
|
2105
1728
|
let failed = false;
|
|
2106
1729
|
process.catch(() => {
|
|
2107
1730
|
failed = true;
|
|
@@ -2117,8 +1740,8 @@ async function startContainer({ executor, network, imageId, alias, env, dockerAr
|
|
|
2117
1740
|
});
|
|
2118
1741
|
executor.registerCleanupTask(async () => {
|
|
2119
1742
|
console.log(`Stopping container ${containerName}`);
|
|
2120
|
-
const r =
|
|
2121
|
-
pipeToConsole(r, (alias
|
|
1743
|
+
const r = execa("docker", ["stop", containerName]);
|
|
1744
|
+
pipeToConsole(r, (alias ?? containerName) + " (stop)");
|
|
2122
1745
|
try {
|
|
2123
1746
|
await r;
|
|
2124
1747
|
}
|
|
@@ -2138,8 +1761,8 @@ async function startContainer({ executor, network, imageId, alias, env, dockerAr
|
|
|
2138
1761
|
};
|
|
2139
1762
|
}
|
|
2140
1763
|
async function runNpmRunScript(name, options) {
|
|
2141
|
-
const result =
|
|
2142
|
-
env: options
|
|
1764
|
+
const result = execa("npm", ["run", name], {
|
|
1765
|
+
env: options?.env,
|
|
2143
1766
|
});
|
|
2144
1767
|
pipeToConsole(result, `npm run ${name}`);
|
|
2145
1768
|
await result;
|
|
@@ -2151,18 +1774,17 @@ async function getDockerHostAddress() {
|
|
|
2151
1774
|
if (process.platform === "darwin" || process.platform === "win32") {
|
|
2152
1775
|
return "host.docker.internal";
|
|
2153
1776
|
}
|
|
2154
|
-
if (
|
|
2155
|
-
const process =
|
|
1777
|
+
if (fs.existsSync("/.dockerenv")) {
|
|
1778
|
+
const process = execa("ip", ["route"]);
|
|
2156
1779
|
pipeToConsole(process, "ip route");
|
|
2157
1780
|
const res = await process;
|
|
2158
1781
|
try {
|
|
2159
|
-
return
|
|
1782
|
+
return res.stdout
|
|
2160
1783
|
.split("\n")
|
|
2161
1784
|
.filter((it) => it.includes("default via"))
|
|
2162
|
-
|
|
2163
|
-
.map((it) => /default via ([\d\.]+) /.exec(it)[1])[0]);
|
|
1785
|
+
.map((it) => /default via ([\d\.]+) /.exec(it)[1])[0];
|
|
2164
1786
|
}
|
|
2165
|
-
catch
|
|
1787
|
+
catch {
|
|
2166
1788
|
throw new Error("Failed to extract docker host address");
|
|
2167
1789
|
}
|
|
2168
1790
|
}
|
|
@@ -2170,11 +1792,12 @@ async function getDockerHostAddress() {
|
|
|
2170
1792
|
}
|
|
2171
1793
|
async function waitForEnterToContinue(prompt = "Press enter to continue") {
|
|
2172
1794
|
return new Promise((resolve, reject) => {
|
|
2173
|
-
|
|
1795
|
+
read({
|
|
2174
1796
|
prompt,
|
|
2175
1797
|
silent: true,
|
|
2176
1798
|
}, (err) => {
|
|
2177
1799
|
if (err) {
|
|
1800
|
+
// eslint-disable-next-line @typescript-eslint/prefer-promise-reject-errors
|
|
2178
1801
|
reject(err);
|
|
2179
1802
|
}
|
|
2180
1803
|
resolve();
|
|
@@ -2184,28 +1807,5 @@ async function waitForEnterToContinue(prompt = "Press enter to continue") {
|
|
|
2184
1807
|
|
|
2185
1808
|
const VERSION = version;
|
|
2186
1809
|
|
|
2187
|
-
|
|
2188
|
-
exports.Config = Config;
|
|
2189
|
-
exports.DefinitionFile = DefinitionFile;
|
|
2190
|
-
exports.GitHubService = GitHubService;
|
|
2191
|
-
exports.Reporter = Reporter;
|
|
2192
|
-
exports.TestExecutor = TestExecutor;
|
|
2193
|
-
exports.VERSION = VERSION;
|
|
2194
|
-
exports.createGitHubService = createGitHubService;
|
|
2195
|
-
exports.createNetwork = createNetwork;
|
|
2196
|
-
exports.createReporter = createReporter;
|
|
2197
|
-
exports.createTestExecutor = createTestExecutor;
|
|
2198
|
-
exports.curl = curl;
|
|
2199
|
-
exports.definition = index$4;
|
|
2200
|
-
exports.getDockerHostAddress = getDockerHostAddress;
|
|
2201
|
-
exports.github = index$3;
|
|
2202
|
-
exports.loadSecrets = index$2;
|
|
2203
|
-
exports.pollForCondition = pollForCondition;
|
|
2204
|
-
exports.runNpmRunScript = runNpmRunScript;
|
|
2205
|
-
exports.snyk = index$1;
|
|
2206
|
-
exports.sonarCloud = index;
|
|
2207
|
-
exports.startContainer = startContainer;
|
|
2208
|
-
exports.waitForEnterToContinue = waitForEnterToContinue;
|
|
2209
|
-
exports.waitForHttpOk = waitForHttpOk;
|
|
2210
|
-
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 };
|
|
2211
1811
|
//# sourceMappingURL=index.js.map
|