@corva/create-app 0.39.0-rc.0 → 0.40.0-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/README.md +2 -1
- package/lib/flows/lib/api.js +225 -0
- package/lib/flows/rerun.js +10 -0
- package/lib/flows/steps/release-upload-zip-to-corva.js +3 -15
- package/lib/flows/steps/rerun-create-task.js +51 -0
- package/lib/flows/steps/rerun-prepare-data.js +243 -0
- package/lib/flows/steps/rerun.js +8 -0
- package/lib/index.js +10 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,6 +26,7 @@ Commands:
|
|
|
26
26
|
create [options] [project-directory] Create a new app
|
|
27
27
|
zip [options] <project-directory> [patterns...] Bundle app
|
|
28
28
|
release [options] <project-directory> [patterns...] Release app
|
|
29
|
+
rerun [options] <project-directory> Rerun app
|
|
29
30
|
help [command] display help for command
|
|
30
31
|
```
|
|
31
32
|
|
|
@@ -199,4 +200,4 @@ create-corva-app release test-app --bump-version=patch
|
|
|
199
200
|
|
|
200
201
|
```sh
|
|
201
202
|
create-corva-app release test-app --bump-version=4.2.0
|
|
202
|
-
```
|
|
203
|
+
```
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
const axios = require('axios');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Connect to Corva API
|
|
5
|
+
*
|
|
6
|
+
*/
|
|
7
|
+
class Api {
|
|
8
|
+
constructor(envName, apiKey, authToken = null) {
|
|
9
|
+
this.baseURL = `https://api${
|
|
10
|
+
envName === 'production' ? '' : `.${envName}`
|
|
11
|
+
}.corva.ai`;
|
|
12
|
+
|
|
13
|
+
this.config = {
|
|
14
|
+
headers: {
|
|
15
|
+
'Authorization': authToken ? `Bearer ${authToken}` :`API ${apiKey}`,
|
|
16
|
+
'Content-Type': 'application/json',
|
|
17
|
+
'Accept': 'application/json',
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Get api url
|
|
24
|
+
*
|
|
25
|
+
* @private
|
|
26
|
+
*
|
|
27
|
+
* @param {string} path
|
|
28
|
+
*
|
|
29
|
+
* @returns {string}
|
|
30
|
+
*/
|
|
31
|
+
getUrl(path) {
|
|
32
|
+
return `${this.baseURL}${path}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Send api request
|
|
37
|
+
*
|
|
38
|
+
* @private
|
|
39
|
+
*
|
|
40
|
+
* @param {string} path
|
|
41
|
+
* @param {string} method
|
|
42
|
+
* @param {object} data
|
|
43
|
+
*
|
|
44
|
+
* @returns {object}
|
|
45
|
+
*/
|
|
46
|
+
sendRequest(method, url, data = null) {
|
|
47
|
+
return data ? axios[method](url, data, this.config) : axios[method](url, this.config);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Get app by appKey
|
|
52
|
+
*
|
|
53
|
+
* @public
|
|
54
|
+
*
|
|
55
|
+
* @param {string} appKey
|
|
56
|
+
*
|
|
57
|
+
* @returns {object}
|
|
58
|
+
*/
|
|
59
|
+
async getAppByKey(appKey) {
|
|
60
|
+
const url = this.getUrl(`/v2/apps?per_page=2&search=${appKey}`);
|
|
61
|
+
const response = await this.sendRequest('get', url);
|
|
62
|
+
|
|
63
|
+
const app = response.data.data[0];
|
|
64
|
+
if (!app || app.attributes.app_key != appKey) {
|
|
65
|
+
throw new Error(`App with key - ${appKey}, not exist`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return app;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Get app datasets
|
|
73
|
+
*
|
|
74
|
+
* @public
|
|
75
|
+
*
|
|
76
|
+
* @param {string} appId
|
|
77
|
+
*
|
|
78
|
+
* @returns {object}
|
|
79
|
+
*/
|
|
80
|
+
async getAppDatasetsOperationWrite(appId) {
|
|
81
|
+
const url = this.getUrl(
|
|
82
|
+
`/v2/apps/${appId}/app_datasets?dataset_operation=write&fields[]=app_dataset.dataset_name`
|
|
83
|
+
);
|
|
84
|
+
const response = await this.sendRequest('get', url);
|
|
85
|
+
|
|
86
|
+
if (!response.data.data.length) {
|
|
87
|
+
throw new Error(`App with ID - ${appId}, has not any datasets`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return response.data.data;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Get asset details
|
|
95
|
+
*
|
|
96
|
+
* @public
|
|
97
|
+
*
|
|
98
|
+
* @param {string} assetId
|
|
99
|
+
*
|
|
100
|
+
* @returns {object[]}
|
|
101
|
+
*/
|
|
102
|
+
async getAssetById(assetId) {
|
|
103
|
+
const url = this.getUrl(`/v2/assets/${assetId}`);
|
|
104
|
+
const response = await this.sendRequest('get', url);
|
|
105
|
+
|
|
106
|
+
return response.data.data;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Get asset streams
|
|
112
|
+
*
|
|
113
|
+
* @public
|
|
114
|
+
*
|
|
115
|
+
* @param {string} assetId
|
|
116
|
+
*
|
|
117
|
+
* @returns {object[]}
|
|
118
|
+
*/
|
|
119
|
+
async getStreamByAssetId(assetId) {
|
|
120
|
+
const url = this.getUrl(`/v1/app_streams?asset_id=${assetId}&segment=drilling&status=complete`);
|
|
121
|
+
const response = await this.sendRequest('get', url);
|
|
122
|
+
|
|
123
|
+
if (!response.data[0]) {
|
|
124
|
+
throw new Error(`Could not found streams for asset ID - ${assetId}`);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return response.data;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Get wells data by asset id
|
|
132
|
+
*
|
|
133
|
+
* @public
|
|
134
|
+
*
|
|
135
|
+
* @param {string} assetId
|
|
136
|
+
*
|
|
137
|
+
* @returns {object[]}
|
|
138
|
+
*/
|
|
139
|
+
async getWellByAssetId(assetId) {
|
|
140
|
+
const data = {
|
|
141
|
+
assets: [assetId],
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const url = this.getUrl(`/v2/assets/resolve`);
|
|
145
|
+
const response = await this.sendRequest('post', url, data);
|
|
146
|
+
|
|
147
|
+
if (!response.data.wells.length) {
|
|
148
|
+
throw new Error(`Could not found wells by asset ID - ${assetId}`);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return response.data.wells;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Queue app run for create new task
|
|
156
|
+
*
|
|
157
|
+
* @public
|
|
158
|
+
*
|
|
159
|
+
* @param {string} appId
|
|
160
|
+
* @param {string} version
|
|
161
|
+
* @param {string} wellId
|
|
162
|
+
* @param {string[]} appDatasetsNames
|
|
163
|
+
* @param {string} streamId
|
|
164
|
+
*
|
|
165
|
+
* @returns {object}
|
|
166
|
+
*/
|
|
167
|
+
async queueAppRun(appId, version, wellId, appDatasetsNames, streamId) {
|
|
168
|
+
const data = {
|
|
169
|
+
app_run: {
|
|
170
|
+
app_stream_id: streamId,
|
|
171
|
+
well_id: wellId,
|
|
172
|
+
app_version: version,
|
|
173
|
+
datasets: appDatasetsNames,
|
|
174
|
+
settings: {
|
|
175
|
+
end: 0,
|
|
176
|
+
interval: null,
|
|
177
|
+
invokes: null,
|
|
178
|
+
records_per_event: 300,
|
|
179
|
+
start: 0,
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const url = this.getUrl(`/v2/apps/${appId}/app_runs`);
|
|
185
|
+
const response = await this.sendRequest('post', url, data);
|
|
186
|
+
return response.data.data;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Get all active(status - pending or in_progress or running) runs by app ID
|
|
191
|
+
*
|
|
192
|
+
* @public
|
|
193
|
+
*
|
|
194
|
+
* @param {string} appId
|
|
195
|
+
*
|
|
196
|
+
* @returns {object[]}
|
|
197
|
+
*/
|
|
198
|
+
async getAppRuns(appId) {
|
|
199
|
+
const url = this.getUrl(`/v2/apps/${appId}/app_runs?page=1&per_page=500&status[]=pending&status[]=in_progress&status[]=running`);
|
|
200
|
+
const response = await this.sendRequest('get', url);
|
|
201
|
+
|
|
202
|
+
return response.data.data;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Upload packages
|
|
207
|
+
*
|
|
208
|
+
* @public
|
|
209
|
+
*
|
|
210
|
+
* @param {string} appKey
|
|
211
|
+
* @param {object} formData
|
|
212
|
+
*
|
|
213
|
+
* @returns
|
|
214
|
+
*/
|
|
215
|
+
async uploadPackages(appKey, formData) {
|
|
216
|
+
const url = this.getUrl(`/v2/apps/${appKey}/packages/upload`);
|
|
217
|
+
this.config.headers = {
|
|
218
|
+
...this.config.headers,
|
|
219
|
+
...formData.getHeaders(),
|
|
220
|
+
};
|
|
221
|
+
return this.sendRequest('post', url, formData)
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
module.exports = { Api };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const { PREPARE_FLOW } = require('./prepare');
|
|
2
|
+
const { RERUN_STEPS } = require('./steps/rerun');
|
|
3
|
+
const { GET_RELEASE_CONFIG_STEP } = require('./steps/release-get-config');
|
|
4
|
+
|
|
5
|
+
const RERUN_FLOW = {
|
|
6
|
+
name: 'rerun',
|
|
7
|
+
steps: [PREPARE_FLOW, GET_RELEASE_CONFIG_STEP, ...RERUN_STEPS],
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
module.exports = { RERUN_FLOW };
|
|
@@ -1,31 +1,19 @@
|
|
|
1
1
|
const { RELEASE } = require('../../constants/messages');
|
|
2
|
-
const axios = require('axios');
|
|
3
2
|
const FormData = require('form-data');
|
|
4
3
|
const { resolve } = require('path');
|
|
5
4
|
const { createReadStream } = require('fs');
|
|
6
5
|
const { StepError } = require('../lib/step-error');
|
|
6
|
+
const { Api } = require('../lib/api');
|
|
7
7
|
const { get } = require('lodash/fp');
|
|
8
8
|
|
|
9
9
|
const UPLOAD_ZIP_TO_CORVA_STEP = {
|
|
10
10
|
message: RELEASE.uploadApp,
|
|
11
11
|
fn: async ({ zipFileName, appKey, CORVA_API_ENV, AUTH_TOKEN, API_KEY, dirName }) => {
|
|
12
12
|
const form = new FormData();
|
|
13
|
-
|
|
14
13
|
form.append('package', createReadStream(resolve(dirName, zipFileName)), 'archive.zip');
|
|
15
14
|
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
}.corva.ai`;
|
|
19
|
-
const uploadURL = `${baseURL}/v2/apps/${appKey}/packages/upload`;
|
|
20
|
-
|
|
21
|
-
await axios
|
|
22
|
-
.post(uploadURL, form, {
|
|
23
|
-
headers: {
|
|
24
|
-
...form.getHeaders(),
|
|
25
|
-
Authorization: AUTH_TOKEN ? `Bearer ${AUTH_TOKEN}` : `API ${API_KEY}`,
|
|
26
|
-
},
|
|
27
|
-
})
|
|
28
|
-
.catch((e) => {
|
|
15
|
+
const api = new Api(CORVA_API_ENV, API_KEY, AUTH_TOKEN);
|
|
16
|
+
api.uploadPackages(appKey, form).catch((e) => {
|
|
29
17
|
throw new StepError(
|
|
30
18
|
`${get('response.data.message', e) || ''} \nPOST: ${uploadURL} failed.`,
|
|
31
19
|
{ cause: e }
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
const _ = require('lodash');
|
|
2
|
+
const chalk = require('chalk');
|
|
3
|
+
|
|
4
|
+
const CREATE_TASK_STEP = {
|
|
5
|
+
message: 'Creating tasks...',
|
|
6
|
+
fn: async ({
|
|
7
|
+
appId,
|
|
8
|
+
assets,
|
|
9
|
+
appDatasetsNames,
|
|
10
|
+
mappedAssetsToStreams,
|
|
11
|
+
mappedAssetsToWells,
|
|
12
|
+
api,
|
|
13
|
+
version,
|
|
14
|
+
CORVA_API_ENV,
|
|
15
|
+
}) => {
|
|
16
|
+
if (!assets.length) {
|
|
17
|
+
process.stdout.write(
|
|
18
|
+
`\n\n${chalk.yellow.bold('There is not a asset ID to create new task')}`
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
for (const assetId of assets) {
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
const result = await api.queueAppRun(
|
|
26
|
+
appId,
|
|
27
|
+
version,
|
|
28
|
+
mappedAssetsToWells.get(parseInt(assetId)),
|
|
29
|
+
appDatasetsNames,
|
|
30
|
+
mappedAssetsToStreams.get(parseInt(assetId))
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
process.stdout.write(
|
|
34
|
+
`\n Created new task with ID ${chalk.yellow(result.id)} for asset ID - ${chalk.green(
|
|
35
|
+
assetId
|
|
36
|
+
)}`
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
process.stdout.write(
|
|
40
|
+
`\n Task link - https://app${CORVA_API_ENV === 'production' ? '.' : `.${CORVA_API_ENV}.`}corva.ai/dev-center/apps/${appId}/runner`
|
|
41
|
+
);
|
|
42
|
+
} catch (e) {
|
|
43
|
+
process.stdout.write(
|
|
44
|
+
`\n\n${chalk.red.underline.bold(`Could not rerun app for asset ID - ${assetId}, an error occured: ${e.message}`)}\n\n`
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
module.exports = { CREATE_TASK_STEP };
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
const _ = require('lodash');
|
|
2
|
+
const chalk = require('chalk');
|
|
3
|
+
const inquirer = require('inquirer');
|
|
4
|
+
const { Api } = require('../lib/api');
|
|
5
|
+
const { StepError } = require('../lib/step-error');
|
|
6
|
+
|
|
7
|
+
const MAX_ASSET_IDS_COUNT = 10;
|
|
8
|
+
|
|
9
|
+
const PREPARE_DATA_STEP = {
|
|
10
|
+
message: 'Preparing data for tasks...',
|
|
11
|
+
fn: async (context) => {
|
|
12
|
+
const { manifest, patterns, API_KEY, CORVA_API_ENV, pkg } = context;
|
|
13
|
+
let { assets } = patterns;
|
|
14
|
+
|
|
15
|
+
assets = _.uniq(assets);
|
|
16
|
+
|
|
17
|
+
if (assets.length > MAX_ASSET_IDS_COUNT) {
|
|
18
|
+
throw new StepError(`Please no more than ${MAX_ASSET_IDS_COUNT} asset ids!`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (!['scheduler', 'stream'].includes(manifest.manifest.application.type)) {
|
|
22
|
+
throw new StepError('Rerun command supports only "scheduler" or "stream" apps');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (!await promptAreYouSure()) {
|
|
26
|
+
throw new StepError('Command stopped');
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const api = new Api(CORVA_API_ENV, API_KEY);
|
|
30
|
+
|
|
31
|
+
const app = await api.getAppByKey(manifest.manifest.application.key.toLowerCase());
|
|
32
|
+
const appDatasets = await api.getAppDatasetsOperationWrite(app.id);
|
|
33
|
+
const appDatasetsNames = appDatasets.map((dataset) => dataset.attributes.dataset_name);
|
|
34
|
+
|
|
35
|
+
const existingAppRuns = await getExistAppRuns(app.id, assets, appDatasetsNames, api);
|
|
36
|
+
if (existingAppRuns.size) {
|
|
37
|
+
for (let appRunAssetId of existingAppRuns.keys()) {
|
|
38
|
+
// remove asset ID if similar rerun already exists
|
|
39
|
+
assets = assets.filter((assetId) => appRunAssetId != assetId);
|
|
40
|
+
|
|
41
|
+
const run = existingAppRuns.get(appRunAssetId);
|
|
42
|
+
|
|
43
|
+
process.stdout.write(
|
|
44
|
+
`\n\n${chalk.yellow.bold(`Similar rerun with ID ${run.id}, for asset ID ${appRunAssetId} - already exist. Will be skipped!`)}`
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const {mappedAssetsToWells, mappedAssetsToStreams, assetsToDelete} = await prepareWellAndStreamData(assets, api);
|
|
50
|
+
|
|
51
|
+
if (assetsToDelete.length) {
|
|
52
|
+
// remove asset ID if could not found stream or well
|
|
53
|
+
assets = assets.filter((assetId) => !assetsToDelete.includes(assetId));
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
appId: app.id,
|
|
58
|
+
assets,
|
|
59
|
+
appDatasetsNames,
|
|
60
|
+
mappedAssetsToStreams,
|
|
61
|
+
mappedAssetsToWells,
|
|
62
|
+
api,
|
|
63
|
+
CORVA_API_ENV,
|
|
64
|
+
version: pkg.version,
|
|
65
|
+
};
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* CLI prompt question - Are you sure you want to do this?
|
|
71
|
+
*
|
|
72
|
+
* @returns
|
|
73
|
+
*/
|
|
74
|
+
const promptAreYouSure = async () => {
|
|
75
|
+
const answers = await inquirer
|
|
76
|
+
.prompt([
|
|
77
|
+
{
|
|
78
|
+
message:
|
|
79
|
+
'\n This command will create additional load on the server, which may take a long time. \n Are you sure you want to do this?',
|
|
80
|
+
name: 'option',
|
|
81
|
+
type: 'list',
|
|
82
|
+
choices: [
|
|
83
|
+
{ value: true, name: 'Yes' },
|
|
84
|
+
{ value: false, name: 'No' },
|
|
85
|
+
],
|
|
86
|
+
default: false,
|
|
87
|
+
},
|
|
88
|
+
]);
|
|
89
|
+
return answers.option;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* CLI prompt question - Please choose the stream
|
|
94
|
+
*
|
|
95
|
+
* @param {object[]} streams
|
|
96
|
+
*
|
|
97
|
+
* @returns
|
|
98
|
+
*/
|
|
99
|
+
const getStreamWithPrompt = async (streams) => {
|
|
100
|
+
let stream = {};
|
|
101
|
+
|
|
102
|
+
const choices = streams.map((stream) => {
|
|
103
|
+
return {
|
|
104
|
+
value: stream,
|
|
105
|
+
name: stream.name
|
|
106
|
+
};
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
await inquirer
|
|
110
|
+
.prompt([
|
|
111
|
+
{
|
|
112
|
+
message:
|
|
113
|
+
'\n Please choose stream?',
|
|
114
|
+
name: 'option',
|
|
115
|
+
type: 'list',
|
|
116
|
+
choices,
|
|
117
|
+
},
|
|
118
|
+
])
|
|
119
|
+
.then((answers) => {
|
|
120
|
+
stream = answers.option;
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
return stream;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* CLI prompt question - Please choose the well
|
|
128
|
+
*
|
|
129
|
+
* @param {object[]} wells
|
|
130
|
+
* @param {object} api
|
|
131
|
+
*
|
|
132
|
+
* @returns
|
|
133
|
+
*/
|
|
134
|
+
const getWellWithPrompt = async (wells, api) => {
|
|
135
|
+
let well = {};
|
|
136
|
+
|
|
137
|
+
const choices = await Promise.all(wells.map( async (well) => {
|
|
138
|
+
const assetDetails = await api.getAssetById(well.data.attributes.asset_id);
|
|
139
|
+
well.data.name = assetDetails.attributes.name;
|
|
140
|
+
return {
|
|
141
|
+
value: well.data,
|
|
142
|
+
name: well.data.name,
|
|
143
|
+
};
|
|
144
|
+
}));
|
|
145
|
+
|
|
146
|
+
await inquirer
|
|
147
|
+
.prompt([
|
|
148
|
+
{
|
|
149
|
+
message:
|
|
150
|
+
'\n Please choose the well?',
|
|
151
|
+
name: 'option',
|
|
152
|
+
type: 'list',
|
|
153
|
+
choices,
|
|
154
|
+
},
|
|
155
|
+
])
|
|
156
|
+
.then((answers) => {
|
|
157
|
+
well = answers.option;
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
return well;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Get stream and well data for assets
|
|
166
|
+
*
|
|
167
|
+
* @param {string[]} assets
|
|
168
|
+
* @param {object} api
|
|
169
|
+
*
|
|
170
|
+
* @returns {object}
|
|
171
|
+
*/
|
|
172
|
+
const prepareWellAndStreamData = async (assets, api) => {
|
|
173
|
+
const mappedAssetsToWells = new Map();
|
|
174
|
+
const mappedAssetsToStreams = new Map();
|
|
175
|
+
const assetsToDelete = [];
|
|
176
|
+
|
|
177
|
+
for (const assetId of assets) {
|
|
178
|
+
try {
|
|
179
|
+
process.stdout.write(
|
|
180
|
+
`\n\n${chalk.black.underline.bold(`Process asset ID - ${chalk.green(assetId)}`)}`
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
process.stdout.write(
|
|
184
|
+
'\n Loading wells...'
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
const wells = await api.getWellByAssetId(assetId);
|
|
188
|
+
const well = await getWellWithPrompt(wells, api);
|
|
189
|
+
mappedAssetsToWells.set(well.attributes.asset_id, well.id);
|
|
190
|
+
|
|
191
|
+
process.stdout.write(
|
|
192
|
+
'\n Loading streams...'
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
const streams = await api.getStreamByAssetId(assetId);
|
|
196
|
+
const stream = await getStreamWithPrompt(streams);
|
|
197
|
+
mappedAssetsToStreams.set(stream.asset_id, stream.id);
|
|
198
|
+
} catch (e) {
|
|
199
|
+
process.stdout.write(
|
|
200
|
+
`\n\n${chalk.red.underline.bold(`Skipped the asset ID - ${assetId}, an error occured: ${e.message}`)}`
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
assetsToDelete.push(assetId);
|
|
204
|
+
|
|
205
|
+
if (mappedAssetsToWells.has(assetId)) mappedAssetsToWells.delete(assetId);
|
|
206
|
+
if (mappedAssetsToStreams.has(assetId)) mappedAssetsToStreams.delete(assetId);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return {mappedAssetsToWells, mappedAssetsToStreams, assetsToDelete};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Check if current runs already exist
|
|
215
|
+
*
|
|
216
|
+
* @param {string} appId
|
|
217
|
+
* @param {string[]} assets
|
|
218
|
+
* @param {string[]} appDatasetsNames
|
|
219
|
+
* @param {object} api
|
|
220
|
+
*
|
|
221
|
+
* @returns {map}
|
|
222
|
+
*/
|
|
223
|
+
const getExistAppRuns = async (appId, assets, appDatasetsNames, api) => {
|
|
224
|
+
const appRuns = new Map();
|
|
225
|
+
const existingAppRuns = await api.getAppRuns(appId);
|
|
226
|
+
|
|
227
|
+
// go through all assets ids
|
|
228
|
+
for (const assetId of assets) {
|
|
229
|
+
const runsForCurrentAsset = existingAppRuns.filter((run) => run.attributes.well_asset_id == assetId);
|
|
230
|
+
// go through all existing runs for current asset ID
|
|
231
|
+
for (const run of runsForCurrentAsset) {
|
|
232
|
+
const currentAppDatasetsNames = run.attributes.app_run_datasets.map((dataset) => dataset.name);
|
|
233
|
+
// if datasets names matched for the same asset ID - then run already exist
|
|
234
|
+
if (appDatasetsNames.sort().toString() === currentAppDatasetsNames.sort().toString()) {
|
|
235
|
+
appRuns.set(assetId, run);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return appRuns;
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
module.exports = { PREPARE_DATA_STEP };
|
package/lib/index.js
CHANGED
|
@@ -30,6 +30,7 @@ const { runFlow } = require('./flow');
|
|
|
30
30
|
const { ERROR_ICON } = require('./constants/messages');
|
|
31
31
|
const { StepError } = require('./flows/lib/step-error');
|
|
32
32
|
const { RELEASE_FLOW } = require('./flows/release');
|
|
33
|
+
const { RERUN_FLOW } = require('./flows/rerun');
|
|
33
34
|
const { ZIP_FLOW } = require('./flows/zip');
|
|
34
35
|
const { bumpVersionOptionDeprecated, bumpVersionOption } = require('./bump-version.option');
|
|
35
36
|
const { Manifest } = require('./flows/lib/manifest');
|
|
@@ -198,6 +199,15 @@ async function initialChecks() {
|
|
|
198
199
|
return runFlow(RELEASE_FLOW, { dirName, patterns, options });
|
|
199
200
|
});
|
|
200
201
|
|
|
202
|
+
program
|
|
203
|
+
.command('rerun')
|
|
204
|
+
.description('Rerun app')
|
|
205
|
+
.argument('<project-directory>', 'Project directory to work with')
|
|
206
|
+
.addOption(new Option('--assets [assets...]', 'Assets ids list', []))
|
|
207
|
+
.action(async (dirName, patterns, options) => {
|
|
208
|
+
return runFlow(RERUN_FLOW, { dirName, patterns, options });
|
|
209
|
+
});
|
|
210
|
+
|
|
201
211
|
try {
|
|
202
212
|
await program.parseAsync(process.argv);
|
|
203
213
|
} catch (e) {
|