UNPKG

13.5 kBJavaScriptView Raw
1"use strict";
2var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 if (k2 === undefined) k2 = k;
4 Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5}) : (function(o, m, k, k2) {
6 if (k2 === undefined) k2 = k;
7 o[k2] = m[k];
8}));
9var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10 Object.defineProperty(o, "default", { enumerable: true, value: v });
11}) : function(o, v) {
12 o["default"] = v;
13});
14var __importStar = (this && this.__importStar) || function (mod) {
15 if (mod && mod.__esModule) return mod;
16 var result = {};
17 if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18 __setModuleDefault(result, mod);
19 return result;
20};
21var __importDefault = (this && this.__importDefault) || function (mod) {
22 return (mod && mod.__esModule) ? mod : { "default": mod };
23};
24Object.defineProperty(exports, "__esModule", { value: true });
25exports.yarnPublish = exports.mapToArgs = exports.getChangedFiles = exports.gitDiff = exports.getCommitHash = exports.pgrep = exports.dockerPush = exports.dockerBuild = exports.dockerContainerReady = exports.dockerRun = exports.remoteDockerImageExists = exports.dockerNetworkExists = exports.getContainerInfo = exports.dockerTag = exports.dockerStop = exports.dockerPull = exports.runJest = exports.yarnRun = exports.setup = exports.build = exports.runTSScript = exports.fork = exports.exec = void 0;
26const ms_1 = __importDefault(require("ms"));
27const path_1 = __importDefault(require("path"));
28const execa_1 = __importDefault(require("execa"));
29const fs_extra_1 = __importDefault(require("fs-extra"));
30const utils_1 = require("@terascope/utils");
31const misc_1 = require("./misc");
32const signale_1 = __importDefault(require("./signale"));
33const config = __importStar(require("./config"));
34const logger = utils_1.debugLogger('ts-scripts:cmd');
35function _exec(opts) {
36 let subprocess;
37 const options = {
38 cwd: opts.cwd || misc_1.getRootDir(),
39 env: opts.env,
40 preferLocal: true,
41 detached: opts.detached,
42 timeout: opts.timeout,
43 stdio: opts.stdio,
44 };
45 logger.debug('executing command', opts);
46 if (opts.args && opts.args.length) {
47 subprocess = execa_1.default(opts.cmd, opts.args, options);
48 }
49 else {
50 subprocess = execa_1.default(opts.cmd, options);
51 }
52 if (!subprocess) {
53 throw new Error(`Failed to execution ${opts.cmd}`);
54 }
55 if (!opts.stdio) {
56 if (!subprocess.stderr || !subprocess.stdout) {
57 throw new Error(`Command ${opts.cmd} failed, stderr or stdout is not available`);
58 }
59 subprocess.stderr.pipe(process.stderr);
60 }
61 return subprocess;
62}
63async function exec(opts, log = true) {
64 try {
65 const env = { FORCE_COLOR: '0', ...opts.env };
66 const _opts = { ...opts };
67 _opts.env = env;
68 const subprocess = _exec(_opts);
69 const { stdout } = await subprocess;
70 const result = stdout.trim();
71 logger.debug(`exec result: ${opts.cmd} ${(opts.args || []).join(' ')}`, log && result);
72 return result;
73 }
74 catch (err) {
75 if (!err.command) {
76 throw err;
77 }
78 process.exitCode = err.exitCode || 1;
79 throw new Error(err.message);
80 }
81}
82exports.exec = exec;
83async function fork(opts) {
84 try {
85 const env = {
86 FORCE_COLOR: config.FORCE_COLOR,
87 ...opts.env
88 };
89 const _opts = { stdio: 'inherit', ...opts };
90 _opts.env = env;
91 await _exec(_opts);
92 }
93 catch (err) {
94 if (!err.command) {
95 throw err;
96 }
97 process.exitCode = err.exitCode || 1;
98 throw new Error(err.message);
99 }
100}
101exports.fork = fork;
102async function runTSScript(cmd, args) {
103 const scriptName = process.argv[1];
104 return fork({
105 cmd: scriptName,
106 args: [cmd, ...args],
107 });
108}
109exports.runTSScript = runTSScript;
110async function build(pkgInfo) {
111 if (pkgInfo) {
112 const distDir = path_1.default.join(pkgInfo.dir, 'dist');
113 if (fs_extra_1.default.existsSync(distDir)) {
114 await fs_extra_1.default.emptyDir(distDir);
115 }
116 await yarnRun('build', [], pkgInfo.dir);
117 return;
118 }
119 await yarnRun('build');
120}
121exports.build = build;
122async function setup() {
123 await yarnRun('setup');
124}
125exports.setup = setup;
126async function yarnRun(script, args = [], cwd, env, log) {
127 const dir = cwd || misc_1.getRootDir();
128 const pkgJSON = await fs_extra_1.default.readJSON(path_1.default.join(dir, 'package.json'));
129 const hasScript = Boolean(utils_1.get(pkgJSON, ['scripts', script]));
130 if (!hasScript)
131 return;
132 const _args = ['run', script, ...args];
133 if (log) {
134 signale_1.default.info(`running yarn ${_args.join(' ')}...`);
135 }
136 await fork({
137 cmd: 'yarn', args: _args, cwd: dir, env
138 });
139}
140exports.yarnRun = yarnRun;
141async function runJest(cwd, argsMap, env, extraArgs, debug) {
142 const args = mapToArgs(argsMap);
143 if (extraArgs) {
144 extraArgs.forEach((extraArg) => {
145 if (extraArg.startsWith('-') && args.includes(extraArg)) {
146 if (debug) {
147 logger.debug(`* skipping duplicate jest arg ${extraArg}`);
148 }
149 return;
150 }
151 args.push(extraArg);
152 });
153 }
154 if (debug) {
155 signale_1.default.debug(`executing: jest ${args.join(' ')}`);
156 }
157 await fork({
158 cmd: 'jest',
159 cwd,
160 args,
161 env,
162 });
163}
164exports.runJest = runJest;
165async function dockerPull(image, timeout = 0) {
166 try {
167 await exec({
168 cmd: 'docker',
169 args: ['pull', image],
170 timeout,
171 });
172 }
173 catch (err) {
174 process.exitCode = 0;
175 throw err;
176 }
177}
178exports.dockerPull = dockerPull;
179async function dockerStop(name) {
180 await exec({
181 cmd: 'docker',
182 args: ['stop', name],
183 });
184}
185exports.dockerStop = dockerStop;
186async function dockerTag(from, to) {
187 await exec({
188 cmd: 'docker',
189 args: ['tag', from, to],
190 });
191}
192exports.dockerTag = dockerTag;
193async function getContainerInfo(name) {
194 const result = await exec({
195 cmd: 'docker',
196 args: ['ps', '--format={{json .}}', `--filter=name=${name}`],
197 });
198 if (!result)
199 return null;
200 return JSON.parse(result);
201}
202exports.getContainerInfo = getContainerInfo;
203async function dockerNetworkExists(name) {
204 const subprocess = await execa_1.default.command(`docker network ls --format='{{json .Name}}' | grep '"${name}"'`, { reject: false });
205 return subprocess.exitCode > 0;
206}
207exports.dockerNetworkExists = dockerNetworkExists;
208async function remoteDockerImageExists(image) {
209 try {
210 await dockerPull(image, ms_1.default('30s'));
211 return true;
212 }
213 catch (err) {
214 return false;
215 }
216}
217exports.remoteDockerImageExists = remoteDockerImageExists;
218async function dockerRun(opt, tag = 'latest', debug) {
219 const args = ['run', '--rm'];
220 if (!opt.image) {
221 throw new Error('Missing required image option');
222 }
223 if (!opt.name) {
224 throw new Error('Missing required name option');
225 }
226 if (opt.ports && opt.ports.length) {
227 opt.ports.forEach((port) => {
228 if (utils_1.isString(port)) {
229 args.push('--publish', port);
230 }
231 else {
232 args.push('--publish', `${port}:${port}`);
233 }
234 });
235 }
236 if (opt.env) {
237 Object.entries(opt.env).forEach(([key, val]) => {
238 args.push('--env', `${key}=${val}`);
239 });
240 }
241 if (opt.tmpfs && opt.tmpfs.length) {
242 args.push('--tmpfs', opt.tmpfs.join(','));
243 }
244 if (opt.network) {
245 const exists = await dockerNetworkExists(opt.network);
246 if (!exists) {
247 throw new Error(`Docker network ${opt.network} does not exist`);
248 }
249 args.push('--network', opt.network);
250 }
251 args.push('--name', opt.name);
252 args.push(`${opt.image}:${tag}`);
253 let error;
254 let stderr;
255 let done = true;
256 if (debug) {
257 signale_1.default.debug(`executing: docker ${args.join(' ')}`);
258 }
259 const subprocess = execa_1.default('docker', args);
260 if (!subprocess || !subprocess.stderr) {
261 throw new Error('Failed to execute docker run');
262 }
263 (async () => {
264 done = false;
265 try {
266 const result = await subprocess;
267 if (result.exitCode > 0) {
268 stderr = result.all;
269 error = new Error(`${result.command} failed`);
270 }
271 }
272 catch (err) {
273 error = err.stack;
274 stderr = err.all;
275 }
276 finally {
277 done = true;
278 }
279 })();
280 const upFor = ms_1.default('5s');
281 await utils_1.pWhile(() => dockerContainerReady(opt.name, upFor), {
282 timeoutMs: ms_1.default('1m')
283 });
284 if (error) {
285 if (stderr) {
286 process.stderr.write(stderr);
287 }
288 throw error;
289 }
290 if (done) {
291 throw new Error('Service ended early');
292 }
293 return () => {
294 if (error) {
295 if (stderr) {
296 process.stderr.write(stderr);
297 }
298 signale_1.default.error(error);
299 }
300 if (done && !subprocess.killed)
301 return;
302 subprocess.kill();
303 };
304}
305exports.dockerRun = dockerRun;
306async function dockerContainerReady(name, upFor) {
307 try {
308 const result = await exec({
309 cmd: 'docker',
310 args: [
311 'ps', '--format', '"{{json .Status}}"', '--filter', `name=${name}`
312 ]
313 });
314 const timeup = ms_1.default(result.replace(/[(Up)\s"]+|/ig, ''));
315 if (!timeup)
316 return false;
317 return timeup >= upFor;
318 }
319 catch (err) {
320 await utils_1.pDelay(1000);
321 return false;
322 }
323}
324exports.dockerContainerReady = dockerContainerReady;
325async function dockerBuild(tag, cacheFrom = [], target, buildArg) {
326 const cacheFromArgs = [];
327 cacheFrom.forEach((image) => {
328 cacheFromArgs.push('--cache-from', image);
329 });
330 const targetArgs = target ? ['--target', target] : [];
331 const buildsArgs = buildArg ? ['--build-arg', buildArg] : [];
332 await fork({
333 cmd: 'docker',
334 args: ['build', ...cacheFromArgs, ...targetArgs, ...buildsArgs, '--tag', tag, '.'],
335 });
336}
337exports.dockerBuild = dockerBuild;
338async function dockerPush(image) {
339 const subprocess = await execa_1.default.command(`docker push ${image}`, { reject: false });
340 if (subprocess.exitCode !== 0) {
341 throw new Error(`Unable to push docker image ${image}, ${subprocess.stderr}`);
342 }
343}
344exports.dockerPush = dockerPush;
345async function pgrep(name) {
346 const result = await exec({ cmd: 'ps', args: ['aux'] }, false);
347 if (!result) {
348 throw new Error('Invalid result from ps aux');
349 }
350 const found = result.split('\n').find((line) => {
351 if (!line)
352 return false;
353 return line.toLowerCase().includes(name.toLowerCase());
354 });
355 if (found) {
356 logger.trace('found process', found);
357 return found;
358 }
359 return '';
360}
361exports.pgrep = pgrep;
362async function getCommitHash() {
363 if (process.env.GIT_COMMIT_HASH)
364 return process.env.GIT_COMMIT_HASH;
365 return exec({ cmd: 'git', args: ['rev-parse', '--short', 'HEAD'] });
366}
367exports.getCommitHash = getCommitHash;
368async function gitDiff(files = []) {
369 try {
370 await fork({ cmd: 'git', args: ['diff', ...files] });
371 }
372 catch (e) {
373 process.exitCode = 0;
374 logger.warn(e);
375 }
376}
377exports.gitDiff = gitDiff;
378async function getChangedFiles(...files) {
379 try {
380 const result = await exec({
381 cmd: 'git', args: ['diff', '--name-only', ...files]
382 });
383 return result
384 .split('\n')
385 .map((str) => str.trim())
386 .filter(Boolean);
387 }
388 catch (e) {
389 // if there error includes ENOENT
390 // we can just log the error and continue on
391 if (e.toString().includes('ENOENT')) {
392 process.exitCode = 0;
393 logger.warn(e);
394 return [];
395 }
396 throw e;
397 }
398}
399exports.getChangedFiles = getChangedFiles;
400function mapToArgs(input) {
401 const args = [];
402 for (const [key, value] of Object.entries(input)) {
403 const vals = Array.isArray(value) ? value : [value];
404 if (key.length > 1) {
405 args.push(`--${key}`, ...vals);
406 }
407 else {
408 args.push(`-${key}`, ...vals);
409 }
410 }
411 return args.filter((str) => str != null && str !== '');
412}
413exports.mapToArgs = mapToArgs;
414async function yarnPublish(pkgInfo, tag = 'latest', registry = config.NPM_DEFAULT_REGISTRY) {
415 await fork({
416 cmd: 'yarn',
417 args: [
418 'publish',
419 '--non-interactive',
420 '--new-version',
421 pkgInfo.version,
422 '--no-git-tag-version',
423 '--registry',
424 registry,
425 '--tag',
426 tag
427 ],
428 cwd: pkgInfo.dir,
429 env: {
430 NODE_ENV: 'production'
431 }
432 });
433}
434exports.yarnPublish = yarnPublish;
435//# sourceMappingURL=scripts.js.map
\No newline at end of file