bdy 1.18.24-dev → 1.18.24-dev-pipeline
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/distTs/package.json +1 -1
- package/distTs/src/api/client.js +9 -2
- package/distTs/src/command/crawl/validation.js +151 -0
- package/distTs/src/command/crawl.js +144 -0
- package/distTs/src/command/pipeline/run/start.js +101 -0
- package/distTs/src/command/pipeline/run/status.js +34 -0
- package/distTs/src/command/pipeline/run.js +7 -125
- package/distTs/src/command/project/link.js +11 -11
- package/distTs/src/command/tests/capture/validation.js +59 -0
- package/distTs/src/command/tests/capture.js +100 -0
- package/distTs/src/command/tests/unit/upload.js +86 -0
- package/distTs/src/command/tests/unit.js +11 -0
- package/distTs/src/command/tests/visual/session/close.js +27 -0
- package/distTs/src/command/tests/visual/session/create.js +82 -0
- package/distTs/src/command/tests/visual/session.js +13 -0
- package/distTs/src/command/tests/visual/setup.js +20 -0
- package/distTs/src/command/tests/visual/shared/validation.js +118 -0
- package/distTs/src/command/tests/visual/upload.js +138 -0
- package/distTs/src/command/tests/visual.js +15 -0
- package/distTs/src/command/tests.js +15 -0
- package/distTs/src/input.js +6 -10
- package/distTs/src/output/pipeline.js +915 -0
- package/distTs/src/output.js +81 -31
- package/distTs/src/texts.js +28 -36
- package/distTs/src/types/crawl.js +2 -0
- package/distTs/src/types/pipeline.js +424 -0
- package/package.json +1 -1
- package/distTs/src/command/project/get.js +0 -18
- package/distTs/src/command/project/set.js +0 -31
- package/distTs/src/command/sandbox/get/yaml.js +0 -30
- package/distTs/src/command/vt/scrape.js +0 -193
package/distTs/package.json
CHANGED
package/distTs/src/api/client.js
CHANGED
|
@@ -216,6 +216,13 @@ class ApiClient {
|
|
|
216
216
|
throw new Error(texts_1.ERR_REST_API_GENERAL_ERROR);
|
|
217
217
|
}
|
|
218
218
|
}
|
|
219
|
+
async getPipelineRunActionExecution(workspace, project, pipelineId, executionId, actionExecutionId) {
|
|
220
|
+
return await this.request({
|
|
221
|
+
method: 'GET',
|
|
222
|
+
path: `/workspaces/${encodeURIComponent(workspace)}/projects/${encodeURIComponent(project)}/pipelines/${encodeURIComponent(pipelineId)}/executions/${encodeURIComponent(executionId)}/action_executions/${encodeURIComponent(actionExecutionId)}`,
|
|
223
|
+
parseResponseBody: true,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
219
226
|
async getPipelineRun(workspace, project, pipelineId, executionId) {
|
|
220
227
|
return await this.request({
|
|
221
228
|
method: 'GET',
|
|
@@ -721,14 +728,14 @@ class ApiClient {
|
|
|
721
728
|
return await this.request({
|
|
722
729
|
method: 'POST',
|
|
723
730
|
path: `/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}/apps/${encodeURIComponent(appId)}/stop`,
|
|
724
|
-
parseResponseBody: true
|
|
731
|
+
parseResponseBody: true,
|
|
725
732
|
});
|
|
726
733
|
}
|
|
727
734
|
async startSandboxApp(workspace, sandboxId, appId) {
|
|
728
735
|
return await this.request({
|
|
729
736
|
method: 'POST',
|
|
730
737
|
path: `/workspaces/${encodeURIComponent(workspace)}/sandboxes/${encodeURIComponent(sandboxId)}/apps/${encodeURIComponent(appId)}/start`,
|
|
731
|
-
parseResponseBody: true
|
|
738
|
+
parseResponseBody: true,
|
|
732
739
|
});
|
|
733
740
|
}
|
|
734
741
|
async getSandboxAppLogs(workspace, sandboxId, appId, cursor) {
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.validateInputAndOptions = validateInputAndOptions;
|
|
7
|
+
const zod_1 = require("zod");
|
|
8
|
+
const output_1 = __importDefault(require("../../output"));
|
|
9
|
+
const validation_1 = require("../tests/visual/shared/validation");
|
|
10
|
+
const urlSchema = zod_1.z.string().url().optional();
|
|
11
|
+
const browserSchema = zod_1.z.enum(['chrome', 'firefox', 'safari']);
|
|
12
|
+
const browsersListSchema = zod_1.z
|
|
13
|
+
.string()
|
|
14
|
+
.transform((value) => value
|
|
15
|
+
.split(',')
|
|
16
|
+
.map((browser) => browser.trim().toLowerCase())
|
|
17
|
+
.filter((browser) => browser.length > 0))
|
|
18
|
+
.refine((browsers) => browsers.length > 0, {
|
|
19
|
+
message: 'Invalid browsers list. Supported values: chrome,firefox,safari',
|
|
20
|
+
})
|
|
21
|
+
.pipe(zod_1.z.array(browserSchema))
|
|
22
|
+
.transform((browsers) => Array.from(new Set(browsers.map((browser) => browser === 'chrome'
|
|
23
|
+
? 'CHROMIUM'
|
|
24
|
+
: browser === 'firefox'
|
|
25
|
+
? 'FIREFOX'
|
|
26
|
+
: 'WEBKIT'))));
|
|
27
|
+
const optionsSchema = zod_1.z.object({
|
|
28
|
+
follow: zod_1.z.boolean(),
|
|
29
|
+
respectRobots: zod_1.z.boolean(),
|
|
30
|
+
outputType: zod_1.z.enum(['jpeg', 'png', 'md', 'html']).optional(),
|
|
31
|
+
outputTypes: zod_1.z.string().optional(),
|
|
32
|
+
quality: zod_1.z.coerce.number().min(1).max(100).optional(),
|
|
33
|
+
outputDir: zod_1.z.string().default('.'),
|
|
34
|
+
fullPage: zod_1.z.boolean().optional(),
|
|
35
|
+
cssSelector: zod_1.z.string().optional(),
|
|
36
|
+
xpathSelector: zod_1.z.string().optional(),
|
|
37
|
+
colorScheme: zod_1.z.enum(['LIGHT', 'DARK', 'LIGHT_AND_DARK']).optional(),
|
|
38
|
+
browsers: browsersListSchema.optional(),
|
|
39
|
+
devices: zod_1.z.string().optional(),
|
|
40
|
+
delay: zod_1.z.coerce.number().min(0).max(10000),
|
|
41
|
+
waitFor: validation_1.waitForSchema,
|
|
42
|
+
cookie: validation_1.cookieSchema,
|
|
43
|
+
header: validation_1.headerSchema,
|
|
44
|
+
localStorage: zod_1.z
|
|
45
|
+
.array(zod_1.z.string().regex(/^(?:([^:]+)::)?([^=]+)=(.*)$/, {
|
|
46
|
+
message: "LocalStorage option must follow pattern '[scope::]key=value' (scope is optional)",
|
|
47
|
+
}))
|
|
48
|
+
.optional()
|
|
49
|
+
.transform((value) => value?.map((v) => {
|
|
50
|
+
const { scope, key, value } = (0, validation_1.parseScopedKeyValue)(v);
|
|
51
|
+
return { scope, key, value };
|
|
52
|
+
})),
|
|
53
|
+
});
|
|
54
|
+
function validateInputAndOptions(input, options) {
|
|
55
|
+
try {
|
|
56
|
+
const url = urlSchema.parse(input);
|
|
57
|
+
const { follow, respectRobots, outputType, outputTypes: rawOutputTypes, quality, outputDir, fullPage, cssSelector, xpathSelector, colorScheme, browsers: parsedBrowsers, devices: rawDevices, delay, waitFor, cookie, header, localStorage, } = optionsSchema.parse(options);
|
|
58
|
+
let parsedOutputTypes;
|
|
59
|
+
if (rawOutputTypes) {
|
|
60
|
+
try {
|
|
61
|
+
const outputTypeEntrySchema = zod_1.z.array(zod_1.z
|
|
62
|
+
.object({
|
|
63
|
+
type: zod_1.z.string().transform((v) => v.toUpperCase()),
|
|
64
|
+
selector: zod_1.z
|
|
65
|
+
.object({
|
|
66
|
+
type: zod_1.z.enum(['CSS', 'XPATH']).optional(),
|
|
67
|
+
value: zod_1.z.string().optional(),
|
|
68
|
+
})
|
|
69
|
+
.optional(),
|
|
70
|
+
quality: zod_1.z.number().min(1).max(100).optional(),
|
|
71
|
+
})
|
|
72
|
+
.transform((data) => ({
|
|
73
|
+
...data,
|
|
74
|
+
type: data.type,
|
|
75
|
+
})));
|
|
76
|
+
parsedOutputTypes = outputTypeEntrySchema.parse(JSON.parse(rawOutputTypes));
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
output_1.default.exitError("Invalid --outputTypes value. Use JSON array, e.g. --outputTypes '[{\"type\":\"png\"},{\"type\":\"jpeg\",\"quality\":80}]'");
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
else if (outputType) {
|
|
83
|
+
if (typeof quality === 'number' && outputType !== 'jpeg') {
|
|
84
|
+
output_1.default.exitError('Quality is only supported for jpeg output type, use --outputType jpeg');
|
|
85
|
+
}
|
|
86
|
+
if (cssSelector && xpathSelector) {
|
|
87
|
+
output_1.default.exitError('Only one of --cssSelector or --xpathSelector can be used');
|
|
88
|
+
}
|
|
89
|
+
const entry = {
|
|
90
|
+
type: outputType.toUpperCase(),
|
|
91
|
+
};
|
|
92
|
+
if (cssSelector) {
|
|
93
|
+
entry.selector = { type: 'CSS', value: cssSelector };
|
|
94
|
+
}
|
|
95
|
+
else if (xpathSelector) {
|
|
96
|
+
entry.selector = { type: 'XPATH', value: xpathSelector };
|
|
97
|
+
}
|
|
98
|
+
if (typeof quality === 'number') {
|
|
99
|
+
entry.quality = quality;
|
|
100
|
+
}
|
|
101
|
+
parsedOutputTypes = [entry];
|
|
102
|
+
}
|
|
103
|
+
let parsedDevices;
|
|
104
|
+
if (rawDevices) {
|
|
105
|
+
try {
|
|
106
|
+
const dimensionSchema = zod_1.z
|
|
107
|
+
.string()
|
|
108
|
+
.regex(/^\d+x\d+$/, 'Must be in format "widthxheight"')
|
|
109
|
+
.transform((val) => {
|
|
110
|
+
const [width, height] = val.split('x').map(Number);
|
|
111
|
+
return { width, height };
|
|
112
|
+
});
|
|
113
|
+
const deviceSchema = zod_1.z.array(zod_1.z.object({
|
|
114
|
+
name: zod_1.z.string().optional(),
|
|
115
|
+
viewport: dimensionSchema,
|
|
116
|
+
screen: dimensionSchema,
|
|
117
|
+
devicePixelRatio: zod_1.z.number().positive(),
|
|
118
|
+
isMobile: zod_1.z.boolean(),
|
|
119
|
+
}));
|
|
120
|
+
parsedDevices = deviceSchema.parse(JSON.parse(rawDevices));
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
output_1.default.exitError('Invalid --devices value. Use JSON array, e.g. --devices \'[{"viewport":"1920x1080","screen":"1920x1080","devicePixelRatio":1,"isMobile":false}]\'');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
url,
|
|
128
|
+
follow,
|
|
129
|
+
respectRobots,
|
|
130
|
+
outputTypes: parsedOutputTypes,
|
|
131
|
+
outputDir,
|
|
132
|
+
fullPage,
|
|
133
|
+
colorScheme,
|
|
134
|
+
browsers: parsedBrowsers,
|
|
135
|
+
devices: parsedDevices,
|
|
136
|
+
cookies: cookie,
|
|
137
|
+
requestHeaders: header,
|
|
138
|
+
delay,
|
|
139
|
+
waitForSelectors: waitFor,
|
|
140
|
+
localStorage,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
if (error instanceof zod_1.ZodError) {
|
|
145
|
+
output_1.default.exitError(error.errors.map((e) => `${e.path}: ${e.message}`).join(', '));
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
throw error;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const utils_1 = require("../utils");
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const texts_1 = require("../texts");
|
|
9
|
+
const output_1 = __importDefault(require("../output"));
|
|
10
|
+
const node_zlib_1 = require("node:zlib");
|
|
11
|
+
const promises_1 = require("node:stream/promises");
|
|
12
|
+
const node_fs_1 = require("node:fs");
|
|
13
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
14
|
+
const promises_2 = require("node:fs/promises");
|
|
15
|
+
const commandCrawl = (0, utils_1.newCommand)('crawl', texts_1.DESC_COMMAND_CRAWL);
|
|
16
|
+
commandCrawl.argument('[url]', texts_1.OPTION_CRAWL_URL);
|
|
17
|
+
commandCrawl.option('--follow', texts_1.OPTION_CRAWL_FOLLOW, false);
|
|
18
|
+
commandCrawl.option('--respectRobots', texts_1.OPTION_COMPARE_RESPECT_ROBOTS, false);
|
|
19
|
+
commandCrawl.addOption(new commander_1.Option('--outputType <type>', texts_1.OPTION_CRAWL_OUTPUT_TYPE).choices([
|
|
20
|
+
'jpeg',
|
|
21
|
+
'png',
|
|
22
|
+
'md',
|
|
23
|
+
'html',
|
|
24
|
+
]));
|
|
25
|
+
commandCrawl.option('--outputTypes <json>', texts_1.OPTION_CRAWL_OUTPUT_TYPES);
|
|
26
|
+
commandCrawl.option('--quality <quality>', texts_1.OPTION_CRAWL_QUALITY);
|
|
27
|
+
commandCrawl.option('--fullPage', texts_1.OPTION_CRAWL_FULL_PAGE, false);
|
|
28
|
+
commandCrawl.option('--cssSelector <selector>', texts_1.OPTION_CRAWL_CSS_SELECTOR);
|
|
29
|
+
commandCrawl.option('--xpathSelector <selector>', texts_1.OPTION_CRAWL_XPATH_SELECTOR);
|
|
30
|
+
commandCrawl.addOption(new commander_1.Option('--colorScheme <scheme>', texts_1.OPTION_CRAWL_COLOR_SCHEME).choices([
|
|
31
|
+
'LIGHT',
|
|
32
|
+
'DARK',
|
|
33
|
+
'LIGHT_AND_DARK',
|
|
34
|
+
]));
|
|
35
|
+
commandCrawl.option('--browsers <browsers>', texts_1.OPTION_CRAWL_BROWSERS);
|
|
36
|
+
commandCrawl.option('--devices <devices>', texts_1.OPTION_CRAWL_DEVICES);
|
|
37
|
+
commandCrawl.option('--waitFor <waitFors...>', texts_1.OPTION_COMPARE_WAIT_FOR);
|
|
38
|
+
commandCrawl.option('--cookie <cookies...>', texts_1.OPTION_COMPARE_COOKIE);
|
|
39
|
+
commandCrawl.option('--header <headers...>', texts_1.OPTION_COMPARE_HEADER);
|
|
40
|
+
commandCrawl.option('--localStorage <items...>', texts_1.OPTION_CRAWL_LOCAL_STORAGE);
|
|
41
|
+
commandCrawl.option('--delay <delay>', texts_1.OPTION_CRAWL_DELAY, '0');
|
|
42
|
+
commandCrawl.option('--outputDir <dir>', texts_1.OPTION_CRAWL_OUTPUT_DIR, '.');
|
|
43
|
+
commandCrawl.action(async (inputUrl, options) => {
|
|
44
|
+
const { checkToken } = require('../visualTest/validation');
|
|
45
|
+
const { downloadScrapPackage, sendScrap } = require('../visualTest/requests');
|
|
46
|
+
const { setCiAndCommitInfo } = require('../visualTest/context');
|
|
47
|
+
const { validateInputAndOptions } = require('./crawl/validation');
|
|
48
|
+
const { getCiAndGitInfo } = require('@buddy-works/ci-info');
|
|
49
|
+
const tar = require('tar-stream');
|
|
50
|
+
if (!checkToken('scrape')) {
|
|
51
|
+
output_1.default.exitError(texts_1.ERR_MISSING_CRAWL_TOKEN);
|
|
52
|
+
}
|
|
53
|
+
const { url, follow, respectRobots, outputTypes, outputDir, fullPage, colorScheme, browsers, devices, cookies, requestHeaders, delay, waitForSelectors, localStorage, } = validateInputAndOptions(inputUrl, options);
|
|
54
|
+
try {
|
|
55
|
+
const ciAndGitInfo = await getCiAndGitInfo({});
|
|
56
|
+
setCiAndCommitInfo(ciAndGitInfo);
|
|
57
|
+
const { buildId } = await sendScrap(url, follow, respectRobots, outputTypes, fullPage, colorScheme, browsers, devices, cookies, requestHeaders, delay, waitForSelectors, localStorage);
|
|
58
|
+
const status = await watchSessionStatus(buildId);
|
|
59
|
+
if (!status.ok) {
|
|
60
|
+
output_1.default.exitError(`Crawl session failed: ${status.error}`);
|
|
61
|
+
}
|
|
62
|
+
output_1.default.normal('Downloading crawl package');
|
|
63
|
+
const scrapPackageStream = await downloadScrapPackage(buildId);
|
|
64
|
+
const brotliDecompressor = (0, node_zlib_1.createBrotliDecompress)();
|
|
65
|
+
const unpack = tar.extract();
|
|
66
|
+
unpack.on('entry', async (header, stream, next) => {
|
|
67
|
+
const currentDir = process.cwd();
|
|
68
|
+
const preparedOutputDir = outputDir.startsWith('.')
|
|
69
|
+
? node_path_1.default.join(currentDir, outputDir)
|
|
70
|
+
: outputDir;
|
|
71
|
+
const newFilePath = node_path_1.default.join(preparedOutputDir, header.name);
|
|
72
|
+
try {
|
|
73
|
+
if (header.type === 'file') {
|
|
74
|
+
await (0, promises_2.mkdir)(node_path_1.default.dirname(newFilePath), { recursive: true });
|
|
75
|
+
const fileWriteStream = (0, node_fs_1.createWriteStream)(newFilePath);
|
|
76
|
+
await (0, promises_1.pipeline)(stream, fileWriteStream);
|
|
77
|
+
next();
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
stream.resume();
|
|
81
|
+
next();
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
catch (entryError) {
|
|
85
|
+
output_1.default.error(`Error processing entry ${header.name}: ${entryError}`);
|
|
86
|
+
next(entryError);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
await (0, promises_1.pipeline)(scrapPackageStream, brotliDecompressor, unpack);
|
|
90
|
+
output_1.default.exitSuccess('Downloading crawl package finished');
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
output_1.default.exitError(`${error}`);
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
async function watchSessionStatus(buildId) {
|
|
97
|
+
const { connectToScrapSession } = require('../visualTest/requests');
|
|
98
|
+
return new Promise((resolve) => {
|
|
99
|
+
const eventSource = connectToScrapSession(buildId);
|
|
100
|
+
eventSource.addEventListener('SESSION_STATUS', (event) => {
|
|
101
|
+
const data = JSON.parse(event.data);
|
|
102
|
+
if (data.status === 'STARTED') {
|
|
103
|
+
output_1.default.normal('Crawl session started');
|
|
104
|
+
}
|
|
105
|
+
else if (data.status === 'GATHER_URLS_COMPLETED') {
|
|
106
|
+
output_1.default.normal(`Gathering URLs completed, found ${data.text} URLs`);
|
|
107
|
+
}
|
|
108
|
+
else if (data.status === 'GATHER_URLS_FAILED') {
|
|
109
|
+
output_1.default.error('Gathering URLs failed');
|
|
110
|
+
}
|
|
111
|
+
else if (data.status === 'SCRAPE_URL_COMPLETED') {
|
|
112
|
+
output_1.default.normal(`Crawling ${data.text} completed`);
|
|
113
|
+
}
|
|
114
|
+
else if (data.status === 'SCRAPE_URL_FAILED') {
|
|
115
|
+
output_1.default.error(`Crawling ${data.text} failed`);
|
|
116
|
+
}
|
|
117
|
+
else if (data.status === 'CREATE_PACKAGE_COMPLETED') {
|
|
118
|
+
output_1.default.normal('Package created');
|
|
119
|
+
}
|
|
120
|
+
else if (data.status === 'CREATE_PACKAGE_FAILED') {
|
|
121
|
+
output_1.default.error('Package creation failed');
|
|
122
|
+
}
|
|
123
|
+
else if (data.status === 'ERROR') {
|
|
124
|
+
eventSource.close();
|
|
125
|
+
resolve({ ok: false, error: data.text });
|
|
126
|
+
}
|
|
127
|
+
else if (data.status === 'FINISHED') {
|
|
128
|
+
eventSource.close();
|
|
129
|
+
output_1.default.normal('Crawl session finished');
|
|
130
|
+
resolve({ ok: true });
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
eventSource.addEventListener('error', (event) => {
|
|
134
|
+
if (event.code) {
|
|
135
|
+
eventSource.close();
|
|
136
|
+
if (event.code === 410) {
|
|
137
|
+
output_1.default.normal('Crawl session finished');
|
|
138
|
+
}
|
|
139
|
+
resolve({ ok: event.code === 410, error: event.code });
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
exports.default = commandCrawl;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const utils_1 = require("../../../utils");
|
|
7
|
+
const texts_1 = require("../../../texts");
|
|
8
|
+
const output_1 = __importDefault(require("../../../output"));
|
|
9
|
+
const input_1 = __importDefault(require("../../../input"));
|
|
10
|
+
const commandPipelineRunStart = (0, utils_1.newCommand)('start', texts_1.DESC_COMMAND_PIPELINE_RUN_START);
|
|
11
|
+
commandPipelineRunStart.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
|
|
12
|
+
commandPipelineRunStart.option('-p, --project <name>', texts_1.OPTION_REST_API_PROJECT);
|
|
13
|
+
commandPipelineRunStart.option('-b, --branch <branch>', texts_1.OPTION_PIPELINE_RUN_BRANCH);
|
|
14
|
+
commandPipelineRunStart.option('-t, --tag <tag>', texts_1.OPTION_PIPELINE_RUN_TAG);
|
|
15
|
+
commandPipelineRunStart.option('-pr, --pull-request <pull request>', texts_1.OPTION_PIPELINE_RUN_PULL_REQUEST);
|
|
16
|
+
commandPipelineRunStart.option('-r, --revision <revision>', texts_1.OPTION_PIPELINE_RUN_REVISION);
|
|
17
|
+
commandPipelineRunStart.option('--comment <comment>', texts_1.OPTION_PIPELINE_RUN_COMMENT);
|
|
18
|
+
commandPipelineRunStart.option('-f, --refresh', texts_1.OPTION_PIPELINE_RUN_REFRESH);
|
|
19
|
+
commandPipelineRunStart.option('-c, --clear-cache', texts_1.OPTION_PIPELINE_RUN_CLEAR_CACHE);
|
|
20
|
+
commandPipelineRunStart.option('--priority <priority>', texts_1.OPTION_PIPELINE_RUN_PRIORITY);
|
|
21
|
+
commandPipelineRunStart.option('-v, --variable <variables...>', texts_1.OPTION_PIPELINE_RUN_VAR);
|
|
22
|
+
commandPipelineRunStart.option('-vm, --variable-masked <variables...>', texts_1.OPTION_PIPELINE_RUN_VAR);
|
|
23
|
+
commandPipelineRunStart.option('--schedule <date>', texts_1.OPTION_PIPELINE_RUN_DELAY);
|
|
24
|
+
commandPipelineRunStart.option('--action <actions...>', texts_1.OPTION_PIPELINE_RUN_ACTION);
|
|
25
|
+
commandPipelineRunStart.option('--no-wait', texts_1.OPTION_PIPELINE_RUN_NO_WAIT);
|
|
26
|
+
commandPipelineRunStart.argument('<identifier>', texts_1.OPTION_PIPELINE_RUN_ARGUMENT);
|
|
27
|
+
commandPipelineRunStart.usage('<identifier> [options]');
|
|
28
|
+
commandPipelineRunStart.addHelpText('after', texts_1.EXAMPLE_PIPELINE_RUN_START);
|
|
29
|
+
commandPipelineRunStart.action(async (identifier, options) => {
|
|
30
|
+
const workspace = input_1.default.restApiWorkspace(options.workspace);
|
|
31
|
+
const project = input_1.default.restApiProject(options.project);
|
|
32
|
+
const client = input_1.default.restApiTokenClient();
|
|
33
|
+
const data = await client.getPipelineByIdentifier(workspace, project, identifier);
|
|
34
|
+
if (!data || !data.domain) {
|
|
35
|
+
output_1.default.exitError(texts_1.ERR_WORKSPACE_NOT_FOUND);
|
|
36
|
+
}
|
|
37
|
+
if (!data.project_identifier) {
|
|
38
|
+
output_1.default.exitError(texts_1.ERR_PROJECT_NOT_FOUND);
|
|
39
|
+
}
|
|
40
|
+
if (!data.pipeline_id) {
|
|
41
|
+
output_1.default.exitError(texts_1.ERR_PIPELINE_NOT_FOUND);
|
|
42
|
+
}
|
|
43
|
+
const body = {};
|
|
44
|
+
if (options.branch) {
|
|
45
|
+
body.branch = {
|
|
46
|
+
name: options.branch,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
if (options.tag) {
|
|
50
|
+
body.tag = {
|
|
51
|
+
name: options.tag,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
if (options.pullRequest) {
|
|
55
|
+
body.pull_request = {
|
|
56
|
+
name: `pull/${options.pullRequest}`,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
if (options.revision) {
|
|
60
|
+
body.to_revision = {
|
|
61
|
+
revision: options.revision,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
if (options.comment) {
|
|
65
|
+
body.comment = options.comment;
|
|
66
|
+
}
|
|
67
|
+
if (options.refresh) {
|
|
68
|
+
body.refresh = true;
|
|
69
|
+
}
|
|
70
|
+
if (options.clearCache) {
|
|
71
|
+
body.clear_cache = true;
|
|
72
|
+
}
|
|
73
|
+
const priority = input_1.default.pipelineRunPriority(options.priority);
|
|
74
|
+
if (priority) {
|
|
75
|
+
body.priority = priority;
|
|
76
|
+
}
|
|
77
|
+
body.variables = [];
|
|
78
|
+
if (options.variable) {
|
|
79
|
+
body.variables = body.variables.concat(input_1.default.pipelineRunVariable(options.variable, false));
|
|
80
|
+
}
|
|
81
|
+
if (options.variableMasked) {
|
|
82
|
+
body.variables = body.variables.concat(input_1.default.pipelineRunVariable(options.variableMasked, true));
|
|
83
|
+
}
|
|
84
|
+
const delay = input_1.default.pipelineRunDelay(options.schedule);
|
|
85
|
+
if (delay) {
|
|
86
|
+
body.delay_until = delay;
|
|
87
|
+
}
|
|
88
|
+
const actions = input_1.default.pipelineRunAction(options.action);
|
|
89
|
+
if (actions) {
|
|
90
|
+
body.actions_to_run = actions;
|
|
91
|
+
}
|
|
92
|
+
const result = await client.pipelineRun(workspace, project, data.pipeline_id, body);
|
|
93
|
+
if (options.noWait) {
|
|
94
|
+
output_1.default.exitSuccess((0, texts_1.TXT_PIPELINE_RUN_SUCCESS)(result.id, result.html_url));
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
const OutputPipeline = require('../../../output/pipeline').default;
|
|
98
|
+
await OutputPipeline.runStatus(client, workspace, project, data.pipeline_id, result.id, false);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
exports.default = commandPipelineRunStart;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const utils_1 = require("../../../utils");
|
|
7
|
+
const texts_1 = require("../../../texts");
|
|
8
|
+
const input_1 = __importDefault(require("../../../input"));
|
|
9
|
+
const output_1 = __importDefault(require("../../../output"));
|
|
10
|
+
const commandPipelineRunStatus = (0, utils_1.newCommand)('status', texts_1.DESC_COMMAND_PIPELINE_RUN_STATUS);
|
|
11
|
+
commandPipelineRunStatus.option('-w, --workspace <domain>', texts_1.OPTION_REST_API_WORKSPACE);
|
|
12
|
+
commandPipelineRunStatus.option('-p, --project <name>', texts_1.OPTION_REST_API_PROJECT);
|
|
13
|
+
commandPipelineRunStatus.option('-n, --no-wait', texts_1.OPTION_PIPELINE_RUN_NO_WAIT);
|
|
14
|
+
commandPipelineRunStatus.argument('<identifier>', texts_1.OPTION_PIPELINE_RUN_ARGUMENT);
|
|
15
|
+
commandPipelineRunStatus.argument('<run-id>', texts_1.OPTION_PIPELINE_RUN_ID);
|
|
16
|
+
commandPipelineRunStatus.action(async (identifier, runId, options) => {
|
|
17
|
+
const workspace = input_1.default.restApiWorkspace(options.workspace);
|
|
18
|
+
const project = input_1.default.restApiProject(options.project);
|
|
19
|
+
const client = input_1.default.restApiTokenClient();
|
|
20
|
+
const rid = input_1.default.pipelineRunId(runId);
|
|
21
|
+
const data = await client.getPipelineByIdentifier(workspace, project, identifier);
|
|
22
|
+
if (!data || !data.domain) {
|
|
23
|
+
output_1.default.exitError(texts_1.ERR_WORKSPACE_NOT_FOUND);
|
|
24
|
+
}
|
|
25
|
+
if (!data.project_identifier) {
|
|
26
|
+
output_1.default.exitError(texts_1.ERR_PROJECT_NOT_FOUND);
|
|
27
|
+
}
|
|
28
|
+
if (!data.pipeline_id) {
|
|
29
|
+
output_1.default.exitError(texts_1.ERR_PIPELINE_NOT_FOUND);
|
|
30
|
+
}
|
|
31
|
+
const OutputPipeline = require('../../../output/pipeline').default;
|
|
32
|
+
await OutputPipeline.runStatus(client, workspace, project, data.pipeline_id, rid, options.noWait);
|
|
33
|
+
});
|
|
34
|
+
exports.default = commandPipelineRunStatus;
|
|
@@ -5,130 +5,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
const utils_1 = require("../../utils");
|
|
7
7
|
const texts_1 = require("../../texts");
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const format_1 = __importDefault(require("../../format"));
|
|
8
|
+
const status_1 = __importDefault(require("./run/status"));
|
|
9
|
+
const start_1 = __importDefault(require("./run/start"));
|
|
11
10
|
const commandPipelineRun = (0, utils_1.newCommand)('run', texts_1.DESC_COMMAND_PIPELINE_RUN);
|
|
12
|
-
commandPipelineRun.
|
|
13
|
-
commandPipelineRun.
|
|
14
|
-
commandPipelineRun.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
commandPipelineRun.option('-r, --revision <revision>', texts_1.OPTION_PIPELINE_RUN_REVISION);
|
|
18
|
-
commandPipelineRun.option('--comment <comment>', texts_1.OPTION_PIPELINE_RUN_COMMENT);
|
|
19
|
-
commandPipelineRun.option('-f, --refresh', texts_1.OPTION_PIPELINE_RUN_REFRESH);
|
|
20
|
-
commandPipelineRun.option('-c, --clear-cache', texts_1.OPTION_PIPELINE_RUN_CLEAR_CACHE);
|
|
21
|
-
commandPipelineRun.option('--priority <priority>', texts_1.OPTION_PIPELINE_RUN_PRIORITY);
|
|
22
|
-
commandPipelineRun.option('-v, --variable <variables...>', texts_1.OPTION_PIPELINE_RUN_VAR);
|
|
23
|
-
commandPipelineRun.option('-vm, --variable-masked <variables...>', texts_1.OPTION_PIPELINE_RUN_VAR);
|
|
24
|
-
commandPipelineRun.option('--schedule <date>', texts_1.OPTION_PIPELINE_RUN_DELAY);
|
|
25
|
-
commandPipelineRun.option('--action <actions...>', texts_1.OPTION_PIPELINE_RUN_ACTION);
|
|
26
|
-
commandPipelineRun.option('--wait [minutes]', texts_1.OPTION_PIPELINE_RUN_WAIT);
|
|
27
|
-
commandPipelineRun.argument('<identifier>', texts_1.OPTION_PIPELINE_RUN_ARGUMENT);
|
|
28
|
-
commandPipelineRun.usage('<identifier> [options]');
|
|
29
|
-
commandPipelineRun.addHelpText('after', texts_1.EXAMPLE_PIPELINE_RUN);
|
|
30
|
-
commandPipelineRun.action(async (identifier, options) => {
|
|
31
|
-
const workspace = input_1.default.restApiWorkspace(options.workspace);
|
|
32
|
-
const project = input_1.default.restApiProject(options.project);
|
|
33
|
-
const client = input_1.default.restApiTokenClient();
|
|
34
|
-
const data = await client.getPipelineByIdentifier(workspace, project, identifier);
|
|
35
|
-
if (!data || !data.domain) {
|
|
36
|
-
output_1.default.exitError(texts_1.ERR_WORKSPACE_NOT_FOUND);
|
|
37
|
-
}
|
|
38
|
-
if (!data.project_identifier) {
|
|
39
|
-
output_1.default.exitError(texts_1.ERR_PROJECT_NOT_FOUND);
|
|
40
|
-
}
|
|
41
|
-
if (!data.pipeline_id) {
|
|
42
|
-
output_1.default.exitError(texts_1.ERR_PIPELINE_NOT_FOUND);
|
|
43
|
-
}
|
|
44
|
-
const body = {};
|
|
45
|
-
if (options.branch) {
|
|
46
|
-
body.branch = {
|
|
47
|
-
name: options.branch,
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
if (options.tag) {
|
|
51
|
-
body.tag = {
|
|
52
|
-
name: options.tag,
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
if (options.pullRequest) {
|
|
56
|
-
body.pull_request = {
|
|
57
|
-
name: `pull/${options.pullRequest}`,
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
if (options.revision) {
|
|
61
|
-
body.to_revision = {
|
|
62
|
-
revision: options.revision,
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
if (options.comment) {
|
|
66
|
-
body.comment = options.comment;
|
|
67
|
-
}
|
|
68
|
-
if (options.refresh) {
|
|
69
|
-
body.refresh = true;
|
|
70
|
-
}
|
|
71
|
-
if (options.clearCache) {
|
|
72
|
-
body.clear_cache = true;
|
|
73
|
-
}
|
|
74
|
-
const priority = input_1.default.pipelineRunPriority(options.priority);
|
|
75
|
-
if (priority) {
|
|
76
|
-
body.priority = priority;
|
|
77
|
-
}
|
|
78
|
-
body.variables = [];
|
|
79
|
-
if (options.variable) {
|
|
80
|
-
body.variables = body.variables.concat(input_1.default.pipelineRunVariable(options.variable, false));
|
|
81
|
-
}
|
|
82
|
-
if (options.variableMasked) {
|
|
83
|
-
body.variables = body.variables.concat(input_1.default.pipelineRunVariable(options.variableMasked, true));
|
|
84
|
-
}
|
|
85
|
-
const delay = input_1.default.pipelineRunDelay(options.schedule);
|
|
86
|
-
if (delay) {
|
|
87
|
-
body.delay_until = delay;
|
|
88
|
-
}
|
|
89
|
-
const actions = input_1.default.pipelineRunAction(options.action);
|
|
90
|
-
if (actions) {
|
|
91
|
-
body.actions_to_run = actions;
|
|
92
|
-
}
|
|
93
|
-
const result = await client.pipelineRun(workspace, project, data.pipeline_id, body);
|
|
94
|
-
if (options.wait) {
|
|
95
|
-
const minutes = input_1.default.pipelineRunWaitTime(options.wait);
|
|
96
|
-
wait(minutes, workspace, project, data.pipeline_id, result.id, result.html_url, client);
|
|
97
|
-
}
|
|
98
|
-
else {
|
|
99
|
-
output_1.default.exitSuccess((0, texts_1.TXT_PIPELINE_RUN_SUCCESS)(result.html_url));
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
const wait = (minutes, workspace, project, pipelineId, runId, htmlUrl, client) => {
|
|
103
|
-
const start = Date.now();
|
|
104
|
-
output_1.default.normal((0, texts_1.TXT_PIPELINE_RUN_WAIT)(minutes));
|
|
105
|
-
let fetchCounter = 1;
|
|
106
|
-
const ts1 = setTimeout(() => {
|
|
107
|
-
output_1.default.exitError(texts_1.ERR_RUN_PIPELINE_WAIT_TIMEOUT);
|
|
108
|
-
}, minutes * 60 * 1000);
|
|
109
|
-
const ts2 = setInterval(async () => {
|
|
110
|
-
output_1.default.clearPreviousLine();
|
|
111
|
-
output_1.default.normal((0, texts_1.TXT_PIPELINE_RUN_STILL_WAITING)(formatWaitTime(start)));
|
|
112
|
-
if (fetchCounter >= 3) {
|
|
113
|
-
const run = await client.getPipelineRun(workspace, project, pipelineId, runId);
|
|
114
|
-
if (!['INPROGRESS', 'ENQUEUED', 'TERMINATING'].includes(run.status)) {
|
|
115
|
-
clearTimeout(ts1);
|
|
116
|
-
clearInterval(ts2);
|
|
117
|
-
output_1.default.clearPreviousLine();
|
|
118
|
-
if (run.status === 'SUCCESSFUL') {
|
|
119
|
-
output_1.default.exitSuccess((0, texts_1.TXT_PIPELINE_RUN_FINISH_SUCCESSFULLY)(htmlUrl));
|
|
120
|
-
}
|
|
121
|
-
else {
|
|
122
|
-
output_1.default.exitError((0, texts_1.TXT_PIPELINE_RUN_FINISH_FAILED)(run.status, htmlUrl));
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
fetchCounter = 0;
|
|
126
|
-
}
|
|
127
|
-
fetchCounter += 1;
|
|
128
|
-
}, 1000);
|
|
129
|
-
};
|
|
130
|
-
const formatWaitTime = (start) => {
|
|
131
|
-
const elapsed = Math.floor((Date.now() - start) / 1000);
|
|
132
|
-
return format_1.default.pipelineRunWaitTime(elapsed);
|
|
133
|
-
};
|
|
11
|
+
commandPipelineRun.addCommand(start_1.default);
|
|
12
|
+
commandPipelineRun.addCommand(status_1.default);
|
|
13
|
+
commandPipelineRun.addHelpText('after', `
|
|
14
|
+
EXAMPLES:${texts_1.EXAMPLE_PIPELINE_RUN_START}
|
|
15
|
+
${texts_1.EXAMPLE_PIPELINE_RUN_STATUS}`);
|
|
134
16
|
exports.default = commandPipelineRun;
|