build-strap 4.0.0-dev.46 → 4.0.0-dev.5
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/README.md +3 -34
- package/ant.d.ts +19 -0
- package/ant.js +12 -37
- package/cert.d.ts +12 -0
- package/cert.js +89 -151
- package/clean.d.ts +4 -0
- package/clean.js +7 -16
- package/copy.d.ts +7 -0
- package/copy.js +49 -76
- package/cp.d.ts +17 -0
- package/cp.js +85 -170
- package/docker.container.d.ts +73 -0
- package/docker.container.js +219 -362
- package/docker.d.ts +68 -0
- package/docker.js +167 -344
- package/docker.network.d.ts +42 -0
- package/docker.network.js +69 -144
- package/docker.volume.d.ts +26 -0
- package/docker.volume.js +52 -126
- package/dockerCleanup.d.ts +38 -0
- package/dockerCleanup.js +66 -141
- package/dockerCompose.d.ts +154 -0
- package/dockerCompose.js +400 -727
- package/fs.d.ts +5 -0
- package/fs.js +38 -95
- package/git.d.ts +9 -0
- package/git.js +19 -30
- package/index.d.ts +20 -0
- package/index.js +20 -27
- package/maps.d.ts +33 -0
- package/maps.js +16 -87
- package/npm.d.ts +48 -0
- package/npm.js +131 -135
- package/package.json +23 -19
- package/pkg.d.ts +39 -0
- package/pkg.js +26 -74
- package/publish.d.ts +27 -0
- package/publish.js +52 -140
- package/run.d.ts +13 -0
- package/run.js +39 -85
- package/tgz.d.ts +13 -0
- package/tgz.js +61 -96
- package/version.d.ts +34 -0
- package/version.js +86 -128
- package/yarn.d.ts +44 -0
- package/yarn.js +150 -119
- package/ant.js.flow +0 -42
- package/artifactory.js +0 -617
- package/artifactory.js.flow +0 -616
- package/cert.conf +0 -20
- package/cert.js.flow +0 -152
- package/clean.js.flow +0 -19
- package/copy.js.flow +0 -79
- package/cp.js.flow +0 -172
- package/docker.container.js.flow +0 -389
- package/docker.js.flow +0 -364
- package/docker.network.js.flow +0 -159
- package/docker.volume.js.flow +0 -136
- package/dockerCleanup.js.flow +0 -151
- package/dockerCompose.js.flow +0 -765
- package/flow.js +0 -21
- package/flow.js.flow +0 -20
- package/fs.js.flow +0 -96
- package/git.js.flow +0 -34
- package/hg.js +0 -35
- package/hg.js.flow +0 -34
- package/index.js.flow +0 -26
- package/inline-resources.js +0 -158
- package/inline-resources.js.flow +0 -157
- package/maps.js.flow +0 -111
- package/npm.js.flow +0 -144
- package/pkg.js.flow +0 -80
- package/publish.js.flow +0 -144
- package/run.js.flow +0 -89
- package/src/ant.js +0 -42
- package/src/artifactory.js +0 -616
- package/src/cert.conf +0 -20
- package/src/cert.js +0 -152
- package/src/clean.js +0 -19
- package/src/copy.js +0 -79
- package/src/cp.js +0 -172
- package/src/docker.container.js +0 -389
- package/src/docker.js +0 -364
- package/src/docker.network.js +0 -159
- package/src/docker.volume.js +0 -136
- package/src/dockerCleanup.js +0 -151
- package/src/dockerCompose.js +0 -765
- package/src/flow.js +0 -20
- package/src/fs.js +0 -96
- package/src/git.js +0 -34
- package/src/hg.js +0 -34
- package/src/index.js +0 -26
- package/src/inline-resources.js +0 -157
- package/src/maps.js +0 -111
- package/src/npm.js +0 -144
- package/src/pkg.js +0 -80
- package/src/publish.js +0 -144
- package/src/run.js +0 -89
- package/src/test.js +0 -55
- package/src/tgz.js +0 -101
- package/src/version.js +0 -142
- package/src/yarn.js +0 -123
- package/test.js +0 -56
- package/test.js.flow +0 -55
- package/tgz.js.flow +0 -101
- package/version.js.flow +0 -142
- package/yarn.js.flow +0 -123
package/docker.d.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
export interface DockerConfig {
|
|
2
|
+
name?: string;
|
|
3
|
+
registry?: string;
|
|
4
|
+
repository?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function getDockerConfig(): DockerConfig;
|
|
7
|
+
export declare const parseDockerDate: (date: string) => Date;
|
|
8
|
+
export declare function dockerBuild(tags?: string[], buildArgs?: string[], target?: string | null, extraArgs?: string[], repo?: string, dockerFile?: string, workDir?: string): Promise<string>;
|
|
9
|
+
export declare function dockerTag(imageId: string, tags?: string[], repo?: string): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* Apply the standard convention for tagging the docker image for the project,
|
|
12
|
+
* based on the source control branch being built.
|
|
13
|
+
* For releases, applies `latest`, `M.m.p`, `M.m`, `M`
|
|
14
|
+
* For release candidates, applies `latest-rc`
|
|
15
|
+
* For feature branches, applies `latest-feature`
|
|
16
|
+
* For development branch, applies `latest-dev`
|
|
17
|
+
* All other branches, no tag is applies
|
|
18
|
+
* @param {string} imageId id of the docker image to which to apply the tags
|
|
19
|
+
* @param {string} repo optional override of the docker repo url to use (derived from package.json by default)
|
|
20
|
+
*/
|
|
21
|
+
export declare function dockerTagVersion(imageId: string, repo?: string): Promise<void>;
|
|
22
|
+
export interface DockerImage {
|
|
23
|
+
created: Date;
|
|
24
|
+
digest: string;
|
|
25
|
+
id: string;
|
|
26
|
+
repository: string;
|
|
27
|
+
size: number;
|
|
28
|
+
tag: string;
|
|
29
|
+
}
|
|
30
|
+
export declare type DockerImageFilter = (i: DockerImage) => boolean;
|
|
31
|
+
export declare function dockerImages(repo?: null | string, filter?: null | DockerImageFilter): Promise<DockerImage[]>;
|
|
32
|
+
export declare function getDockerId(tag?: string, repo?: null | string): Promise<string>;
|
|
33
|
+
export declare function getUntaggedDockerIds(repo?: string, filter?: null | DockerImageFilter): Promise<string[]>;
|
|
34
|
+
export declare function getDockerTags(id?: null | string, repo?: null | string, fullName?: boolean, filter?: null | DockerImageFilter): Promise<string[]>;
|
|
35
|
+
export declare function getDockerDigest(imageId: string, repo?: string): Promise<string>;
|
|
36
|
+
interface DockerLoginOptions {
|
|
37
|
+
password?: string;
|
|
38
|
+
registry?: string;
|
|
39
|
+
user?: string;
|
|
40
|
+
}
|
|
41
|
+
export declare function dockerLogin({ password, registry, user, }?: DockerLoginOptions): Promise<void>;
|
|
42
|
+
export declare function dockerPush(tags?: string[], repo?: string): Promise<void>;
|
|
43
|
+
export interface DockerPullOptions {
|
|
44
|
+
image: string;
|
|
45
|
+
offline?: boolean;
|
|
46
|
+
testUrl?: string | null;
|
|
47
|
+
}
|
|
48
|
+
export declare function dockerPull({ image, offline, testUrl, }: DockerPullOptions): Promise<void>;
|
|
49
|
+
export declare function dockerRmi(images?: string[], ignoreErrors?: boolean): Promise<void>;
|
|
50
|
+
export declare function getDockerRepo(): string;
|
|
51
|
+
export interface PullAndRunContainerOptions extends DockerPullOptions {
|
|
52
|
+
alias?: string | null;
|
|
53
|
+
cmd?: string[];
|
|
54
|
+
network?: string | null;
|
|
55
|
+
runArgs?: string[];
|
|
56
|
+
}
|
|
57
|
+
export declare function dockerPullAndRunContainer(options: PullAndRunContainerOptions): Promise<string>;
|
|
58
|
+
export interface CopyFilePathConfig {
|
|
59
|
+
from: string;
|
|
60
|
+
to: string;
|
|
61
|
+
}
|
|
62
|
+
export interface CopyFilesFromDockerImageConfig {
|
|
63
|
+
filePaths: CopyFilePathConfig[];
|
|
64
|
+
ignoreErrors?: boolean;
|
|
65
|
+
imageId: string;
|
|
66
|
+
}
|
|
67
|
+
export declare function copyFilesFromDockerImage({ filePaths, ignoreErrors, imageId, }: CopyFilesFromDockerImageConfig): Promise<any>;
|
|
68
|
+
export {};
|
package/docker.js
CHANGED
|
@@ -1,66 +1,35 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
1
|
+
import bytes from 'bytes';
|
|
2
|
+
import isReachable from 'is-reachable';
|
|
3
|
+
import moment from 'moment';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import { spawn } from './cp.js';
|
|
6
|
+
import { dockerContainerKill, dockerContainerRunDaemon, } from './docker.container.js';
|
|
7
|
+
import { dockerNetworkConnect } from './docker.network.js';
|
|
8
|
+
import { getCfg, getPkgName, getPkgScope } from './pkg.js';
|
|
9
|
+
import { buildLog } from './run.js';
|
|
10
|
+
import { getDevBranch, getVersion } from './version.js';
|
|
11
|
+
export function getDockerConfig() {
|
|
12
|
+
return getCfg().docker || {};
|
|
13
|
+
}
|
|
14
|
+
export const parseDockerDate = (date) => moment(date, 'YYYY-MM-DD HH:mm:ss ZZ').toDate();
|
|
15
|
+
export async function dockerBuild(tags = ['latest'], buildArgs = [], target = null, extraArgs = [], repo = getDockerRepo(), dockerFile = './Dockerfile', workDir = '.') {
|
|
16
|
+
const args = [
|
|
17
|
+
'build',
|
|
18
|
+
...['-f', path.resolve(dockerFile)],
|
|
19
|
+
...(target ? ['--target', target] : []),
|
|
20
|
+
...tags.reduce((ar, t) => [...ar, '-t', `${repo}:${t}`], []),
|
|
21
|
+
...buildArgs.reduce((ar, a) => [...ar, '--build-arg', a], []),
|
|
22
|
+
...(extraArgs || []),
|
|
23
|
+
path.resolve(workDir),
|
|
24
|
+
];
|
|
25
|
+
return (await spawn('docker', args, { stdio: 'inherit' })).output;
|
|
26
|
+
}
|
|
27
|
+
export async function dockerTag(imageId, tags = ['latest'], repo = getDockerRepo()) {
|
|
28
|
+
await Promise.all(tags.map(async (t) => {
|
|
29
|
+
await spawn('docker', ['tag', imageId, `${repo}:${t}`]);
|
|
30
|
+
buildLog(`Tagged image ${imageId} as ${repo}:${t}`);
|
|
31
|
+
}));
|
|
24
32
|
}
|
|
25
|
-
|
|
26
|
-
const parseDockerDate = (date) =>
|
|
27
|
-
(0, _moment.default)(date, 'YYYY-MM-DD HH:mm:ss ZZ').toDate();exports.parseDockerDate = parseDockerDate;
|
|
28
|
-
|
|
29
|
-
async function dockerBuild(
|
|
30
|
-
tags = ['latest'],
|
|
31
|
-
buildArgs = [],
|
|
32
|
-
target = null,
|
|
33
|
-
extraArgs = [],
|
|
34
|
-
repo = getDockerRepo(),
|
|
35
|
-
dockerFile = './Dockerfile',
|
|
36
|
-
workDir = '.')
|
|
37
|
-
{
|
|
38
|
-
const args = [
|
|
39
|
-
'build',
|
|
40
|
-
...['-f', _path.default.resolve(dockerFile)],
|
|
41
|
-
...(target ? ['--target', target] : []),
|
|
42
|
-
...tags.reduce((ar, t) => [...ar, '-t', `${repo}:${t}`], []),
|
|
43
|
-
...buildArgs.reduce((ar, a) => [...ar, '--build-arg', a], []),
|
|
44
|
-
...(extraArgs || []),
|
|
45
|
-
_path.default.resolve(workDir)];
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
return (0, _cp.spawn)('docker', args, { stdio: 'inherit' });
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
async function dockerTag(
|
|
52
|
-
imageId,
|
|
53
|
-
tags = ['latest'],
|
|
54
|
-
repo = getDockerRepo())
|
|
55
|
-
{
|
|
56
|
-
await Promise.all(
|
|
57
|
-
tags.map(async (t) => {
|
|
58
|
-
await (0, _cp.spawn)('docker', ['tag', imageId, `${repo}:${t}`]);
|
|
59
|
-
(0, _run.buildLog)(`Tagged image ${imageId} as ${repo}:${t}`);
|
|
60
|
-
}));
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
33
|
/**
|
|
65
34
|
* Apply the standard convention for tagging the docker image for the project,
|
|
66
35
|
* based on the source control branch being built.
|
|
@@ -72,294 +41,148 @@ repo = getDockerRepo())
|
|
|
72
41
|
* @param {string} imageId id of the docker image to which to apply the tags
|
|
73
42
|
* @param {string} repo optional override of the docker repo url to use (derived from package.json by default)
|
|
74
43
|
*/
|
|
75
|
-
async function dockerTagVersion(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
{
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
} else if (branch.match(/^(release|patch)-/)) {
|
|
90
|
-
await dockerTag(imageId, ['latest-rc'], repo);
|
|
91
|
-
} else if (branch.match(/^feature-/)) {
|
|
92
|
-
await dockerTag(imageId, ['latest-feature'], repo);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
async function dockerImages(
|
|
108
|
-
repo = getDockerRepo(),
|
|
109
|
-
filter = null)
|
|
110
|
-
{
|
|
111
|
-
return (
|
|
112
|
-
await (0, _cp.spawn)(
|
|
113
|
-
'docker',
|
|
114
|
-
['images', '--format', `{{json .}}`, ...(repo ? [repo] : [])],
|
|
115
|
-
{ captureOutput: true })).
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
split('\n').
|
|
119
|
-
filter((line) => !!line.trim()).
|
|
120
|
-
map((l) => {
|
|
121
|
-
const {
|
|
122
|
-
Repository: repository,
|
|
123
|
-
Tag: tag,
|
|
124
|
-
ID: id,
|
|
125
|
-
Digest: digest,
|
|
126
|
-
CreatedAt,
|
|
127
|
-
Size } =
|
|
128
|
-
JSON.parse(l.trim());
|
|
129
|
-
return {
|
|
130
|
-
repository,
|
|
131
|
-
tag,
|
|
132
|
-
id,
|
|
133
|
-
digest,
|
|
134
|
-
created: parseDockerDate(CreatedAt),
|
|
135
|
-
size: _bytes.default.parse(Size) };
|
|
136
|
-
|
|
137
|
-
}).
|
|
138
|
-
filter(
|
|
139
|
-
(m) =>
|
|
140
|
-
(m && m.id) != null && (
|
|
141
|
-
typeof filter === 'function' ? filter(m) : true));
|
|
142
|
-
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
async function getDockerId(
|
|
146
|
-
tag = 'latest',
|
|
147
|
-
repo)
|
|
148
|
-
{
|
|
149
|
-
return (await dockerImages(repo, (m) => m.tag === tag)).map((m) => m.id)[0];
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
async function getUntaggedDockerIds(
|
|
153
|
-
repo,
|
|
154
|
-
filter = null)
|
|
155
|
-
{
|
|
156
|
-
return (
|
|
157
|
-
await dockerImages(
|
|
158
|
-
repo,
|
|
159
|
-
(m) =>
|
|
160
|
-
m.tag === '<none>' && (typeof filter === 'function' ? filter(m) : true))).
|
|
161
|
-
|
|
162
|
-
map((m) => m.id);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
async function getDockerTags(
|
|
166
|
-
id,
|
|
167
|
-
repo,
|
|
168
|
-
fullName = false,
|
|
169
|
-
filter = null)
|
|
170
|
-
{
|
|
171
|
-
return (
|
|
172
|
-
await dockerImages(
|
|
173
|
-
repo,
|
|
174
|
-
(m) =>
|
|
175
|
-
(!id || m.id === id) && (
|
|
176
|
-
typeof filter === 'function' ? filter(m) : true))).
|
|
177
|
-
|
|
178
|
-
map((m) => fullName ? `${m.repository}:${m.tag}` : m.tag);
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
async function getDockerDigest(
|
|
182
|
-
imageId,
|
|
183
|
-
repo)
|
|
184
|
-
{
|
|
185
|
-
return (await dockerImages(repo, (m) => m.id === imageId)).map(
|
|
186
|
-
(m) => m.digest)[
|
|
187
|
-
0];
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
async function dockerLogin(
|
|
191
|
-
user,
|
|
192
|
-
password,
|
|
193
|
-
registry)
|
|
194
|
-
{
|
|
195
|
-
const reg = registry || getDockerConfig().registry;
|
|
196
|
-
await (0, _cp.spawn)(
|
|
197
|
-
'docker',
|
|
198
|
-
[
|
|
199
|
-
'login',
|
|
200
|
-
'-u',
|
|
201
|
-
user || process.env.ARTIFACTORY_USER || '',
|
|
202
|
-
'-p',
|
|
203
|
-
password || process.env.ARTIFACTORY_PASSWORD || '',
|
|
204
|
-
...(reg ? [reg] : [])],
|
|
205
|
-
|
|
206
|
-
{ stdio: 'inherit' });
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
async function dockerPush(
|
|
211
|
-
tags = ['latest'],
|
|
212
|
-
repo = getDockerRepo())
|
|
213
|
-
{
|
|
214
|
-
// do this sequentially, so you don't push the same image simultaneously
|
|
215
|
-
await tags.reduce(async (prev, tag) => {
|
|
216
|
-
await prev;
|
|
217
|
-
await (0, _cp.spawn)('docker', ['push', `${repo}:${tag}`], { stdio: 'inherit' });
|
|
218
|
-
}, Promise.resolve());
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
async function dockerPull({
|
|
228
|
-
image,
|
|
229
|
-
offline = process.argv.includes('--offline'),
|
|
230
|
-
testUrl })
|
|
231
|
-
{
|
|
232
|
-
if (offline || !(await (0, _isReachable.default)(testUrl || 'https://hub.docker.com'))) {
|
|
233
|
-
if (offline === false) {
|
|
234
|
-
throw new Error('Offline, cannot docker pull');
|
|
44
|
+
export async function dockerTagVersion(imageId, repo = getDockerRepo()) {
|
|
45
|
+
const { branch, isRelease, major, minor, patch } = await getVersion();
|
|
46
|
+
// determine what tags to apply
|
|
47
|
+
if (isRelease) {
|
|
48
|
+
await dockerTag(imageId, ['latest', `${major}`, `${major}.${minor}`, `${major}.${minor}.${patch}`], repo);
|
|
49
|
+
}
|
|
50
|
+
else if (branch === (await getDevBranch())) {
|
|
51
|
+
await dockerTag(imageId, ['latest-dev'], repo);
|
|
52
|
+
}
|
|
53
|
+
else if (branch.match(/^(release|patch)-/)) {
|
|
54
|
+
await dockerTag(imageId, ['latest-rc'], repo);
|
|
55
|
+
}
|
|
56
|
+
else if (branch.match(/^feature-/)) {
|
|
57
|
+
await dockerTag(imageId, ['latest-feature'], repo);
|
|
235
58
|
}
|
|
236
|
-
(0, _run.buildLog)('It looks like you are offline, skipping docker pull');
|
|
237
|
-
} else {
|
|
238
|
-
// throws on failure
|
|
239
|
-
await (0, _cp.spawn)('docker', ['pull', image], { stdio: 'inherit' });
|
|
240
|
-
}
|
|
241
59
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
{
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
60
|
+
export async function dockerImages(repo = getDockerRepo(), filter = null) {
|
|
61
|
+
return (await spawn('docker', ['images', '--format', `{{json .}}`, ...(repo ? [repo] : [])], { captureOutput: true })).output
|
|
62
|
+
.split('\n')
|
|
63
|
+
.filter((line) => !!line.trim())
|
|
64
|
+
.map((l) => {
|
|
65
|
+
const { CreatedAt, Digest: digest, ID: id, Repository: repository, Size, Tag: tag, } = JSON.parse(l.trim());
|
|
66
|
+
return {
|
|
67
|
+
created: parseDockerDate(CreatedAt),
|
|
68
|
+
digest,
|
|
69
|
+
id,
|
|
70
|
+
repository,
|
|
71
|
+
size: bytes.parse(Size),
|
|
72
|
+
tag,
|
|
73
|
+
};
|
|
74
|
+
})
|
|
75
|
+
.filter((m) => (m && m.id) != null &&
|
|
76
|
+
(typeof filter === 'function' ? filter(m) : true));
|
|
77
|
+
}
|
|
78
|
+
export async function getDockerId(tag = 'latest', repo = null) {
|
|
79
|
+
return (await dockerImages(repo, (m) => m.tag === tag)).map((m) => m.id)[0];
|
|
80
|
+
}
|
|
81
|
+
export async function getUntaggedDockerIds(repo, filter = null) {
|
|
82
|
+
return (await dockerImages(repo, (m) => m.tag === '<none>' && (typeof filter === 'function' ? filter(m) : true))).map((m) => m.id);
|
|
83
|
+
}
|
|
84
|
+
export async function getDockerTags(id, repo, fullName = false, filter = null) {
|
|
85
|
+
return (await dockerImages(repo, (m) => (!id || m.id === id) &&
|
|
86
|
+
(typeof filter === 'function' ? filter(m) : true))).map((m) => (fullName ? `${m.repository}:${m.tag}` : m.tag));
|
|
87
|
+
}
|
|
88
|
+
export async function getDockerDigest(imageId, repo) {
|
|
89
|
+
return (await dockerImages(repo, (m) => m.id === imageId)).map((m) => m.digest)[0];
|
|
90
|
+
}
|
|
91
|
+
export async function dockerLogin({ password = process.env.DOCKER_PASSWORD, registry = process.env.DOCKER_REGISTRY, user = process.env.DOCKER_PASSWORD, } = {}) {
|
|
92
|
+
const reg = registry || getDockerConfig().registry;
|
|
93
|
+
await spawn('docker', ['login', '-u', user || '', '-p', password || '', ...(reg ? [reg] : [])], { stdio: 'inherit' });
|
|
94
|
+
}
|
|
95
|
+
export async function dockerPush(tags = ['latest'], repo = getDockerRepo()) {
|
|
96
|
+
// do this sequentially, so you don't push the same image simultaneously
|
|
97
|
+
await tags.reduce(async (prev, tag) => {
|
|
98
|
+
await prev;
|
|
99
|
+
await spawn('docker', ['push', `${repo}:${tag}`], { stdio: 'inherit' });
|
|
100
|
+
}, Promise.resolve());
|
|
101
|
+
}
|
|
102
|
+
export async function dockerPull({ image, offline = process.argv.includes('--offline'), testUrl, }) {
|
|
103
|
+
if (offline || !(await isReachable(testUrl || 'https://hub.docker.com'))) {
|
|
104
|
+
if (offline === false) {
|
|
105
|
+
throw new Error('Offline, cannot docker pull');
|
|
106
|
+
}
|
|
107
|
+
buildLog('It looks like you are offline, skipping docker pull');
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
// throws on failure
|
|
111
|
+
await spawn('docker', ['pull', image], { stdio: 'inherit' });
|
|
112
|
+
}
|
|
260
113
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
114
|
+
export async function dockerRmi(images = [], ignoreErrors = true) {
|
|
115
|
+
// must do these sequentially, or they will interfere with each other
|
|
116
|
+
await images.reduce(async (prev, image) => {
|
|
117
|
+
await prev;
|
|
118
|
+
await spawn('docker', ['rmi', image], { stdio: 'inherit' }).catch((err) => {
|
|
119
|
+
if (ignoreErrors) {
|
|
120
|
+
buildLog(`Warning (ignored Error): Failed to rm image(s): ${err.message}`);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
throw err;
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
}, Promise.resolve());
|
|
127
|
+
}
|
|
128
|
+
export function getDockerRepo() {
|
|
129
|
+
const { name: dkrName, registry, repository: dkrRepo } = getDockerConfig();
|
|
130
|
+
const repository = dkrRepo || getPkgScope();
|
|
131
|
+
const name = dkrName || getPkgName(false);
|
|
132
|
+
if (!repository || !name) {
|
|
133
|
+
throw new Error('Docker configuration is missing or incomplete in package.json');
|
|
134
|
+
}
|
|
135
|
+
return `${registry ? `${registry}/` : ''}${repository}/${name}`;
|
|
272
136
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
const {
|
|
287
|
-
runArgs = [],
|
|
288
|
-
cmd = [],
|
|
289
|
-
network,
|
|
290
|
-
alias,
|
|
291
|
-
offline = process.argv.includes('--offline'),
|
|
292
|
-
testUrl } =
|
|
293
|
-
options;
|
|
294
|
-
|
|
295
|
-
try {
|
|
296
|
-
await dockerPull({ image, offline, testUrl });
|
|
297
|
-
} catch (err) {
|
|
298
|
-
(0, _run.buildLog)(`docker pull failed (${err.message}), attempting to continue...`);
|
|
299
|
-
}
|
|
300
|
-
const { id } = await (0, _docker.dockerContainerRunDaemon)({ image, runArgs, cmd });
|
|
301
|
-
if (network) {
|
|
302
|
-
await (0, _docker2.dockerNetworkConnect)(network, id, alias);
|
|
303
|
-
}
|
|
304
|
-
return id;
|
|
137
|
+
export async function dockerPullAndRunContainer(options) {
|
|
138
|
+
const { image, runArgs = [], cmd = [], network, alias, offline = process.argv.includes('--offline'), testUrl, } = options;
|
|
139
|
+
try {
|
|
140
|
+
await dockerPull({ image, offline, testUrl });
|
|
141
|
+
}
|
|
142
|
+
catch (err) {
|
|
143
|
+
buildLog(`docker pull failed (${err.message}), attempting to continue...`);
|
|
144
|
+
}
|
|
145
|
+
const { id } = await dockerContainerRunDaemon({ cmd, image, runArgs });
|
|
146
|
+
if (network) {
|
|
147
|
+
await dockerNetworkConnect(network, id, alias);
|
|
148
|
+
}
|
|
149
|
+
return id;
|
|
305
150
|
}
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
async function copyFilesFromDockerImage({
|
|
319
|
-
imageId,
|
|
320
|
-
filePaths,
|
|
321
|
-
ignoreErrors })
|
|
322
|
-
{
|
|
323
|
-
const container = await (0, _docker.dockerContainerRunDaemon)({
|
|
324
|
-
image: imageId,
|
|
325
|
-
runArgs: ['-it', '--rm', '--entrypoint=/bin/bash'],
|
|
326
|
-
cmd: ['read', '-p', 'pause'] });
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
(0, _run.buildLog)(`Copying Files from Docker Image - imageId (${imageId})`);
|
|
330
|
-
|
|
331
|
-
const spawnOptions = {
|
|
332
|
-
stdio: 'inherit',
|
|
333
|
-
pipeOutput: true,
|
|
334
|
-
captureOutput: false };
|
|
335
|
-
|
|
336
|
-
const copyErrors = [];
|
|
337
|
-
|
|
338
|
-
try {
|
|
339
|
-
filePaths.forEach(async (fp) => {
|
|
340
|
-
// Try to copy from the Debug Folder
|
|
341
|
-
try {
|
|
342
|
-
await (0, _cp.spawn)(
|
|
343
|
-
'docker',
|
|
344
|
-
['cp', `${container.id}:${fp.from}`, fp.to],
|
|
345
|
-
spawnOptions);
|
|
346
|
-
|
|
347
|
-
(0, _run.buildLog)(`Copied ${fp.from} => ${fp.to}`);
|
|
348
|
-
} catch (error) {
|
|
349
|
-
copyErrors.push(error);
|
|
350
|
-
(0, _run.buildLog)(`Error copying file ${fp.from}`);
|
|
351
|
-
}
|
|
151
|
+
export async function copyFilesFromDockerImage({ filePaths, ignoreErrors, imageId, }) {
|
|
152
|
+
const container = await dockerContainerRunDaemon({
|
|
153
|
+
cmd: ['read', '-p', 'pause'],
|
|
154
|
+
image: imageId,
|
|
155
|
+
runArgs: ['-it', '--rm', '--entrypoint=/bin/bash'],
|
|
352
156
|
});
|
|
353
|
-
|
|
157
|
+
buildLog(`Copying Files from Docker Image - imageId (${imageId})`);
|
|
158
|
+
const spawnOptions = {
|
|
159
|
+
captureOutput: false,
|
|
160
|
+
pipeOutput: true,
|
|
161
|
+
stdio: 'inherit',
|
|
162
|
+
};
|
|
163
|
+
const copyErrors = [];
|
|
354
164
|
try {
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
165
|
+
filePaths.forEach(async (fp) => {
|
|
166
|
+
// Try to copy from the Debug Folder
|
|
167
|
+
try {
|
|
168
|
+
await spawn('docker', ['cp', `${container.id}:${fp.from}`, fp.to], spawnOptions);
|
|
169
|
+
buildLog(`Copied ${fp.from} => ${fp.to}`);
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
copyErrors.push(error);
|
|
173
|
+
buildLog(`Error copying file ${fp.from}`);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
finally {
|
|
178
|
+
try {
|
|
179
|
+
await dockerContainerKill(container.id);
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
copyErrors.push(error);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
if (copyErrors.length > 0 && ignoreErrors !== true) {
|
|
186
|
+
throw new Error('Some files failed to copy');
|
|
358
187
|
}
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
if (copyErrors.length > 0 && ignoreErrors !== true) {
|
|
362
|
-
throw new Error('Some files failed to copy');
|
|
363
|
-
}
|
|
364
188
|
}
|
|
365
|
-
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9kb2NrZXIuanMiXSwibmFtZXMiOlsiZ2V0RG9ja2VyQ29uZmlnIiwiZG9ja2VyIiwicGFyc2VEb2NrZXJEYXRlIiwiZGF0ZSIsInRvRGF0ZSIsImRvY2tlckJ1aWxkIiwidGFncyIsImJ1aWxkQXJncyIsInRhcmdldCIsImV4dHJhQXJncyIsInJlcG8iLCJnZXREb2NrZXJSZXBvIiwiZG9ja2VyRmlsZSIsIndvcmtEaXIiLCJhcmdzIiwicGF0aCIsInJlc29sdmUiLCJyZWR1Y2UiLCJhciIsInQiLCJhIiwic3RkaW8iLCJkb2NrZXJUYWciLCJpbWFnZUlkIiwiUHJvbWlzZSIsImFsbCIsIm1hcCIsImRvY2tlclRhZ1ZlcnNpb24iLCJpc1JlbGVhc2UiLCJtYWpvciIsIm1pbm9yIiwicGF0Y2giLCJicmFuY2giLCJtYXRjaCIsImRvY2tlckltYWdlcyIsImZpbHRlciIsImNhcHR1cmVPdXRwdXQiLCJzcGxpdCIsImxpbmUiLCJ0cmltIiwibCIsIlJlcG9zaXRvcnkiLCJyZXBvc2l0b3J5IiwiVGFnIiwidGFnIiwiSUQiLCJpZCIsIkRpZ2VzdCIsImRpZ2VzdCIsIkNyZWF0ZWRBdCIsIlNpemUiLCJKU09OIiwicGFyc2UiLCJjcmVhdGVkIiwic2l6ZSIsImJ5dGVzIiwibSIsImdldERvY2tlcklkIiwiZ2V0VW50YWdnZWREb2NrZXJJZHMiLCJnZXREb2NrZXJUYWdzIiwiZnVsbE5hbWUiLCJnZXREb2NrZXJEaWdlc3QiLCJkb2NrZXJMb2dpbiIsInVzZXIiLCJwYXNzd29yZCIsInJlZ2lzdHJ5IiwicmVnIiwicHJvY2VzcyIsImVudiIsIkFSVElGQUNUT1JZX1VTRVIiLCJBUlRJRkFDVE9SWV9QQVNTV09SRCIsImRvY2tlclB1c2giLCJwcmV2IiwiZG9ja2VyUHVsbCIsImltYWdlIiwib2ZmbGluZSIsImFyZ3YiLCJpbmNsdWRlcyIsInRlc3RVcmwiLCJFcnJvciIsImRvY2tlclJtaSIsImltYWdlcyIsImlnbm9yZUVycm9ycyIsImNhdGNoIiwiZXJyIiwibWVzc2FnZSIsImRrclJlcG8iLCJuYW1lIiwiZGtyTmFtZSIsImRvY2tlclB1bGxBbmRSdW5Db250YWluZXIiLCJvcHRpb25zIiwicnVuQXJncyIsImNtZCIsIm5ldHdvcmsiLCJhbGlhcyIsImNvcHlGaWxlc0Zyb21Eb2NrZXJJbWFnZSIsImZpbGVQYXRocyIsImNvbnRhaW5lciIsInNwYXduT3B0aW9ucyIsInBpcGVPdXRwdXQiLCJjb3B5RXJyb3JzIiwiZm9yRWFjaCIsImZwIiwiZnJvbSIsInRvIiwiZXJyb3IiLCJwdXNoIiwibGVuZ3RoIl0sIm1hcHBpbmdzIjoiO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FBSUEsMkM7Ozs7Ozs7O0FBUU8sU0FBU0EsZUFBVCxHQUF5QztBQUM5QyxTQUFPLG1CQUFTQyxNQUFULElBQW1CLEVBQTFCO0FBQ0Q7O0FBRU0sTUFBTUMsZUFBZSxHQUFHLENBQUNDLElBQUQ7QUFDN0IscUJBQU9BLElBQVAsRUFBYSx3QkFBYixFQUF1Q0MsTUFBdkMsRUFESyxDOztBQUdBLGVBQWVDLFdBQWY7QUFDTEMsSUFBYyxHQUFHLENBQUMsUUFBRCxDQURaO0FBRUxDLFNBQW1CLEdBQUcsRUFGakI7QUFHTEMsTUFBZSxHQUFHLElBSGI7QUFJTEMsU0FBdUIsR0FBRyxFQUpyQjtBQUtMQyxJQUFZLEdBQUdDLGFBQWEsRUFMdkI7QUFNTEMsVUFBa0IsR0FBRyxjQU5oQjtBQU9MQyxPQUFlLEdBQUcsR0FQYjtBQVFZO0FBQ2pCLFFBQU1DLElBQUksR0FBRztBQUNYLFNBRFc7QUFFWCxLQUFHLENBQUMsSUFBRCxFQUFPQyxjQUFLQyxPQUFMLENBQWFKLFVBQWIsQ0FBUCxDQUZRO0FBR1gsTUFBSUosTUFBTSxHQUFHLENBQUMsVUFBRCxFQUFhQSxNQUFiLENBQUgsR0FBMEIsRUFBcEMsQ0FIVztBQUlYLEtBQUdGLElBQUksQ0FBQ1csTUFBTCxDQUFZLENBQUNDLEVBQUQsRUFBS0MsQ0FBTCxLQUFXLENBQUMsR0FBR0QsRUFBSixF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LE9BQU8yRCxLQUFQLEVBQWM7QUFDZEwsTUFBQUEsVUFBVSxDQUFDTSxJQUFYLENBQWdCRCxLQUFoQjtBQUNEO0FBQ0Y7O0FBRUQsTUFBSUwsVUFBVSxDQUFDTyxNQUFYLEdBQW9CLENBQXBCLElBQXlCekIsWUFBWSxLQUFLLElBQTlDLEVBQW9EO0FBQ2xELFVBQU0sSUFBSUgsS0FBSixDQUFVLDJCQUFWLENBQU47QUFDRDtBQUNGIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQGZsb3dcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnO1xuaW1wb3J0IGJ5dGVzIGZyb20gJ2J5dGVzJztcbmltcG9ydCBpc1JlYWNoYWJsZSBmcm9tICdpcy1yZWFjaGFibGUnO1xuaW1wb3J0IG1vbWVudCBmcm9tICdtb21lbnQnO1xuaW1wb3J0IHsgYnVpbGRMb2cgfSBmcm9tICcuL3J1bic7XG5pbXBvcnQgeyBnZXRDZmcsIGdldFBrZ05hbWUsIGdldFBrZ1Njb3BlIH0gZnJvbSAnLi9wa2cnO1xuaW1wb3J0IHsgc3Bhd24gfSBmcm9tICcuL2NwJztcbmltcG9ydCB7IGdldFZlcnNpb24sIGdldERldkJyYW5jaCB9IGZyb20gJy4vdmVyc2lvbic7XG5pbXBvcnQge1xuICBkb2NrZXJDb250YWluZXJSdW5EYWVtb24sXG4gIGRvY2tlckNvbnRhaW5lcktpbGwsXG59IGZyb20gJy4vZG9ja2VyLmNvbnRhaW5lcic7XG5pbXBvcnQgeyBkb2NrZXJOZXR3b3JrQ29ubmVjdCB9IGZyb20gJy4vZG9ja2VyLm5ldHdvcmsnO1xuXG5leHBvcnQgdHlwZSBEb2NrZXJDb25maWcgPSB7XG4gIHJlZ2lzdHJ5Pzogc3RyaW5nLFxuICByZXBvc2l0b3J5Pzogc3RyaW5nLFxuICBuYW1lPzogc3RyaW5nLFxufTtcblxuZXhwb3J0IGZ1bmN0aW9uIGdldERvY2tlckNvbmZpZygpOiBEb2NrZXJDb25maWcge1xuICByZXR1cm4gZ2V0Q2ZnKCkuZG9ja2VyIHx8IHt9O1xufVxuXG5leHBvcnQgY29uc3QgcGFyc2VEb2NrZXJEYXRlID0gKGRhdGU6IHN0cmluZyk6IERhdGUgPT5cbiAgbW9tZW50KGRhdGUsICdZWVlZLU1NLUREIEhIOm1tOnNzIFpaJykudG9EYXRlKCk7XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkb2NrZXJCdWlsZChcbiAgdGFnczogc3RyaW5nW10gPSBbJ2xhdGVzdCddLFxuICBidWlsZEFyZ3M6IHN0cmluZ1tdID0gW10sXG4gIHRhcmdldDogP3N0cmluZyA9IG51bGwsXG4gIGV4dHJhQXJncz86ID8oc3RyaW5nW10pID0gW10sXG4gIHJlcG86IHN0cmluZyA9IGdldERvY2tlclJlcG8oKSxcbiAgZG9ja2VyRmlsZTogc3RyaW5nID0gJy4vRG9ja2VyZmlsZScsXG4gIHdvcmtEaXI6IHN0cmluZyA9ICcuJyxcbik6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IGFyZ3MgPSBbXG4gICAgJ2J1aWxkJyxcbiAgICAuLi5bJy1mJywgcGF0aC5yZXNvbHZlKGRvY2tlckZpbGUpXSxcbiAgICAuLi4odGFyZ2V0ID8gWyctLXRhcmdldCcsIHRhcmdldF0gOiBbXSksXG4gICAgLi4udGFncy5yZWR1Y2UoKGFyLCB0KSA9PiBbLi4uYXIsICctdCcsIGAke3JlcG99OiR7dH1gXSwgW10pLFxuICAgIC4uLmJ1aWxkQXJncy5yZWR1Y2UoKGFyLCBhKSA9PiBbLi4uYXIsICctLWJ1aWxkLWFyZycsIGFdLCBbXSksXG4gICAgLi4uKGV4dHJhQXJncyB8fCBbXSksXG4gICAgcGF0aC5yZXNvbHZlKHdvcmtEaXIpLFxuICBdO1xuXG4gIHJldHVybiBzcGF3bignZG9ja2VyJywgYXJncywgeyBzdGRpbzogJ2luaGVyaXQnIH0pO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZG9ja2VyVGFnKFxuICBpbWFnZUlkOiBzdHJpbmcsXG4gIHRhZ3M6IHN0cmluZ1tdID0gWydsYXRlc3QnXSxcbiAgcmVwbz86IHN0cmluZyA9IGdldERvY2tlclJlcG8oKSxcbik6IFByb21pc2U8dm9pZD4ge1xuICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICB0YWdzLm1hcChhc3luYyAodCkgPT4ge1xuICAgICAgYXdhaXQgc3Bhd24oJ2RvY2tlcicsIFsndGFnJywgaW1hZ2VJZCwgYCR7cmVwb306JHt0fWBdKTtcbiAgICAgIGJ1aWxkTG9nKGBUYWdnZWQgaW1hZ2UgJHtpbWFnZUlkfSBhcyAke3JlcG99OiR7dH1gKTtcbiAgICB9KSxcbiAgKTtcbn1cblxuLyoqXG4gKiBBcHBseSB0aGUgc3RhbmRhcmQgY29udmVudGlvbiBmb3IgdGFnZ2luZyB0aGUgZG9ja2VyIGltYWdlIGZvciB0aGUgcHJvamVjdCxcbiAqIGJhc2VkIG9uIHRoZSBzb3VyY2UgY29udHJvbCBicmFuY2ggYmVpbmcgYnVpbHQuXG4gKiBGb3IgcmVsZWFzZXMsIGFwcGxpZXMgYGxhdGVzdGAsIGBNLm0ucGAsIGBNLm1gLCBgTWBcbiAqIEZvciByZWxlYXNlIGNhbmRpZGF0ZXMsIGFwcGxpZXMgYGxhdGVzdC1yY2BcbiAqIEZvciBmZWF0dXJlIGJyYW5jaGVzLCBhcHBsaWVzIGBsYXRlc3QtZmVhdHVyZWBcbiAqIEZvciBkZXZlbG9wbWVudCBicmFuY2gsIGFwcGxpZXMgYGxhdGVzdC1kZXZgXG4gKiBBbGwgb3RoZXIgYnJhbmNoZXMsIG5vIHRhZyBpcyBhcHBsaWVzXG4gKiBAcGFyYW0ge3N0cmluZ30gaW1hZ2VJZCBpZCBvZiB0aGUgZG9ja2VyIGltYWdlIHRvIHdoaWNoIHRvIGFwcGx5IHRoZSB0YWdzXG4gKiBAcGFyYW0ge3N0cmluZ30gcmVwbyBvcHRpb25hbCBvdmVycmlkZSBvZiB0aGUgZG9ja2VyIHJlcG8gdXJsIHRvIHVzZSAoZGVyaXZlZCBmcm9tIHBhY2thZ2UuanNvbiBieSBkZWZhdWx0KVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZG9ja2VyVGFnVmVyc2lvbihcbiAgaW1hZ2VJZDogc3RyaW5nLFxuICByZXBvPzogc3RyaW5nID0gZ2V0RG9ja2VyUmVwbygpLFxuKSB7XG4gIGNvbnN0IHsgaXNSZWxlYXNlLCBtYWpvciwgbWlub3IsIHBhdGNoLCBicmFuY2ggfSA9IGF3YWl0IGdldFZlcnNpb24oKTtcbiAgLy8gZGV0ZXJtaW5lIHdoYXQgdGFncyB0byBhcHBseVxuICBpZiAoaXNSZWxlYXNlKSB7XG4gICAgYXdhaXQgZG9ja2VyVGFnKFxuICAgICAgaW1hZ2VJZCxcbiAgICAgIFsnbGF0ZXN0JywgYCR7bWFqb3J9YCwgYCR7bWFqb3J9LiR7bWlub3J9YCwgYCR7bWFqb3J9LiR7bWlub3J9LiR7cGF0Y2h9YF0sXG4gICAgICByZXBvLFxuICAgICk7XG4gIH0gZWxzZSBpZiAoYnJhbmNoID09PSAoYXdhaXQgZ2V0RGV2QnJhbmNoKCkpKSB7XG4gICAgYXdhaXQgZG9ja2VyVGFnKGltYWdlSWQsIFsnbGF0ZXN0LWRldiddLCByZXBvKTtcbiAgfSBlbHNlIGlmIChicmFuY2gubWF0Y2goL14ocmVsZWFzZXxwYXRjaCktLykpIHtcbiAgICBhd2FpdCBkb2NrZXJUYWcoaW1hZ2VJZCwgWydsYXRlc3QtcmMnXSwgcmVwbyk7XG4gIH0gZWxzZSBpZiAoYnJhbmNoLm1hdGNoKC9eZmVhdHVyZS0vKSkge1xuICAgIGF3YWl0IGRvY2tlclRhZyhpbWFnZUlkLCBbJ2xhdGVzdC1mZWF0dXJlJ10sIHJlcG8pO1xuICB9XG59XG5cbmV4cG9ydCB0eXBlIERvY2tlckltYWdlID0ge1xuICByZXBvc2l0b3J5OiBzdHJpbmcsXG4gIHRhZzogc3RyaW5nLFxuICBpZDogc3RyaW5nLFxuICBkaWdlc3Q6IHN0cmluZyxcbiAgY3JlYXRlZDogRGF0ZSxcbiAgc2l6ZTogbnVtYmVyLFxufTtcblxuZXhwb3J0IHR5cGUgRG9ja2VySW1hZ2VGaWx0ZXIgPSAoaTogRG9ja2VySW1hZ2UpID0+IGJvb2xlYW47XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkb2NrZXJJbWFnZXMoXG4gIHJlcG8/OiA/c3RyaW5nID0gZ2V0RG9ja2VyUmVwbygpLFxuICBmaWx0ZXI/OiA/RG9ja2VySW1hZ2VGaWx0ZXIgPSBudWxsLFxuKTogUHJvbWlzZTxEb2NrZXJJbWFnZVtdPiB7XG4gIHJldHVybiAoXG4gICAgYXdhaXQgc3Bhd24oXG4gICAgICAnZG9ja2VyJyxcbiAgICAgIFsnaW1hZ2VzJywgJy0tZm9ybWF0JywgYHt7anNvbiAufX1gLCAuLi4ocmVwbyA/IFtyZXBvXSA6IFtdKV0sXG4gICAgICB7IGNhcHR1cmVPdXRwdXQ6IHRydWUgfSxcbiAgICApXG4gIClcbiAgICAuc3BsaXQoJ1xcbicpXG4gICAgLmZpbHRlcigobGluZSkgPT4gISFsaW5lLnRyaW0oKSlcbiAgICAubWFwKChsKSA9PiB7XG4gICAgICBjb25zdCB7XG4gICAgICAgIFJlcG9zaXRvcnk6IHJlcG9zaXRvcnksXG4gICAgICAgIFRhZzogdGFnLFxuICAgICAgICBJRDogaWQsXG4gICAgICAgIERpZ2VzdDogZGlnZXN0LFxuICAgICAgICBDcmVhdGVkQXQsXG4gICAgICAgIFNpemUsXG4gICAgICB9ID0gSlNPTi5wYXJzZShsLnRyaW0oKSk7XG4gICAgICByZXR1cm4ge1xuICAgICAgICByZXBvc2l0b3J5LFxuICAgICAgICB0YWcsXG4gICAgICAgIGlkLFxuICAgICAgICBkaWdlc3QsXG4gICAgICAgIGNyZWF0ZWQ6IHBhcnNlRG9ja2VyRGF0ZShDcmVhdGVkQXQpLFxuICAgICAgICBzaXplOiBieXRlcy5wYXJzZShTaXplKSxcbiAgICAgIH07XG4gICAgfSlcbiAgICAuZmlsdGVyKFxuICAgICAgKG0pID0+XG4gICAgICAgIChtICYmIG0uaWQpICE9IG51bGwgJiZcbiAgICAgICAgKHR5cGVvZiBmaWx0ZXIgPT09ICdmdW5jdGlvbicgPyBmaWx0ZXIobSkgOiB0cnVlKSxcbiAgICApO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0RG9ja2VySWQoXG4gIHRhZzogc3RyaW5nID0gJ2xhdGVzdCcsXG4gIHJlcG8/OiA/c3RyaW5nLFxuKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgcmV0dXJuIChhd2FpdCBkb2NrZXJJbWFnZXMocmVwbywgKG0pID0+IG0udGFnID09PSB0YWcpKS5tYXAoKG0pID0+IG0uaWQpWzBdO1xufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0VW50YWdnZWREb2NrZXJJZHMoXG4gIHJlcG8/OiA/c3RyaW5nLFxuICBmaWx0ZXI/OiA/RG9ja2VySW1hZ2VGaWx0ZXIgPSBudWxsLFxuKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICByZXR1cm4gKFxuICAgIGF3YWl0IGRvY2tlckltYWdlcyhcbiAgICAgIHJlcG8sXG4gICAgICAobSkgPT5cbiAgICAgICAgbS50YWcgPT09ICc8bm9uZT4nICYmICh0eXBlb2YgZmlsdGVyID09PSAnZnVuY3Rpb24nID8gZmlsdGVyKG0pIDogdHJ1ZSksXG4gICAgKVxuICApLm1hcCgobSkgPT4gbS5pZCk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXREb2NrZXJUYWdzKFxuICBpZD86ID9zdHJpbmcsXG4gIHJlcG8/OiA/c3RyaW5nLFxuICBmdWxsTmFtZTogYm9vbGVhbiA9IGZhbHNlLFxuICBmaWx0ZXI/OiA/RG9ja2VySW1hZ2VGaWx0ZXIgPSBudWxsLFxuKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICByZXR1cm4gKFxuICAgIGF3YWl0IGRvY2tlckltYWdlcyhcbiAgICAgIHJlcG8sXG4gICAgICAobSkgPT5cbiAgICAgICAgKCFpZCB8fCBtLmlkID09PSBpZCkgJiZcbiAgICAgICAgKHR5cGVvZiBmaWx0ZXIgPT09ICdmdW5jdGlvbicgPyBmaWx0ZXIobSkgOiB0cnVlKSxcbiAgICApXG4gICkubWFwKChtKSA9PiAoZnVsbE5hbWUgPyBgJHttLnJlcG9zaXRvcnl9OiR7bS50YWd9YCA6IG0udGFnKSk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXREb2NrZXJEaWdlc3QoXG4gIGltYWdlSWQ6IHN0cmluZyxcbiAgcmVwbz86IHN0cmluZyxcbik6IFByb21pc2U8c3RyaW5nPiB7XG4gIHJldHVybiAoYXdhaXQgZG9ja2VySW1hZ2VzKHJlcG8sIChtKSA9PiBtLmlkID09PSBpbWFnZUlkKSkubWFwKFxuICAgIChtKSA9PiBtLmRpZ2VzdCxcbiAgKVswXTtcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRvY2tlckxvZ2luKFxuICB1c2VyOiBzdHJpbmcsXG4gIHBhc3N3b3JkOiBzdHJpbmcsXG4gIHJlZ2lzdHJ5OiBzdHJpbmcsXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgcmVnID0gcmVnaXN0cnkgfHwgZ2V0RG9ja2VyQ29uZmlnKCkucmVnaXN0cnk7XG4gIGF3YWl0IHNwYXduKFxuICAgICdkb2NrZXInLFxuICAgIFtcbiAgICAgICdsb2dpbicsXG4gICAgICAnLXUnLFxuICAgICAgdXNlciB8fCBwcm9jZXNzLmVudi5BUlRJRkFDVE9SWV9VU0VSIHx8ICcnLFxuICAgICAgJy1wJyxcbiAgICAgIHBhc3N3b3JkIHx8IHByb2Nlc3MuZW52LkFSVElGQUNUT1JZX1BBU1NXT1JEIHx8ICcnLFxuICAgICAgLi4uKHJlZyA/IFtyZWddIDogW10pLFxuICAgIF0sXG4gICAgeyBzdGRpbzogJ2luaGVyaXQnIH0sXG4gICk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkb2NrZXJQdXNoKFxuICB0YWdzPzogc3RyaW5nW10gPSBbJ2xhdGVzdCddLFxuICByZXBvPzogc3RyaW5nID0gZ2V0RG9ja2VyUmVwbygpLFxuKSB7XG4gIC8vIGRvIHRoaXMgc2VxdWVudGlhbGx5LCBzbyB5b3UgZG9uJ3QgcHVzaCB0aGUgc2FtZSBpbWFnZSBzaW11bHRhbmVvdXNseVxuICBhd2FpdCB0YWdzLnJlZHVjZShhc3luYyAocHJldiwgdGFnKSA9PiB7XG4gICAgYXdhaXQgcHJldjtcbiAgICBhd2FpdCBzcGF3bignZG9ja2VyJywgWydwdXNoJywgYCR7cmVwb306JHt0YWd9YF0sIHsgc3RkaW86ICdpbmhlcml0JyB9KTtcbiAgfSwgUHJvbWlzZS5yZXNvbHZlKCkpO1xufVxuXG5leHBvcnQgdHlwZSBEb2NrZXJQdWxsT3B0aW9ucyA9IHtcbiAgaW1hZ2U6IHN0cmluZyxcbiAgb2ZmbGluZT86IGJvb2xlYW4sXG4gIHRlc3RVcmw/OiA/c3RyaW5nLFxufTtcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRvY2tlclB1bGwoe1xuICBpbWFnZSxcbiAgb2ZmbGluZSA9IHByb2Nlc3MuYXJndi5pbmNsdWRlcygnLS1vZmZsaW5lJyksXG4gIHRlc3RVcmwsXG59OiBEb2NrZXJQdWxsT3B0aW9ucykge1xuICBpZiAob2ZmbGluZSB8fCAhKGF3YWl0IGlzUmVhY2hhYmxlKHRlc3RVcmwgfHwgJ2h0dHBzOi8vaHViLmRvY2tlci5jb20nKSkpIHtcbiAgICBpZiAob2ZmbGluZSA9PT0gZmFsc2UpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignT2ZmbGluZSwgY2Fubm90IGRvY2tlciBwdWxsJyk7XG4gICAgfVxuICAgIGJ1aWxkTG9nKCdJdCBsb29rcyBsaWtlIHlvdSBhcmUgb2ZmbGluZSwgc2tpcHBpbmcgZG9ja2VyIHB1bGwnKTtcbiAgfSBlbHNlIHtcbiAgICAvLyB0aHJvd3Mgb24gZmFpbHVyZVxuICAgIGF3YWl0IHNwYXduKCdkb2NrZXInLCBbJ3B1bGwnLCBpbWFnZV0sIHsgc3RkaW86ICdpbmhlcml0JyB9KTtcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZG9ja2VyUm1pKFxuICBpbWFnZXM6IHN0cmluZ1tdID0gW10sXG4gIGlnbm9yZUVycm9yczogYm9vbGVhbiA9IHRydWUsXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgLy8gbXVzdCBkbyB0aGVzZSBzZXF1ZW50aWFsbHksIG9yIHRoZXkgd2lsbCBpbnRlcmZlcmUgd2l0aCBlYWNoIG90aGVyXG4gIGF3YWl0IGltYWdlcy5yZWR1Y2UoYXN5bmMgKHByZXYsIGltYWdlKSA9PiB7XG4gICAgYXdhaXQgcHJldjtcbiAgICBhd2FpdCBzcGF3bignZG9ja2VyJywgWydybWknLCBpbWFnZV0sIHsgc3RkaW86ICdpbmhlcml0JyB9KS5jYXRjaCgoZXJyKSA9PiB7XG4gICAgICBpZiAoaWdub3JlRXJyb3JzKSB7XG4gICAgICAgIGJ1aWxkTG9nKFxuICAgICAgICAgIGBXYXJuaW5nIChpZ25vcmVkIEVycm9yKTogRmFpbGVkIHRvIHJtIGltYWdlKHMpOiAke2Vyci5tZXNzYWdlfWAsXG4gICAgICAgICk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9XG4gICAgfSk7XG4gIH0sIFByb21pc2UucmVzb2x2ZSgpKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldERvY2tlclJlcG8oKTogc3RyaW5nIHtcbiAgY29uc3QgeyByZWdpc3RyeSwgcmVwb3NpdG9yeTogZGtyUmVwbywgbmFtZTogZGtyTmFtZSB9ID0gZ2V0RG9ja2VyQ29uZmlnKCk7XG4gIGNvbnN0IHJlcG9zaXRvcnkgPSBka3JSZXBvIHx8IGdldFBrZ1Njb3BlKCk7XG4gIGNvbnN0IG5hbWUgPSBka3JOYW1lIHx8IGdldFBrZ05hbWUoZmFsc2UpO1xuICBpZiAoIXJlcG9zaXRvcnkgfHwgIW5hbWUpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAnRG9ja2VyIGNvbmZpZ3VyYXRpb24gaXMgbWlzc2luZyBvciBpbmNvbXBsZXRlIGluIHBhY2thZ2UuanNvbicsXG4gICAgKTtcbiAgfVxuICByZXR1cm4gYCR7cmVnaXN0cnkgPyBgJHtyZWdpc3RyeX0vYCA6ICcnfSR7cmVwb3NpdG9yeX0vJHtuYW1lfWA7XG59XG5cbmV4cG9ydCB0eXBlIFB1bGxBbmRSdW5Db250YWluZXJPcHRpb25zID0ge1xuICAuLi5Eb2NrZXJQdWxsT3B0aW9ucyxcbiAgcnVuQXJncz86IHN0cmluZ1tdLFxuICBjbWQ/OiBzdHJpbmdbXSxcbiAgbmV0d29yaz86ID9zdHJpbmcsXG4gIGFsaWFzPzogP3N0cmluZyxcbn07XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkb2NrZXJQdWxsQW5kUnVuQ29udGFpbmVyKFxuICBpbWFnZTogc3RyaW5nLFxuICBvcHRpb25zOiBQdWxsQW5kUnVuQ29udGFpbmVyT3B0aW9ucyA9IHt9LFxuKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgY29uc3Qge1xuICAgIHJ1bkFyZ3MgPSBbXSxcbiAgICBjbWQgPSBbXSxcbiAgICBuZXR3b3JrLFxuICAgIGFsaWFzLFxuICAgIG9mZmxpbmUgPSBwcm9jZXNzLmFyZ3YuaW5jbHVkZXMoJy0tb2ZmbGluZScpLFxuICAgIHRlc3RVcmwsXG4gIH0gPSBvcHRpb25zO1xuXG4gIHRyeSB7XG4gICAgYXdhaXQgZG9ja2VyUHVsbCh7IGltYWdlLCBvZmZsaW5lLCB0ZXN0VXJsIH0pO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBidWlsZExvZyhgZG9ja2VyIHB1bGwgZmFpbGVkICgke2Vyci5tZXNzYWdlfSksIGF0dGVtcHRpbmcgdG8gY29udGludWUuLi5gKTtcbiAgfVxuICBjb25zdCB7IGlkIH0gPSBhd2FpdCBkb2NrZXJDb250YWluZXJSdW5EYWVtb24oeyBpbWFnZSwgcnVuQXJncywgY21kIH0pO1xuICBpZiAobmV0d29yaykge1xuICAgIGF3YWl0IGRvY2tlck5ldHdvcmtDb25uZWN0KG5ldHdvcmssIGlkLCBhbGlhcyk7XG4gIH1cbiAgcmV0dXJuIGlkO1xufVxuXG5leHBvcnQgdHlwZSBDb3B5RmlsZVBhdGhDb25maWcgPSB7XG4gIGZyb206IHN0cmluZyxcbiAgdG86IHN0cmluZyxcbn07XG5cbmV4cG9ydCB0eXBlIENvcHlGaWxlc0Zyb21Eb2NrZXJJbWFnZUNvbmZpZyA9IHtcbiAgaW1hZ2VJZDogc3RyaW5nLFxuICBmaWxlUGF0aHM6IENvcHlGaWxlUGF0aENvbmZpZ1tdLFxuICBpZ25vcmVFcnJvcnM/OiA/Ym9vbGVhbixcbn07XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjb3B5RmlsZXNGcm9tRG9ja2VySW1hZ2Uoe1xuICBpbWFnZUlkLFxuICBmaWxlUGF0aHMsXG4gIGlnbm9yZUVycm9ycyxcbn06IENvcHlGaWxlc0Zyb21Eb2NrZXJJbWFnZUNvbmZpZyk6IFByb21pc2U8YW55PiB7XG4gIGNvbnN0IGNvbnRhaW5lciA9IGF3YWl0IGRvY2tlckNvbnRhaW5lclJ1bkRhZW1vbih7XG4gICAgaW1hZ2U6IGltYWdlSWQsXG4gICAgcnVuQXJnczogWyctaXQnLCAnLS1ybScsICctLWVudHJ5cG9pbnQ9L2Jpbi9iYXNoJ10sXG4gICAgY21kOiBbJ3JlYWQnLCAnLXAnLCAncGF1c2UnXSxcbiAgfSk7XG5cbiAgYnVpbGRMb2coYENvcHlpbmcgRmlsZXMgZnJvbSBEb2NrZXIgSW1hZ2UgLSBpbWFnZUlkICgke2ltYWdlSWR9KWApO1xuXG4gIGNvbnN0IHNwYXduT3B0aW9ucyA9IHtcbiAgICBzdGRpbzogJ2luaGVyaXQnLFxuICAgIHBpcGVPdXRwdXQ6IHRydWUsXG4gICAgY2FwdHVyZU91dHB1dDogZmFsc2UsXG4gIH07XG4gIGNvbnN0IGNvcHlFcnJvcnMgPSBbXTtcblxuICB0cnkge1xuICAgIGZpbGVQYXRocy5mb3JFYWNoKGFzeW5jIChmcCkgPT4ge1xuICAgICAgLy8gVHJ5IHRvIGNvcHkgZnJvbSB0aGUgRGVidWcgRm9sZGVyXG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBzcGF3bihcbiAgICAgICAgICAnZG9ja2VyJyxcbiAgICAgICAgICBbJ2NwJywgYCR7Y29udGFpbmVyLmlkfToke2ZwLmZyb219YCwgZnAudG9dLFxuICAgICAgICAgIHNwYXduT3B0aW9ucyxcbiAgICAgICAgKTtcbiAgICAgICAgYnVpbGRMb2coYENvcGllZCAke2ZwLmZyb219ID0+ICR7ZnAudG99YCk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBjb3B5RXJyb3JzLnB1c2goZXJyb3IpO1xuICAgICAgICBidWlsZExvZyhgRXJyb3IgY29weWluZyBmaWxlICR7ZnAuZnJvbX1gKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSBmaW5hbGx5IHtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgZG9ja2VyQ29udGFpbmVyS2lsbChjb250YWluZXIuaWQpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb3B5RXJyb3JzLnB1c2goZXJyb3IpO1xuICAgIH1cbiAgfVxuXG4gIGlmIChjb3B5RXJyb3JzLmxlbmd0aCA+IDAgJiYgaWdub3JlRXJyb3JzICE9PSB0cnVlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdTb21lIGZpbGVzIGZhaWxlZCB0byBjb3B5Jyk7XG4gIH1cbn1cbiJdfQ==
|