hereya-cli 0.64.2 → 0.65.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 +133 -43
- package/dist/backend/cloud/cloud-backend.d.ts +71 -0
- package/dist/backend/cloud/cloud-backend.js +96 -0
- package/dist/backend/common.d.ts +4 -0
- package/dist/backend/common.js +1 -0
- package/dist/backend/index.d.ts +5 -1
- package/dist/backend/index.js +18 -2
- package/dist/commands/add/index.js +109 -2
- package/dist/commands/deploy/index.js +8 -2
- package/dist/commands/docker/run/index.js +1 -0
- package/dist/commands/down/index.js +111 -3
- package/dist/commands/env/index.js +1 -0
- package/dist/commands/executor/start/index.d.ts +11 -0
- package/dist/commands/executor/start/index.js +176 -0
- package/dist/commands/remove/index.js +138 -4
- package/dist/commands/run/index.js +1 -0
- package/dist/commands/undeploy/index.js +4 -1
- package/dist/commands/up/index.js +102 -5
- package/dist/commands/workspace/executor/install/index.d.ts +9 -0
- package/dist/commands/workspace/executor/install/index.js +110 -0
- package/dist/commands/workspace/executor/token/index.d.ts +8 -0
- package/dist/commands/workspace/executor/token/index.js +41 -0
- package/dist/commands/workspace/executor/uninstall/index.d.ts +9 -0
- package/dist/commands/workspace/executor/uninstall/index.js +102 -0
- package/dist/executor/context.d.ts +2 -0
- package/dist/executor/context.js +39 -0
- package/dist/executor/delegating.d.ts +15 -0
- package/dist/executor/delegating.js +50 -0
- package/dist/executor/index.d.ts +12 -3
- package/dist/executor/index.js +13 -2
- package/dist/executor/remote.d.ts +16 -0
- package/dist/executor/remote.js +168 -0
- package/dist/infrastructure/index.js +55 -22
- package/dist/lib/config/common.d.ts +5 -0
- package/dist/lib/config/simple.js +43 -24
- package/dist/lib/env/index.d.ts +9 -0
- package/dist/lib/env/index.js +101 -15
- package/dist/lib/package/index.d.ts +12 -0
- package/dist/lib/package/index.js +4 -0
- package/oclif.manifest.json +159 -1
- package/package.json +1 -1
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { Command, Flags } from '@oclif/core';
|
|
2
|
+
import { CloudBackend } from '../../../backend/cloud/cloud-backend.js';
|
|
3
|
+
import { getBackend } from '../../../backend/index.js';
|
|
4
|
+
import { LocalExecutor } from '../../../executor/local.js';
|
|
5
|
+
export default class ExecutorStart extends Command {
|
|
6
|
+
static description = `Start the remote executor process (polls for jobs from hereya cloud).
|
|
7
|
+
|
|
8
|
+
Jobs are executed in parallel up to the concurrency limit (default: 10). Use --concurrency to adjust.
|
|
9
|
+
|
|
10
|
+
Set the HEREYA_TOKEN environment variable to authenticate without running \`hereya login\`.
|
|
11
|
+
Set the HEREYA_CLOUD_URL environment variable to target a specific hereya cloud instance (defaults to https://cloud.hereya.dev).`;
|
|
12
|
+
static examples = [
|
|
13
|
+
'<%= config.bin %> <%= command.id %> -w my-workspace',
|
|
14
|
+
'<%= config.bin %> <%= command.id %> -w my-workspace --concurrency 5',
|
|
15
|
+
'HEREYA_TOKEN=<token> <%= config.bin %> <%= command.id %> -w my-workspace',
|
|
16
|
+
'HEREYA_TOKEN=<token> HEREYA_CLOUD_URL=https://my-cloud.example.com <%= config.bin %> <%= command.id %> -w my-workspace',
|
|
17
|
+
];
|
|
18
|
+
static flags = {
|
|
19
|
+
concurrency: Flags.integer({
|
|
20
|
+
char: 'c',
|
|
21
|
+
default: 10,
|
|
22
|
+
description: 'maximum number of parallel jobs',
|
|
23
|
+
min: 1,
|
|
24
|
+
}),
|
|
25
|
+
workspace: Flags.string({
|
|
26
|
+
char: 'w',
|
|
27
|
+
description: 'name of the workspace to poll jobs for',
|
|
28
|
+
required: true,
|
|
29
|
+
}),
|
|
30
|
+
};
|
|
31
|
+
async run() {
|
|
32
|
+
const { flags } = await this.parse(ExecutorStart);
|
|
33
|
+
const { concurrency } = flags;
|
|
34
|
+
const executor = new LocalExecutor();
|
|
35
|
+
const backend = await getBackend({
|
|
36
|
+
token: process.env.HEREYA_TOKEN,
|
|
37
|
+
url: process.env.HEREYA_CLOUD_URL,
|
|
38
|
+
});
|
|
39
|
+
if (!(backend instanceof CloudBackend)) {
|
|
40
|
+
this.error('Remote executor requires cloud backend. Set HEREYA_TOKEN or run `hereya login` first.');
|
|
41
|
+
}
|
|
42
|
+
const cloudBackend = backend;
|
|
43
|
+
this.log(`Starting executor for workspace: ${flags.workspace} (concurrency: ${concurrency})`);
|
|
44
|
+
this.log('Polling for jobs...');
|
|
45
|
+
// Handle graceful shutdown
|
|
46
|
+
const state = { shuttingDown: false };
|
|
47
|
+
const shutdown = () => {
|
|
48
|
+
this.log('Shutting down executor...');
|
|
49
|
+
state.shuttingDown = true;
|
|
50
|
+
};
|
|
51
|
+
process.on('SIGINT', shutdown);
|
|
52
|
+
process.on('SIGTERM', shutdown);
|
|
53
|
+
const activeJobs = new Set();
|
|
54
|
+
while (!state.shuttingDown) {
|
|
55
|
+
try {
|
|
56
|
+
// Wait for a slot to open up if at concurrency limit
|
|
57
|
+
if (activeJobs.size >= concurrency) {
|
|
58
|
+
// eslint-disable-next-line no-await-in-loop
|
|
59
|
+
await Promise.race(activeJobs);
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
// eslint-disable-next-line no-await-in-loop
|
|
63
|
+
const pollResult = await cloudBackend.pollExecutorJobs({
|
|
64
|
+
workspace: flags.workspace,
|
|
65
|
+
});
|
|
66
|
+
if (!pollResult.success) {
|
|
67
|
+
this.warn(`Poll error: ${pollResult.reason}`);
|
|
68
|
+
// eslint-disable-next-line no-await-in-loop
|
|
69
|
+
await new Promise(resolve => {
|
|
70
|
+
setTimeout(resolve, 5000);
|
|
71
|
+
});
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (!pollResult.job) {
|
|
75
|
+
// No job available, continue polling
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
const { job } = pollResult;
|
|
79
|
+
this.log(`Received job ${job.id} (${job.type}) [${activeJobs.size + 1}/${concurrency} slots used]`);
|
|
80
|
+
// Fire off the job without awaiting it
|
|
81
|
+
const jobPromise = this.executeJob(job, executor, cloudBackend).finally(() => {
|
|
82
|
+
activeJobs.delete(jobPromise);
|
|
83
|
+
});
|
|
84
|
+
activeJobs.add(jobPromise);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
this.warn(`Executor error: ${error.message}`);
|
|
88
|
+
// Wait before retrying
|
|
89
|
+
// eslint-disable-next-line no-await-in-loop
|
|
90
|
+
await new Promise(resolve => {
|
|
91
|
+
setTimeout(resolve, 5000);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Wait for all active jobs to complete before exiting
|
|
96
|
+
if (activeJobs.size > 0) {
|
|
97
|
+
this.log(`Waiting for ${activeJobs.size} active job(s) to complete...`);
|
|
98
|
+
await Promise.allSettled(activeJobs);
|
|
99
|
+
}
|
|
100
|
+
this.log('Executor stopped.');
|
|
101
|
+
}
|
|
102
|
+
async executeJob(job, executor, cloudBackend) {
|
|
103
|
+
// Set up buffered logging
|
|
104
|
+
let logBuffer = '';
|
|
105
|
+
const logInterval = setInterval(async () => {
|
|
106
|
+
if (logBuffer) {
|
|
107
|
+
const logs = logBuffer;
|
|
108
|
+
logBuffer = '';
|
|
109
|
+
try {
|
|
110
|
+
await cloudBackend.updateExecutorJob({
|
|
111
|
+
jobId: job.id,
|
|
112
|
+
logs,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
// Log flush errors are non-fatal
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}, 10_000);
|
|
120
|
+
const logger = {
|
|
121
|
+
debug(msg) {
|
|
122
|
+
logBuffer += msg + '\n';
|
|
123
|
+
},
|
|
124
|
+
error(msg) {
|
|
125
|
+
logBuffer += msg + '\n';
|
|
126
|
+
},
|
|
127
|
+
info(msg) {
|
|
128
|
+
logBuffer += msg + '\n';
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
try {
|
|
132
|
+
if (job.type === 'resolve-env') {
|
|
133
|
+
// resolve-env job: resolve env values using local executor
|
|
134
|
+
const resolved = await executor.resolveEnvValues(job.payload);
|
|
135
|
+
// Send resolved env as result
|
|
136
|
+
clearInterval(logInterval);
|
|
137
|
+
await cloudBackend.updateExecutorJob({
|
|
138
|
+
jobId: job.id,
|
|
139
|
+
logs: logBuffer,
|
|
140
|
+
result: { env: resolved, success: true },
|
|
141
|
+
status: 'completed',
|
|
142
|
+
});
|
|
143
|
+
this.log(`Job ${job.id} completed (resolve-env)`);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
const result = job.type === 'provision'
|
|
147
|
+
? await executor.provision({
|
|
148
|
+
...job.payload,
|
|
149
|
+
logger,
|
|
150
|
+
})
|
|
151
|
+
: await executor.destroy({
|
|
152
|
+
...job.payload,
|
|
153
|
+
logger,
|
|
154
|
+
});
|
|
155
|
+
// Flush remaining logs and send result
|
|
156
|
+
clearInterval(logInterval);
|
|
157
|
+
await cloudBackend.updateExecutorJob({
|
|
158
|
+
jobId: job.id,
|
|
159
|
+
logs: logBuffer,
|
|
160
|
+
result,
|
|
161
|
+
status: result.success ? 'completed' : 'failed',
|
|
162
|
+
});
|
|
163
|
+
this.log(`Job ${job.id} ${result.success ? 'completed' : 'failed'}`);
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
clearInterval(logInterval);
|
|
167
|
+
await cloudBackend.updateExecutorJob({
|
|
168
|
+
jobId: job.id,
|
|
169
|
+
logs: logBuffer + `\nError: ${error.message}\n`,
|
|
170
|
+
result: { reason: error.message, success: false },
|
|
171
|
+
status: 'failed',
|
|
172
|
+
});
|
|
173
|
+
this.warn(`Job ${job.id} failed: ${error.message}`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Args, Command, Flags } from '@oclif/core';
|
|
2
2
|
import { Listr, ListrLogger, ListrLogLevels } from 'listr2';
|
|
3
3
|
import { getBackend } from '../../backend/index.js';
|
|
4
|
-
import {
|
|
4
|
+
import { getExecutorForWorkspace } from '../../executor/context.js';
|
|
5
5
|
import { getConfigManager } from '../../lib/config/index.js';
|
|
6
6
|
import { getEnvManager } from '../../lib/env/index.js';
|
|
7
7
|
import { getLogger, getLogPath, isDebug, setDebug } from '../../lib/log.js';
|
|
@@ -71,7 +71,8 @@ export default class Remove extends Command {
|
|
|
71
71
|
// Parse package name to extract name and version
|
|
72
72
|
const [packageNameWithoutVersion, userSpecifiedVersion] = ctx.package.split('@');
|
|
73
73
|
// Check if package exists in config (using clean name without version)
|
|
74
|
-
|
|
74
|
+
ctx.isDevDeploy = Boolean(config.devDeploy?.[packageNameWithoutVersion]);
|
|
75
|
+
const packageInfo = config.packages?.[packageNameWithoutVersion] || config.deploy?.[packageNameWithoutVersion] || config.devDeploy?.[packageNameWithoutVersion];
|
|
75
76
|
if (!packageInfo) {
|
|
76
77
|
throw new Error(`Package ${packageNameWithoutVersion} not found in the project.`);
|
|
77
78
|
}
|
|
@@ -102,12 +103,34 @@ export default class Remove extends Command {
|
|
|
102
103
|
},
|
|
103
104
|
title: 'Resolving package parameters',
|
|
104
105
|
},
|
|
106
|
+
{
|
|
107
|
+
skip: (ctx) => !ctx.isDevDeploy,
|
|
108
|
+
async task(ctx) {
|
|
109
|
+
const backend = await getBackend();
|
|
110
|
+
const profile = await getProfileFromWorkspace(backend, ctx.workspace, ctx.configOutput.config.project);
|
|
111
|
+
const envManager = getEnvManager();
|
|
112
|
+
const getProjectEnvOutput = await envManager.getProjectEnv({
|
|
113
|
+
excludeDevDeploy: true,
|
|
114
|
+
markSecret: false,
|
|
115
|
+
profile,
|
|
116
|
+
project: ctx.configOutput.config.project,
|
|
117
|
+
projectRootDir,
|
|
118
|
+
workspace: ctx.workspace,
|
|
119
|
+
});
|
|
120
|
+
if (!getProjectEnvOutput.success) {
|
|
121
|
+
throw new Error(getProjectEnvOutput.reason);
|
|
122
|
+
}
|
|
123
|
+
ctx.projectEnv = getProjectEnvOutput.env;
|
|
124
|
+
await delay(500);
|
|
125
|
+
},
|
|
126
|
+
title: 'Loading project environment for devDeploy',
|
|
127
|
+
},
|
|
105
128
|
{
|
|
106
129
|
rendererOptions: {
|
|
107
130
|
persistentOutput: isDebug(),
|
|
108
131
|
},
|
|
109
132
|
async task(ctx, task) {
|
|
110
|
-
const executor$ =
|
|
133
|
+
const executor$ = await getExecutorForWorkspace(ctx.workspace, ctx.configOutput.config.project);
|
|
111
134
|
if (!executor$.success) {
|
|
112
135
|
throw new Error(executor$.reason);
|
|
113
136
|
}
|
|
@@ -117,8 +140,9 @@ export default class Remove extends Command {
|
|
|
117
140
|
package: ctx.packageWithInstalledVersion,
|
|
118
141
|
parameters: ctx.parametersOutput.parameters,
|
|
119
142
|
project: ctx.configOutput.config.project,
|
|
143
|
+
projectEnv: ctx.projectEnv,
|
|
120
144
|
projectRootDir,
|
|
121
|
-
skipDeploy:
|
|
145
|
+
skipDeploy: !ctx.isDevDeploy,
|
|
122
146
|
workspace: ctx.workspace,
|
|
123
147
|
});
|
|
124
148
|
if (!destroyOutput.success) {
|
|
@@ -134,7 +158,9 @@ export default class Remove extends Command {
|
|
|
134
158
|
await envManager.removeProjectEnv({
|
|
135
159
|
env: ctx.destroyOutput.env,
|
|
136
160
|
infra: ctx.destroyOutput.metadata.infra,
|
|
161
|
+
pkg: ctx.destroyOutput.pkgName,
|
|
137
162
|
projectRootDir,
|
|
163
|
+
snakeCase: ctx.destroyOutput.metadata.snakeCase,
|
|
138
164
|
workspace: ctx.workspace,
|
|
139
165
|
});
|
|
140
166
|
await delay(500);
|
|
@@ -163,6 +189,114 @@ export default class Remove extends Command {
|
|
|
163
189
|
},
|
|
164
190
|
title: 'Saving state',
|
|
165
191
|
},
|
|
192
|
+
{
|
|
193
|
+
skip(ctx) {
|
|
194
|
+
const devDeploy = ctx.configOutput.config.devDeploy ?? {};
|
|
195
|
+
return Object.keys(devDeploy).length === 0;
|
|
196
|
+
},
|
|
197
|
+
async task(ctx) {
|
|
198
|
+
const configManager = getConfigManager();
|
|
199
|
+
const { config } = await configManager.loadConfig({ projectRootDir });
|
|
200
|
+
const devDeploy = config.devDeploy ?? {};
|
|
201
|
+
if (Object.keys(devDeploy).length === 0) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
const backend = await getBackend();
|
|
205
|
+
const profile = await getProfileFromWorkspace(backend, ctx.workspace, ctx.configOutput.config.project);
|
|
206
|
+
const envManager = getEnvManager();
|
|
207
|
+
const getProjectEnvOutput = await envManager.getProjectEnv({
|
|
208
|
+
excludeDevDeploy: true,
|
|
209
|
+
markSecret: false,
|
|
210
|
+
profile,
|
|
211
|
+
project: ctx.configOutput.config.project,
|
|
212
|
+
projectRootDir,
|
|
213
|
+
workspace: ctx.workspace,
|
|
214
|
+
});
|
|
215
|
+
if (!getProjectEnvOutput.success) {
|
|
216
|
+
throw new Error(getProjectEnvOutput.reason);
|
|
217
|
+
}
|
|
218
|
+
ctx.projectEnv = getProjectEnvOutput.env;
|
|
219
|
+
ctx.configOutput = { config, found: true };
|
|
220
|
+
await delay(500);
|
|
221
|
+
},
|
|
222
|
+
title: 'Loading project environment',
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
skip(ctx) {
|
|
226
|
+
const devDeploy = ctx.configOutput.config.devDeploy ?? {};
|
|
227
|
+
return Object.keys(devDeploy).length === 0;
|
|
228
|
+
},
|
|
229
|
+
async task(ctx, task) {
|
|
230
|
+
const configManager = getConfigManager();
|
|
231
|
+
const { config } = await configManager.loadConfig({ projectRootDir });
|
|
232
|
+
const devDeployPackages = config.devDeploy ?? {};
|
|
233
|
+
const devDeployEntries = Object.entries(devDeployPackages).map(([name, info]) => ({
|
|
234
|
+
name,
|
|
235
|
+
packageSpec: info.version ? `${name}@${info.version}` : name,
|
|
236
|
+
version: info.version || '',
|
|
237
|
+
}));
|
|
238
|
+
return task.newListr(devDeployEntries.map((pkg) => ({
|
|
239
|
+
rendererOptions: {
|
|
240
|
+
persistentOutput: isDebug(),
|
|
241
|
+
},
|
|
242
|
+
async task(_, task) {
|
|
243
|
+
const parameterManager = getParameterManager();
|
|
244
|
+
const backend = await getBackend();
|
|
245
|
+
const profile = await getProfileFromWorkspace(backend, ctx.workspace, ctx.configOutput.config.project);
|
|
246
|
+
const { parameters } = await parameterManager.getPackageParameters({
|
|
247
|
+
package: pkg.name,
|
|
248
|
+
profile,
|
|
249
|
+
projectRootDir,
|
|
250
|
+
});
|
|
251
|
+
const executor$ = await getExecutorForWorkspace(ctx.workspace, ctx.configOutput.config.project);
|
|
252
|
+
if (!executor$.success) {
|
|
253
|
+
throw new Error(executor$.reason);
|
|
254
|
+
}
|
|
255
|
+
const { executor } = executor$;
|
|
256
|
+
const provisionOutput = await executor.provision({
|
|
257
|
+
logger: getLogger(task),
|
|
258
|
+
package: pkg.packageSpec,
|
|
259
|
+
parameters,
|
|
260
|
+
project: ctx.configOutput.config.project,
|
|
261
|
+
projectEnv: ctx.projectEnv ?? {},
|
|
262
|
+
workspace: ctx.workspace,
|
|
263
|
+
});
|
|
264
|
+
if (!provisionOutput.success) {
|
|
265
|
+
throw new Error(provisionOutput.reason);
|
|
266
|
+
}
|
|
267
|
+
const { env, metadata } = provisionOutput;
|
|
268
|
+
const output = ctx.devDeployAdded || [];
|
|
269
|
+
output.push({ env, metadata, packageName: pkg.name });
|
|
270
|
+
ctx.devDeployAdded = output;
|
|
271
|
+
},
|
|
272
|
+
title: `Provisioning ${pkg.name}`,
|
|
273
|
+
})), { concurrent: true, rendererOptions: { collapseSubtasks: !isDebug() } });
|
|
274
|
+
},
|
|
275
|
+
title: 'Provisioning devDeploy packages',
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
skip: (ctx) => !ctx.devDeployAdded || ctx.devDeployAdded.length === 0,
|
|
279
|
+
async task(ctx) {
|
|
280
|
+
if (!ctx.devDeployAdded || ctx.devDeployAdded.length === 0) {
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
const envManager = getEnvManager();
|
|
284
|
+
for (const { env, metadata, packageName } of ctx.devDeployAdded) {
|
|
285
|
+
// eslint-disable-next-line no-await-in-loop
|
|
286
|
+
await envManager.addProjectEnv({
|
|
287
|
+
env,
|
|
288
|
+
infra: metadata.originalInfra ?? metadata.infra,
|
|
289
|
+
isDevDeploy: true,
|
|
290
|
+
pkg: packageName,
|
|
291
|
+
projectRootDir,
|
|
292
|
+
snakeCase: metadata.snakeCase,
|
|
293
|
+
workspace: ctx.workspace,
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
await delay(500);
|
|
297
|
+
},
|
|
298
|
+
title: 'Adding env vars from devDeploy packages',
|
|
299
|
+
},
|
|
166
300
|
]);
|
|
167
301
|
},
|
|
168
302
|
title: `Removing ${args.package}`,
|
|
@@ -70,6 +70,7 @@ export default class Undeploy extends Command {
|
|
|
70
70
|
const getProjectEnvOutput = await envManager.getProjectEnv({
|
|
71
71
|
markSecret: true,
|
|
72
72
|
profile,
|
|
73
|
+
project: ctx.configOutput.config.project,
|
|
73
74
|
projectRootDir,
|
|
74
75
|
workspace: ctx.workspace,
|
|
75
76
|
});
|
|
@@ -229,12 +230,14 @@ export default class Undeploy extends Command {
|
|
|
229
230
|
return;
|
|
230
231
|
}
|
|
231
232
|
const envManager = getEnvManager();
|
|
232
|
-
for (const { env, metadata } of destroyed) {
|
|
233
|
+
for (const { env, metadata, packageName } of destroyed) {
|
|
233
234
|
// eslint-disable-next-line no-await-in-loop
|
|
234
235
|
await envManager.removeProjectEnv({
|
|
235
236
|
env,
|
|
236
237
|
infra: metadata.originalInfra ?? metadata.infra,
|
|
238
|
+
pkg: packageName,
|
|
237
239
|
projectRootDir,
|
|
240
|
+
snakeCase: metadata.snakeCase,
|
|
238
241
|
workspace,
|
|
239
242
|
});
|
|
240
243
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Command, Flags } from '@oclif/core';
|
|
2
2
|
import { Listr, ListrLogger, ListrLogLevels } from 'listr2';
|
|
3
3
|
import { getBackend } from '../../backend/index.js';
|
|
4
|
-
import {
|
|
4
|
+
import { getExecutorForWorkspace } from '../../executor/context.js';
|
|
5
5
|
import { getConfigManager } from '../../lib/config/index.js';
|
|
6
6
|
import { getEnvManager } from '../../lib/env/index.js';
|
|
7
7
|
import { getLogger, getLogPath, isDebug, setDebug } from '../../lib/log.js';
|
|
@@ -142,7 +142,7 @@ export default class Up extends Command {
|
|
|
142
142
|
profile,
|
|
143
143
|
projectRootDir,
|
|
144
144
|
});
|
|
145
|
-
const executor$ =
|
|
145
|
+
const executor$ = await getExecutorForWorkspace(ctx.workspace, ctx.configOutput.config.project);
|
|
146
146
|
if (!executor$.success) {
|
|
147
147
|
throw new Error(executor$.reason);
|
|
148
148
|
}
|
|
@@ -188,7 +188,7 @@ export default class Up extends Command {
|
|
|
188
188
|
profile,
|
|
189
189
|
projectRootDir,
|
|
190
190
|
});
|
|
191
|
-
const executor$ =
|
|
191
|
+
const executor$ = await getExecutorForWorkspace(ctx.workspace, ctx.configOutput.config.project);
|
|
192
192
|
if (!executor$.success) {
|
|
193
193
|
throw new Error(executor$.reason);
|
|
194
194
|
}
|
|
@@ -223,12 +223,14 @@ export default class Up extends Command {
|
|
|
223
223
|
return;
|
|
224
224
|
}
|
|
225
225
|
const envManager = getEnvManager();
|
|
226
|
-
for (const { env, metadata } of removed) {
|
|
226
|
+
for (const { env, metadata, packageName } of removed) {
|
|
227
227
|
// eslint-disable-next-line no-await-in-loop
|
|
228
228
|
await envManager.removeProjectEnv({
|
|
229
229
|
env,
|
|
230
230
|
infra: metadata.originalInfra ?? metadata.infra,
|
|
231
|
+
pkg: packageName,
|
|
231
232
|
projectRootDir,
|
|
233
|
+
snakeCase: metadata.snakeCase,
|
|
232
234
|
workspace,
|
|
233
235
|
});
|
|
234
236
|
}
|
|
@@ -243,12 +245,14 @@ export default class Up extends Command {
|
|
|
243
245
|
return;
|
|
244
246
|
}
|
|
245
247
|
const envManager = getEnvManager();
|
|
246
|
-
for (const { env, metadata } of ctx.added) {
|
|
248
|
+
for (const { env, metadata, packageName } of ctx.added) {
|
|
247
249
|
// eslint-disable-next-line no-await-in-loop
|
|
248
250
|
await envManager.addProjectEnv({
|
|
249
251
|
env,
|
|
250
252
|
infra: metadata.originalInfra ?? metadata.infra,
|
|
253
|
+
pkg: packageName,
|
|
251
254
|
projectRootDir,
|
|
255
|
+
snakeCase: metadata.snakeCase,
|
|
252
256
|
workspace: ctx.workspace,
|
|
253
257
|
});
|
|
254
258
|
}
|
|
@@ -256,6 +260,99 @@ export default class Up extends Command {
|
|
|
256
260
|
},
|
|
257
261
|
title: 'Adding env vars from added packages',
|
|
258
262
|
},
|
|
263
|
+
{
|
|
264
|
+
skip: (ctx) => !ctx.configOutput.config.devDeploy || Object.keys(ctx.configOutput.config.devDeploy).length === 0,
|
|
265
|
+
async task(ctx) {
|
|
266
|
+
const backend = await getBackend();
|
|
267
|
+
const profile = await getProfileFromWorkspace(backend, ctx.workspace, ctx.configOutput.config.project);
|
|
268
|
+
const envManager = getEnvManager();
|
|
269
|
+
const getProjectEnvOutput = await envManager.getProjectEnv({
|
|
270
|
+
excludeDevDeploy: true,
|
|
271
|
+
markSecret: false,
|
|
272
|
+
profile,
|
|
273
|
+
project: ctx.configOutput.config.project,
|
|
274
|
+
projectRootDir,
|
|
275
|
+
workspace: ctx.workspace,
|
|
276
|
+
});
|
|
277
|
+
if (!getProjectEnvOutput.success) {
|
|
278
|
+
throw new Error(getProjectEnvOutput.reason);
|
|
279
|
+
}
|
|
280
|
+
ctx.projectEnv = getProjectEnvOutput.env;
|
|
281
|
+
await delay(500);
|
|
282
|
+
},
|
|
283
|
+
title: 'Loading project environment',
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
skip: (ctx) => !ctx.configOutput.config.devDeploy || Object.keys(ctx.configOutput.config.devDeploy).length === 0,
|
|
287
|
+
async task(ctx) {
|
|
288
|
+
const devDeployPackages = ctx.configOutput.config.devDeploy ?? {};
|
|
289
|
+
const devDeployEntries = Object.entries(devDeployPackages).map(([name, info]) => ({
|
|
290
|
+
name,
|
|
291
|
+
packageSpec: info.version ? `${name}@${info.version}` : name,
|
|
292
|
+
version: info.version || '',
|
|
293
|
+
}));
|
|
294
|
+
return task.newListr(devDeployEntries.map((pkg) => ({
|
|
295
|
+
rendererOptions: {
|
|
296
|
+
persistentOutput: isDebug(),
|
|
297
|
+
},
|
|
298
|
+
async task(_, task) {
|
|
299
|
+
const parameterManager = getParameterManager();
|
|
300
|
+
const backend = await getBackend();
|
|
301
|
+
const profile = await getProfileFromWorkspace(backend, ctx.workspace, ctx.configOutput.config.project);
|
|
302
|
+
const { parameters } = await parameterManager.getPackageParameters({
|
|
303
|
+
package: pkg.name,
|
|
304
|
+
profile,
|
|
305
|
+
projectRootDir,
|
|
306
|
+
});
|
|
307
|
+
const executor$ = await getExecutorForWorkspace(ctx.workspace, ctx.configOutput.config.project);
|
|
308
|
+
if (!executor$.success) {
|
|
309
|
+
throw new Error(executor$.reason);
|
|
310
|
+
}
|
|
311
|
+
const { executor } = executor$;
|
|
312
|
+
const provisionOutput = await executor.provision({
|
|
313
|
+
logger: getLogger(task),
|
|
314
|
+
package: pkg.packageSpec,
|
|
315
|
+
parameters,
|
|
316
|
+
project: ctx.configOutput.config.project,
|
|
317
|
+
projectEnv: ctx.projectEnv ?? {},
|
|
318
|
+
workspace: ctx.workspace,
|
|
319
|
+
});
|
|
320
|
+
if (!provisionOutput.success) {
|
|
321
|
+
throw new Error(provisionOutput.reason);
|
|
322
|
+
}
|
|
323
|
+
const { env, metadata } = provisionOutput;
|
|
324
|
+
const output = ctx.devDeployAdded || [];
|
|
325
|
+
output.push({ env, metadata, packageName: pkg.name });
|
|
326
|
+
ctx.devDeployAdded = output;
|
|
327
|
+
},
|
|
328
|
+
title: `Provisioning ${pkg.name}`,
|
|
329
|
+
})), { concurrent: true, rendererOptions: { collapseSubtasks: !isDebug() } });
|
|
330
|
+
},
|
|
331
|
+
title: 'Provisioning devDeploy packages',
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
skip: (ctx) => !ctx.devDeployAdded || ctx.devDeployAdded.length === 0,
|
|
335
|
+
async task(ctx) {
|
|
336
|
+
if (!ctx.devDeployAdded || ctx.devDeployAdded.length === 0) {
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
const envManager = getEnvManager();
|
|
340
|
+
for (const { env, metadata, packageName } of ctx.devDeployAdded) {
|
|
341
|
+
// eslint-disable-next-line no-await-in-loop
|
|
342
|
+
await envManager.addProjectEnv({
|
|
343
|
+
env,
|
|
344
|
+
infra: metadata.originalInfra ?? metadata.infra,
|
|
345
|
+
isDevDeploy: true,
|
|
346
|
+
pkg: packageName,
|
|
347
|
+
projectRootDir,
|
|
348
|
+
snakeCase: metadata.snakeCase,
|
|
349
|
+
workspace: ctx.workspace,
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
await delay(500);
|
|
353
|
+
},
|
|
354
|
+
title: 'Adding env vars from devDeploy packages',
|
|
355
|
+
},
|
|
259
356
|
{
|
|
260
357
|
async task(ctx) {
|
|
261
358
|
const backend = await getBackend();
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class WorkspaceExecutorInstall extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static flags: {
|
|
5
|
+
debug: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
6
|
+
workspace: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
};
|
|
8
|
+
run(): Promise<void>;
|
|
9
|
+
}
|