@corva/create-app 0.0.0-2576df8

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.
Files changed (204) hide show
  1. package/README.md +218 -0
  2. package/bin/cca.js +5 -0
  3. package/bin/create-corva-app.cjs +25 -0
  4. package/common/node/.env +15 -0
  5. package/common/node/.env.sample +26 -0
  6. package/common/node/gitignore +130 -0
  7. package/common/package.json +3 -0
  8. package/common/python/.env +5 -0
  9. package/common/python/.env.sample +7 -0
  10. package/common/python/Makefile +15 -0
  11. package/common/python/gitignore +161 -0
  12. package/common/python/requirements.txt +2 -0
  13. package/lib/commands/attach.js +28 -0
  14. package/lib/commands/create.js +463 -0
  15. package/lib/commands/release.js +58 -0
  16. package/lib/commands/rerun.js +34 -0
  17. package/lib/commands/zip.js +39 -0
  18. package/lib/constants/cache.js +5 -0
  19. package/lib/constants/cli.js +35 -0
  20. package/lib/constants/manifest.js +263 -0
  21. package/lib/constants/messages.js +15 -0
  22. package/lib/constants/package.js +288 -0
  23. package/lib/flow.js +53 -0
  24. package/lib/flows/attach.js +8 -0
  25. package/lib/flows/lib/api.js +385 -0
  26. package/lib/flows/lib/create-zip-archive.js +83 -0
  27. package/lib/flows/lib/json.js +30 -0
  28. package/lib/flows/lib/manifest.js +81 -0
  29. package/lib/flows/lib/notification.js +142 -0
  30. package/lib/flows/lib/step-error.js +10 -0
  31. package/lib/flows/lib/waitForMs.js +3 -0
  32. package/lib/flows/prepare.js +6 -0
  33. package/lib/flows/release.js +26 -0
  34. package/lib/flows/rerun.js +8 -0
  35. package/lib/flows/steps/attach/add-app-to-stream.js +23 -0
  36. package/lib/flows/steps/attach/get-all-live-assets.js +135 -0
  37. package/lib/flows/steps/attach/index.js +5 -0
  38. package/lib/flows/steps/attach/prepare-data.js +19 -0
  39. package/lib/flows/steps/prepare-load-app-files.js +12 -0
  40. package/lib/flows/steps/release/add-label.js +10 -0
  41. package/lib/flows/steps/release/add-notes.js +10 -0
  42. package/lib/flows/steps/release/get-config.js +41 -0
  43. package/lib/flows/steps/release/prepare-data.js +12 -0
  44. package/lib/flows/steps/release/publish.js +11 -0
  45. package/lib/flows/steps/release/remove-failed-upload.js +21 -0
  46. package/lib/flows/steps/release/upload-zip-to-corva.js +136 -0
  47. package/lib/flows/steps/release/wait-for-build.js +36 -0
  48. package/lib/flows/steps/rerun/create-task.js +77 -0
  49. package/lib/flows/steps/rerun/ensure-that-app-in-stream.js +68 -0
  50. package/lib/flows/steps/rerun/get-app-version.js +111 -0
  51. package/lib/flows/steps/rerun/prepare-data.js +162 -0
  52. package/lib/flows/steps/rerun/prepare-well-and-stream-data.js +188 -0
  53. package/lib/flows/steps/rerun/rerun.js +13 -0
  54. package/lib/flows/steps/zip-cleanup.js +17 -0
  55. package/lib/flows/steps/zip-create-archive.js +15 -0
  56. package/lib/flows/steps/zip-file-list-resolve.js +266 -0
  57. package/lib/flows/steps/zip-prepare.js +20 -0
  58. package/lib/flows/steps/zip.js +6 -0
  59. package/lib/flows/zip-simple.js +6 -0
  60. package/lib/flows/zip.js +7 -0
  61. package/lib/helpers/cli-version.js +150 -0
  62. package/lib/helpers/commands.js +13 -0
  63. package/lib/helpers/logger.js +35 -0
  64. package/lib/helpers/manifest.js +82 -0
  65. package/lib/helpers/resolve-app-runtime.js +132 -0
  66. package/lib/helpers/utils.js +97 -0
  67. package/lib/helpers/versioning.js +94 -0
  68. package/lib/main.js +64 -0
  69. package/lib/options/api-key.js +6 -0
  70. package/lib/options/app-key.js +6 -0
  71. package/lib/options/app-version.js +3 -0
  72. package/lib/options/bump-version.js +19 -0
  73. package/lib/options/cache.js +11 -0
  74. package/lib/options/env.js +3 -0
  75. package/lib/options/original-cwd.js +3 -0
  76. package/lib/options/silent.js +3 -0
  77. package/package.json +1 -0
  78. package/template_extensions/corva/.commitlintrc.json +6 -0
  79. package/template_extensions/corva/.eslintrc +32 -0
  80. package/template_extensions/corva/.github/pull_request_template.md +14 -0
  81. package/template_extensions/corva/.github/workflows/code-checks.yml +15 -0
  82. package/template_extensions/corva/.github/workflows/develop.yml +19 -0
  83. package/template_extensions/corva/.github/workflows/feat-fix-delete.yml +14 -0
  84. package/template_extensions/corva/.github/workflows/feat-fix.yml +23 -0
  85. package/template_extensions/corva/.github/workflows/release-fix-X.X.X.yml +16 -0
  86. package/template_extensions/corva/.github/workflows/validate-pr-title.yml +19 -0
  87. package/template_extensions/corva/.husky/commit-msg +5 -0
  88. package/template_extensions/corva/.husky/pre-commit +4 -0
  89. package/template_extensions/corva/.release-please-manifest.json +3 -0
  90. package/template_extensions/corva/release-please-config.json +10 -0
  91. package/templates/scheduler_data-time/javascript/README.md +19 -0
  92. package/templates/scheduler_data-time/javascript/__tests__/processor.spec.js +15 -0
  93. package/templates/scheduler_data-time/javascript/index.js +15 -0
  94. package/templates/scheduler_data-time/python/README.md +31 -0
  95. package/templates/scheduler_data-time/python/lambda_function.py +7 -0
  96. package/templates/scheduler_data-time/python/test/__init__.py +0 -0
  97. package/templates/scheduler_data-time/python/test/app_test.py +10 -0
  98. package/templates/scheduler_data-time/typescript/README.md +25 -0
  99. package/templates/scheduler_data-time/typescript/__tests__/processor.spec.ts +15 -0
  100. package/templates/scheduler_data-time/typescript/index.ts +8 -0
  101. package/templates/scheduler_depth/javascript/README.md +19 -0
  102. package/templates/scheduler_depth/javascript/__tests__/processor.spec.js +17 -0
  103. package/templates/scheduler_depth/javascript/index.js +15 -0
  104. package/templates/scheduler_depth/python/README.md +31 -0
  105. package/templates/scheduler_depth/python/lambda_function.py +7 -0
  106. package/templates/scheduler_depth/python/test/__init__.py +0 -0
  107. package/templates/scheduler_depth/python/test/app_test.py +10 -0
  108. package/templates/scheduler_depth/typescript/README.md +25 -0
  109. package/templates/scheduler_depth/typescript/__tests__/processor.spec.ts +17 -0
  110. package/templates/scheduler_depth/typescript/index.ts +8 -0
  111. package/templates/scheduler_natural-time/javascript/README.md +19 -0
  112. package/templates/scheduler_natural-time/javascript/__tests__/processor.spec.js +15 -0
  113. package/templates/scheduler_natural-time/javascript/index.js +15 -0
  114. package/templates/scheduler_natural-time/python/README.md +31 -0
  115. package/templates/scheduler_natural-time/python/lambda_function.py +7 -0
  116. package/templates/scheduler_natural-time/python/test/__init__.py +0 -0
  117. package/templates/scheduler_natural-time/python/test/app_test.py +10 -0
  118. package/templates/scheduler_natural-time/typescript/README.md +25 -0
  119. package/templates/scheduler_natural-time/typescript/__tests__/processor.spec.ts +15 -0
  120. package/templates/scheduler_natural-time/typescript/index.ts +8 -0
  121. package/templates/stream_depth/javascript/README.md +19 -0
  122. package/templates/stream_depth/javascript/__tests__/processor.spec.js +20 -0
  123. package/templates/stream_depth/javascript/index.js +14 -0
  124. package/templates/stream_depth/python/README.md +31 -0
  125. package/templates/stream_depth/python/lambda_function.py +7 -0
  126. package/templates/stream_depth/python/test/__init__.py +0 -0
  127. package/templates/stream_depth/python/test/app_test.py +16 -0
  128. package/templates/stream_depth/typescript/README.md +25 -0
  129. package/templates/stream_depth/typescript/__tests__/processor.spec.ts +20 -0
  130. package/templates/stream_depth/typescript/index.ts +8 -0
  131. package/templates/stream_time/javascript/README.md +19 -0
  132. package/templates/stream_time/javascript/__tests__/processor.spec.js +14 -0
  133. package/templates/stream_time/javascript/index.js +14 -0
  134. package/templates/stream_time/python/README.md +31 -0
  135. package/templates/stream_time/python/lambda_function.py +7 -0
  136. package/templates/stream_time/python/test/__init__.py +0 -0
  137. package/templates/stream_time/python/test/app_test.py +16 -0
  138. package/templates/stream_time/typescript/README.md +25 -0
  139. package/templates/stream_time/typescript/__tests__/processor.spec.ts +14 -0
  140. package/templates/stream_time/typescript/index.ts +8 -0
  141. package/templates/task/javascript/README.md +19 -0
  142. package/templates/task/javascript/__tests__/processor.spec.js +16 -0
  143. package/templates/task/javascript/index.js +15 -0
  144. package/templates/task/python/README.md +31 -0
  145. package/templates/task/python/lambda_function.py +7 -0
  146. package/templates/task/python/test/__init__.py +0 -0
  147. package/templates/task/python/test/app_test.py +8 -0
  148. package/templates/task/typescript/README.md +25 -0
  149. package/templates/task/typescript/__tests__/processor.spec.ts +16 -0
  150. package/templates/task/typescript/index.ts +8 -0
  151. package/templates/ui/javascript/.codex/config.toml +3 -0
  152. package/templates/ui/javascript/.cursor/mcp.json +8 -0
  153. package/templates/ui/javascript/.eslintrc +11 -0
  154. package/templates/ui/javascript/.mcp.json +8 -0
  155. package/templates/ui/javascript/.prettierrc +1 -0
  156. package/templates/ui/javascript/AGENTS.md +304 -0
  157. package/templates/ui/javascript/CLAUDE.md +1 -0
  158. package/templates/ui/javascript/README.md +31 -0
  159. package/templates/ui/javascript/config/jest/babelTransform.js +16 -0
  160. package/templates/ui/javascript/config/jest/cssTransform.js +16 -0
  161. package/templates/ui/javascript/config/jest/fileTransform.js +48 -0
  162. package/templates/ui/javascript/config/jest/globalSetup.js +5 -0
  163. package/templates/ui/javascript/config/jest/setupTests.js +30 -0
  164. package/templates/ui/javascript/config-overrides.js +10 -0
  165. package/templates/ui/javascript/gitignore +27 -0
  166. package/templates/ui/javascript/src/App.completion.js +52 -0
  167. package/templates/ui/javascript/src/App.drilling.js +49 -0
  168. package/templates/ui/javascript/src/App.scss +17 -0
  169. package/templates/ui/javascript/src/AppSettings.js +28 -0
  170. package/templates/ui/javascript/src/__tests__/App.test.js +26 -0
  171. package/templates/ui/javascript/src/__tests__/AppSettings.test.js +28 -0
  172. package/templates/ui/javascript/src/__tests__/TestsExample.test.js +37 -0
  173. package/templates/ui/javascript/src/assets/logo.svg +7 -0
  174. package/templates/ui/javascript/src/constants.js +3 -0
  175. package/templates/ui/javascript/src/index.js +8 -0
  176. package/templates/ui/typescript/.codex/config.toml +3 -0
  177. package/templates/ui/typescript/.cursor/mcp.json +8 -0
  178. package/templates/ui/typescript/.eslintrc +28 -0
  179. package/templates/ui/typescript/.mcp.json +8 -0
  180. package/templates/ui/typescript/.prettierrc +1 -0
  181. package/templates/ui/typescript/AGENTS.md +344 -0
  182. package/templates/ui/typescript/CLAUDE.md +1 -0
  183. package/templates/ui/typescript/README.md +31 -0
  184. package/templates/ui/typescript/config/jest/babelTransform.js +16 -0
  185. package/templates/ui/typescript/config/jest/cssTransform.js +16 -0
  186. package/templates/ui/typescript/config/jest/fileTransform.js +48 -0
  187. package/templates/ui/typescript/config/jest/globalSetup.js +5 -0
  188. package/templates/ui/typescript/config/jest/setupTests.js +30 -0
  189. package/templates/ui/typescript/config-overrides.js +10 -0
  190. package/templates/ui/typescript/gitignore +27 -0
  191. package/templates/ui/typescript/src/App.completion.tsx +52 -0
  192. package/templates/ui/typescript/src/App.drilling.tsx +49 -0
  193. package/templates/ui/typescript/src/App.scss +17 -0
  194. package/templates/ui/typescript/src/AppSettings.tsx +28 -0
  195. package/templates/ui/typescript/src/__mocks__/mockData.ts +22 -0
  196. package/templates/ui/typescript/src/__tests__/App.test.tsx +27 -0
  197. package/templates/ui/typescript/src/__tests__/AppSettings.test.tsx +28 -0
  198. package/templates/ui/typescript/src/__tests__/TestsExample.test.tsx +37 -0
  199. package/templates/ui/typescript/src/assets/logo.svg +7 -0
  200. package/templates/ui/typescript/src/constants.ts +3 -0
  201. package/templates/ui/typescript/src/custom.d.ts +19 -0
  202. package/templates/ui/typescript/src/index.js +8 -0
  203. package/templates/ui/typescript/src/types.ts +3 -0
  204. package/templates/ui/typescript/tsconfig.json +7 -0
@@ -0,0 +1,10 @@
1
+ export class StepError extends Error {
2
+ cause;
3
+ name;
4
+
5
+ constructor(message, { cause } = {}) {
6
+ super(message);
7
+ this.name = 'StepError';
8
+ this.cause = cause;
9
+ }
10
+ }
@@ -0,0 +1,3 @@
1
+ export async function waitForMs(ms) {
2
+ return new Promise((resolve) => setTimeout(resolve, ms));
3
+ }
@@ -0,0 +1,6 @@
1
+ import { LOAD_APP_FILES_STEP } from './steps/prepare-load-app-files.js';
2
+
3
+ export const PREPARE_FLOW = {
4
+ name: 'prepare',
5
+ steps: [LOAD_APP_FILES_STEP],
6
+ };
@@ -0,0 +1,26 @@
1
+ import { PREPARE_FLOW } from './prepare.js';
2
+ import { SETUP_API_CLIENT_STEP } from './steps/release/get-config.js';
3
+ import { UPLOAD_ZIP_TO_CORVA_STEP } from './steps/release/upload-zip-to-corva.js';
4
+ import { ZIP_SIMPLE_FLOW } from './zip-simple.js';
5
+ import { WAIT_FOR_BUILD_FINISH_STEP } from './steps/release/wait-for-build.js';
6
+ import { REMOVE_FAILED_UPLOAD_STEP } from './steps/release/remove-failed-upload.js';
7
+ import { ADD_LABEL_STEP } from './steps/release/add-label.js';
8
+ import { ADD_NOTES_STEP } from './steps/release/add-notes.js';
9
+ import { PUBLISH_PACKAGE_STEP } from './steps/release/publish.js';
10
+ import { RELEASE_PREPARE_DATA_STEP } from './steps/release/prepare-data.js';
11
+
12
+ export const RELEASE_FLOW = {
13
+ name: 'release',
14
+ steps: [
15
+ PREPARE_FLOW,
16
+ SETUP_API_CLIENT_STEP,
17
+ RELEASE_PREPARE_DATA_STEP,
18
+ ZIP_SIMPLE_FLOW,
19
+ UPLOAD_ZIP_TO_CORVA_STEP,
20
+ WAIT_FOR_BUILD_FINISH_STEP,
21
+ REMOVE_FAILED_UPLOAD_STEP,
22
+ PUBLISH_PACKAGE_STEP,
23
+ ADD_LABEL_STEP,
24
+ ADD_NOTES_STEP,
25
+ ],
26
+ };
@@ -0,0 +1,8 @@
1
+ import { PREPARE_FLOW } from './prepare.js';
2
+ import { RERUN_STEPS } from './steps/rerun/rerun.js';
3
+ import { SETUP_API_CLIENT_STEP } from './steps/release/get-config.js';
4
+
5
+ export const RERUN_FLOW = {
6
+ name: 'rerun',
7
+ steps: [PREPARE_FLOW, SETUP_API_CLIENT_STEP, ...RERUN_STEPS],
8
+ };
@@ -0,0 +1,23 @@
1
+ export const ADD_APP_TO_STREAM_TASK_STEP = {
2
+ message: 'Add app to streams...',
3
+ fn: async (context) => {
4
+ const { assetsStreamsDataToProcess, api, app, manifest, notification } = context;
5
+
6
+ let counter = 0;
7
+
8
+ for (const assetStreamsData of assetsStreamsDataToProcess) {
9
+ for (const stream of assetStreamsData.selectedStreams) {
10
+ notification.printStreamLink(stream.name, stream.id);
11
+
12
+ try {
13
+ await api.connectAppToStream(app.id, stream.id, manifest.manifest.settings.app);
14
+ ++counter;
15
+ } catch (e) {
16
+ notification.printError(`Could not add app to the stream, an error occurred: ${e.message}`);
17
+ }
18
+ }
19
+ }
20
+
21
+ notification.print(`The app has been added to ${counter} - stream(s)`);
22
+ },
23
+ };
@@ -0,0 +1,135 @@
1
+ import inquirer from 'inquirer';
2
+
3
+ export const GET_ALL_LIVE_ASSETS_TASK_STEP = {
4
+ message: 'Fetching all live assets information...',
5
+ fn: async (context) => {
6
+ const { manifest, api, app, notification } = context;
7
+
8
+ const assets = await api.getAllAssets();
9
+
10
+ notification.print(`${assets.length} - asset was found`);
11
+
12
+ const selectedAssets = await getAssetsListWithPrompt(assets, notification);
13
+
14
+ const assetsIds = selectedAssets.map((asset) => asset.id);
15
+ const streams = await api.getStreamsByAssetIds(assetsIds, manifest.manifest.application.segments);
16
+
17
+ const mappedAssetStreamsData = mapAssetsStreamsData(selectedAssets, streams);
18
+
19
+ const assetsStreamsDataToProcess = await getAssetsStreamsWithPrompt(mappedAssetStreamsData, app.id, notification);
20
+
21
+ return {
22
+ ...context,
23
+ assetsStreamsDataToProcess,
24
+ };
25
+ },
26
+ };
27
+
28
+ /**
29
+ * CLI get assets list
30
+ *
31
+ * @param {object[]} assets
32
+ * @param {import('../../lib/notification').Notification} notification
33
+ *
34
+ * @returns {Promise<object[]>}
35
+ */
36
+ const getAssetsListWithPrompt = (assets, notification) => {
37
+ const choices = assets.map((asset) => {
38
+ return {
39
+ value: asset,
40
+ name: notification.getAssetLink(asset.attributes.name, asset.id),
41
+ checked: true,
42
+ };
43
+ });
44
+
45
+ return inquirer
46
+ .prompt([
47
+ {
48
+ message: 'Please choose assets?',
49
+ name: 'option',
50
+ type: 'checkbox',
51
+ choices,
52
+ },
53
+ ])
54
+ .then((res) => res.option);
55
+ };
56
+
57
+ /**
58
+ * Map asset and stream data
59
+ *
60
+ * @param {object[]} assets
61
+ * @param {object[]} streamsData
62
+ *
63
+ * @returns {object[]}
64
+ */
65
+ const mapAssetsStreamsData = (assets, streamsData) => {
66
+ return assets.map((asset) => {
67
+ const currentStreams = streamsData.filter((stream) => stream.asset_id === parseInt(asset.id));
68
+
69
+ return {
70
+ assetId: asset.id,
71
+ assetName: asset.attributes.name,
72
+ streams: currentStreams,
73
+ selectedStreams: [],
74
+ };
75
+ });
76
+ };
77
+
78
+ /**
79
+ * CLI get streams list to process
80
+ *
81
+ * @param {object[]} mappedAssetsStreamsData
82
+ * @param {number} appId
83
+ * @param {import('../../lib/notification').Notification} notification
84
+ *
85
+ * @returns {Promise<object[]>}
86
+ */
87
+ const getAssetsStreamsWithPrompt = async (mappedAssetsStreamsData, appId, notification) => {
88
+ notification.printLineBreak();
89
+
90
+ for (const mappedData of mappedAssetsStreamsData) {
91
+ const currentStreamsCount = mappedData.streams.length;
92
+
93
+ if (!currentStreamsCount) {
94
+ continue;
95
+ }
96
+
97
+ const streamsWithoutCurrentApp = mappedData.streams.filter((stream) => {
98
+ return !stream.app_connections.find((appConnection) => appConnection.app_id === parseInt(appId));
99
+ });
100
+
101
+ if (!streamsWithoutCurrentApp.length) {
102
+ continue;
103
+ }
104
+
105
+ if (streamsWithoutCurrentApp.length === 1) {
106
+ mappedData.selectedStreams = streamsWithoutCurrentApp;
107
+
108
+ continue;
109
+ }
110
+
111
+ const choices = streamsWithoutCurrentApp.map((stream) => {
112
+ return {
113
+ value: stream,
114
+ name: notification.getStreamLink(stream.name, stream.id),
115
+ checked: true,
116
+ };
117
+ });
118
+
119
+ const link = notification.getAssetLink(mappedData.assetName, mappedData.assetId);
120
+ const selectedStreams = await inquirer
121
+ .prompt([
122
+ {
123
+ message: `Please choose streams for the asset - ${link}?`,
124
+ name: 'option',
125
+ type: 'checkbox',
126
+ choices,
127
+ },
128
+ ])
129
+ .then((res) => res.option);
130
+
131
+ mappedData.selectedStreams = selectedStreams;
132
+ }
133
+
134
+ return mappedAssetsStreamsData;
135
+ };
@@ -0,0 +1,5 @@
1
+ import { PREPARE_DATA_TASK_STEP } from './prepare-data.js';
2
+ import { GET_ALL_LIVE_ASSETS_TASK_STEP } from './get-all-live-assets.js';
3
+ import { ADD_APP_TO_STREAM_TASK_STEP } from './add-app-to-stream.js';
4
+
5
+ export const ATTACH_STEPS = [PREPARE_DATA_TASK_STEP, GET_ALL_LIVE_ASSETS_TASK_STEP, ADD_APP_TO_STREAM_TASK_STEP];
@@ -0,0 +1,19 @@
1
+ import { StepError } from '../../lib/step-error.js';
2
+
3
+ export const PREPARE_DATA_TASK_STEP = {
4
+ message: 'Preparing and checking data...',
5
+ fn: async (context) => {
6
+ const { manifest, api } = context;
7
+
8
+ if (!['scheduler', 'stream'].includes(manifest.manifest.application.type)) {
9
+ throw new StepError('Command supports only "scheduler" or "stream" apps');
10
+ }
11
+
12
+ const app = await api.getAppByKey(manifest.manifest.application.key);
13
+
14
+ return {
15
+ app,
16
+ ...context,
17
+ };
18
+ },
19
+ };
@@ -0,0 +1,12 @@
1
+ import { loadJson } from '../lib/json.js';
2
+ import { Manifest } from '../lib/manifest.js';
3
+
4
+ export const LOAD_APP_FILES_STEP = {
5
+ message: "Loading Corva app's files...",
6
+ async fn(context) {
7
+ const manifest = context.manifest || new Manifest(await loadJson(context.dirName, 'manifest.json'));
8
+ const pkg = context.package || (manifest.isJs() && (await loadJson(context.dirName, 'package.json')));
9
+
10
+ return { pkg, manifest };
11
+ },
12
+ };
@@ -0,0 +1,10 @@
1
+ export const ADD_LABEL_STEP = {
2
+ message: 'Adding label...',
3
+ async fn({ options: { label }, api, appId, packageId }) {
4
+ if (!label) {
5
+ return;
6
+ }
7
+
8
+ await api.putLabel(appId, packageId, label);
9
+ },
10
+ };
@@ -0,0 +1,10 @@
1
+ export const ADD_NOTES_STEP = {
2
+ message: 'Adding notes...',
3
+ async fn({ api, appId, packageId, options: { notes } }) {
4
+ if (!notes) {
5
+ return;
6
+ }
7
+
8
+ await api.addNotes(appId, packageId, notes);
9
+ },
10
+ };
@@ -0,0 +1,41 @@
1
+ import { RELEASE } from '../../../constants/messages.js';
2
+ import { promises as fs } from 'node:fs';
3
+ import dotenv from 'dotenv';
4
+ import { resolve } from 'node:path';
5
+ import { StepError } from '../../lib/step-error.js';
6
+ import { Api } from '../../lib/api.js';
7
+ import { Notification } from '../../lib/notification.js';
8
+
9
+ async function getVarsFromDotEnv({ dirName }) {
10
+ try {
11
+ const envFile = await fs.readFile(resolve(dirName, '.env'));
12
+
13
+ return dotenv.parse(envFile);
14
+ } catch (error) {
15
+ return {};
16
+ }
17
+ }
18
+
19
+ export const SETUP_API_CLIENT_STEP = {
20
+ message: RELEASE.getAuthToken,
21
+ fn: async ({ dirName, options: { apiKey, env } }) => {
22
+ const parsedEnv = await getVarsFromDotEnv({ dirName });
23
+
24
+ const CORVA_API_ENV = env || parsedEnv.CORVA_API_ENV || process.env.CORVA_API_ENV || 'production';
25
+ const AUTH_TOKEN = process.env.AUTH_TOKEN || parsedEnv.AUTH_TOKEN;
26
+ const API_KEY = apiKey || process.env.API_KEY || parsedEnv.API_KEY;
27
+
28
+ if (!AUTH_TOKEN && !API_KEY) {
29
+ throw new StepError(RELEASE.getAuthTokenError);
30
+ }
31
+
32
+ const api = new Api(CORVA_API_ENV, API_KEY, AUTH_TOKEN);
33
+ const notification = new Notification(CORVA_API_ENV);
34
+
35
+ return {
36
+ CORVA_API_ENV,
37
+ api,
38
+ notification,
39
+ };
40
+ },
41
+ };
@@ -0,0 +1,12 @@
1
+ export const RELEASE_PREPARE_DATA_STEP = {
2
+ message: 'Preparing data...',
3
+ async fn({ api, manifest, options }) {
4
+ const appKey = options.appKey || manifest.manifest.application.key;
5
+ const app = await api.getAppByKey(appKey);
6
+
7
+ return {
8
+ appId: app.id,
9
+ appKey,
10
+ };
11
+ },
12
+ };
@@ -0,0 +1,11 @@
1
+ export const PUBLISH_PACKAGE_STEP = {
2
+ message: 'Publishing app...',
3
+ /**
4
+ *
5
+ * @param {object} param0
6
+ * @param {import('../../lib/api').Api} param0.api
7
+ */
8
+ async fn({ api, appId, packageId }) {
9
+ await api.publishApp(appId, packageId);
10
+ },
11
+ };
@@ -0,0 +1,21 @@
1
+ import { resolve } from 'node:path';
2
+ import { unlink } from 'node:fs/promises';
3
+ import { StepError } from '../../lib/step-error.js';
4
+
5
+ export const REMOVE_FAILED_UPLOAD_STEP = {
6
+ message: 'Cleaning up...',
7
+ async fn({ api, appId, packageId, removeOnFail, uploadStatus, dirName, zipFileName, removeOnSuccess }) {
8
+ if (uploadStatus === 'draft') {
9
+ removeOnSuccess && (await unlink(resolve(dirName, zipFileName)));
10
+
11
+ return;
12
+ }
13
+
14
+ if (removeOnFail) {
15
+ await unlink(resolve(dirName, zipFileName));
16
+ await api.deleteAppUpload(appId, packageId);
17
+ }
18
+
19
+ throw new StepError(`Got unexpected status '${uploadStatus}' while processing package ${packageId}.`);
20
+ },
21
+ };
@@ -0,0 +1,136 @@
1
+ import FormData from 'form-data';
2
+ import chalk from 'chalk';
3
+ import fs from 'fs';
4
+ import { createReadStream } from 'node:fs';
5
+ import { resolve } from 'node:path';
6
+ import { RELEASE } from '../../../constants/messages.js';
7
+ import { StepError } from '../../lib/step-error.js';
8
+ import { logger } from '../../../helpers/logger.js';
9
+ import { execSync } from 'node:child_process';
10
+
11
+ async function deleteAppPackage({ api, appId, appPkgVersion }) {
12
+ const appPackages = await api.getAppPackages(appId);
13
+ const packageToDelete = appPackages.find(
14
+ (appPackage) => appPackage.attributes.package_code_version === appPkgVersion,
15
+ );
16
+
17
+ if (!packageToDelete) {
18
+ throw new StepError('No matching version while trying to remove the existing package, unrecoverable error');
19
+ }
20
+
21
+ try {
22
+ await api.deleteAppUpload(appId, packageToDelete?.id);
23
+ } catch (error) {
24
+ throw new StepError('Failed to remove the package, probably can retry');
25
+ }
26
+ }
27
+
28
+ function getRealAuthorFromGithubEvent() {
29
+ if (!process.env.GITHUB_EVENT_PATH) {
30
+ return null;
31
+ }
32
+
33
+ try {
34
+ const event = JSON.parse(fs.readFileSync(process.env.GITHUB_EVENT_PATH, 'utf8'));
35
+
36
+ // For push-event
37
+ if (event?.pusher?.name) {
38
+ return event.pusher.name;
39
+ }
40
+
41
+ // For PR event
42
+ if (event?.pull_request?.user?.login) {
43
+ return event.pull_request.user.login;
44
+ }
45
+ } catch (error) {
46
+ // Catch error in case json file is invalid or absent
47
+ return null;
48
+ }
49
+
50
+ return null;
51
+ }
52
+
53
+ function getGithubUsernameActor() {
54
+ // If option passed --author – we firstly take it
55
+ if (process.env.githubUsername) {
56
+ return process.env.githubUsername;
57
+ }
58
+
59
+ // If no --author passed, try use GITHUB_ACTOR
60
+ const actor = process.env.GITHUB_ACTOR;
61
+
62
+ if (actor && actor !== 'github-actions[bot]') {
63
+ return actor;
64
+ }
65
+
66
+ // If actor == github-actions[bot], let's try to get a real user
67
+ const realAuthor = getRealAuthorFromGithubEvent();
68
+
69
+ if (realAuthor) {
70
+ return realAuthor;
71
+ }
72
+
73
+ return null;
74
+ }
75
+
76
+ function getGitConfigUsername() {
77
+ try {
78
+ let username = execSync('git config user.name').toString().trim();
79
+
80
+ if (!username) {
81
+ username = execSync('git config --global user.name').toString().trim();
82
+ }
83
+
84
+ return username || null;
85
+ } catch (error) {
86
+ logger.log('Unable to fetch git config username:', error.message);
87
+
88
+ return null;
89
+ }
90
+ }
91
+
92
+ export const UPLOAD_ZIP_TO_CORVA_STEP = {
93
+ message: RELEASE.uploadApp,
94
+ /**
95
+ *
96
+ * @param {object} param0
97
+ * @param {import('../../lib/api').Api} param0.api
98
+ */
99
+ fn: async ({ zipFileName, api, appId, appKey, dirName, options, pkg }) => {
100
+ async function uploadAppPackage() {
101
+ const form = new FormData();
102
+
103
+ form.append('package', createReadStream(resolve(dirName, zipFileName)), 'package.zip');
104
+
105
+ let githubUsername = getGithubUsernameActor();
106
+
107
+ if (!githubUsername) {
108
+ githubUsername = getGitConfigUsername();
109
+ }
110
+
111
+ form.append('github_username', githubUsername);
112
+
113
+ const { id: packageId, isDeletedDueToLimit } = await api.uploadPackages(appKey, form);
114
+
115
+ if (isDeletedDueToLimit) {
116
+ logger.write(
117
+ `\n${chalk.yellow`NOTE`}: Version number limit reached. The oldest version without label was deleted.`,
118
+ );
119
+ }
120
+
121
+ return { packageId };
122
+ }
123
+
124
+ try {
125
+ return await uploadAppPackage();
126
+ } catch (error) {
127
+ if (error?.message?.includes('Package code version has already been taken') && options.removeExisting) {
128
+ await deleteAppPackage({ api, appPkgVersion: pkg.version, appId });
129
+
130
+ return uploadAppPackage();
131
+ }
132
+
133
+ throw error;
134
+ }
135
+ },
136
+ };
@@ -0,0 +1,36 @@
1
+ import debugFn from 'debug';
2
+ import { waitForMs } from '../../lib/waitForMs.js';
3
+ import { logger } from '../../../helpers/logger.js';
4
+
5
+ const debug = debugFn('cca:flow:release:step:wait-for-build');
6
+
7
+ const PROCESSING_STATUSES = ['pending', 'processing', 'queued', 'deploying'];
8
+
9
+ export const WAIT_FOR_BUILD_FINISH_STEP = {
10
+ message: 'Wait till the app will process to draft status...',
11
+ /**
12
+ * @param {object} param0
13
+ * @param {import('../../lib/api').Api} param0.api
14
+ */
15
+ async fn({ api, appId, packageId, progress }) {
16
+ do {
17
+ const { status, notes } = await api.checkApp(appId, packageId);
18
+
19
+ progress();
20
+
21
+ debug(`Status: ${status}`);
22
+
23
+ if (!PROCESSING_STATUSES.includes(status)) {
24
+ if (notes) {
25
+ logger.write('\nNotes after package upload:\n\n');
26
+ logger.write(notes);
27
+ }
28
+
29
+ return { uploadStatus: status };
30
+ }
31
+
32
+ await waitForMs(5000);
33
+ // eslint-disable-next-line no-constant-condition
34
+ } while (true);
35
+ },
36
+ };
@@ -0,0 +1,77 @@
1
+ import chalk from 'chalk';
2
+
3
+ import { logger } from '../../../helpers/logger.js';
4
+
5
+ export const CREATE_TASK_STEP = {
6
+ message: 'Creating tasks...',
7
+ /**
8
+ *
9
+ * @param {object} param0
10
+ * @param {import('../../lib/api').Api} param0.api
11
+ */
12
+ fn: async ({
13
+ app,
14
+ assets,
15
+ appDatasetsNames,
16
+ mappedAssetsToStreams,
17
+ mappedAssetsToWells,
18
+ api,
19
+ version,
20
+ interval,
21
+ corvaUrl,
22
+ options,
23
+ }) => {
24
+ const { cache } = options;
25
+
26
+ if (!assets.length) {
27
+ logger.write(`\n\n${chalk.yellow.bold('There is no asset ID to create a new task')}`);
28
+ }
29
+
30
+ logger.write(`\n ${corvaUrl}/dev-center/apps/${app.id}/runner`);
31
+
32
+ let i = 1;
33
+
34
+ for (const assetId of assets) {
35
+ const wellId = mappedAssetsToWells.get(parseInt(assetId)).id;
36
+ const stream = mappedAssetsToStreams.get(parseInt(assetId));
37
+ const streamId = stream.id;
38
+ const connectedApps = stream.app_connections.filter((connectedApp) => connectedApp.app_id === Number(app.id));
39
+
40
+ if (!wellId || !streamId) {
41
+ logger.write(
42
+ `\n\n${chalk.red.underline.bold(
43
+ `Skipped creating a task for asset ID - ${assetId}, well ID or stream ID is missing`,
44
+ )}\n\n`,
45
+ );
46
+
47
+ continue;
48
+ }
49
+
50
+ try {
51
+ for (const connectedApp of connectedApps) {
52
+ const extraNotification = connectedApps.length > 1 ? `(connected app ID ${connectedApp.id})` : '';
53
+ const result = await api
54
+ .queueAppRun(app.id, version, interval, wellId, appDatasetsNames, stream.id, connectedApp.id, cache)
55
+ .catch((e) => {
56
+ console.log(e.response.body);
57
+
58
+ throw e;
59
+ });
60
+
61
+ logger.write(`
62
+ \n${i}/${assets.length}. Re-run ID ${chalk.yellow(
63
+ result.id,
64
+ )} for the asset - ${corvaUrl}/assets/${assetId} ${extraNotification}`);
65
+ }
66
+
67
+ i++;
68
+ } catch (e) {
69
+ logger.write(
70
+ `\n\n${chalk.red.underline.bold(
71
+ `Could not rerun app for asset ID - ${assetId}, an error occurred: ${e.message}`,
72
+ )}\n\n`,
73
+ );
74
+ }
75
+ }
76
+ },
77
+ };