@akash-chowdhury-24/deployhub 2.0.16 → 2.0.17
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/package.json +1 -1
- package/src/commands/env.js +22 -22
- package/src/commands/init.js +14 -0
- package/src/commands/sync-workflows.js +4 -1
- package/src/core/config.js +2 -2
- package/src/deployment/init-prompts.js +51 -0
- package/src/utils/github-actions.js +111 -43
package/package.json
CHANGED
package/src/commands/env.js
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
saveConfig,
|
|
7
7
|
} from '../core/config.js';
|
|
8
8
|
import {
|
|
9
|
+
getEnabledEnvironmentNames,
|
|
9
10
|
getEnvMethod,
|
|
10
11
|
getEnvTrigger,
|
|
11
12
|
isEnvEnabled,
|
|
@@ -25,6 +26,21 @@ import {
|
|
|
25
26
|
envLatestArtifactRemoteKey,
|
|
26
27
|
} from '../utils/build-id.js';
|
|
27
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Regenerate GitHub Actions workflows after env enable/disable/add/remove.
|
|
31
|
+
* @param {import('../core/config.js').DeployHubConfig} config
|
|
32
|
+
* @param {string} cwd
|
|
33
|
+
*/
|
|
34
|
+
async function regenerateWorkflows(config, cwd) {
|
|
35
|
+
await writeWorkflowFile(
|
|
36
|
+
config.storage || [],
|
|
37
|
+
getEnabledEnvironmentNames(config),
|
|
38
|
+
config.environments || {},
|
|
39
|
+
cwd,
|
|
40
|
+
config.cli?.source,
|
|
41
|
+
config
|
|
42
|
+
);
|
|
43
|
+
}
|
|
28
44
|
/**
|
|
29
45
|
* Best-effort last buildId for an env from per-env deploy history.
|
|
30
46
|
* @param {import('../core/config.js').DeployHubConfig} config
|
|
@@ -172,17 +188,7 @@ export function registerEnvCommand(program) {
|
|
|
172
188
|
|
|
173
189
|
await saveConfig(config, cwd);
|
|
174
190
|
|
|
175
|
-
|
|
176
|
-
isEnvEnabled(config.environments[n])
|
|
177
|
-
);
|
|
178
|
-
await writeWorkflowFile(
|
|
179
|
-
config.storage || [],
|
|
180
|
-
enabledNames,
|
|
181
|
-
config.environments,
|
|
182
|
-
cwd,
|
|
183
|
-
config.cli?.source,
|
|
184
|
-
config
|
|
185
|
-
);
|
|
191
|
+
await regenerateWorkflows(config, cwd);
|
|
186
192
|
|
|
187
193
|
log.success(`Added environment "${name}" (${deployAnswers.deployType})`);
|
|
188
194
|
console.log(chalk.gray(` defaultEnvironment: ${config.defaultEnvironment}`));
|
|
@@ -234,7 +240,9 @@ export function registerEnvCommand(program) {
|
|
|
234
240
|
}
|
|
235
241
|
config.environments[name].enabled = true;
|
|
236
242
|
await saveConfig(config, cwd);
|
|
243
|
+
await regenerateWorkflows(config, cwd);
|
|
237
244
|
console.log(chalk.green(`✓ Enabled environment "${name}"`));
|
|
245
|
+
console.log(chalk.gray(' Workflows regenerated — commit .github/workflows if using CI.'));
|
|
238
246
|
});
|
|
239
247
|
|
|
240
248
|
env
|
|
@@ -250,7 +258,9 @@ export function registerEnvCommand(program) {
|
|
|
250
258
|
}
|
|
251
259
|
config.environments[name].enabled = false;
|
|
252
260
|
await saveConfig(config, cwd);
|
|
261
|
+
await regenerateWorkflows(config, cwd);
|
|
253
262
|
console.log(chalk.yellow(`Disabled environment "${name}"`));
|
|
263
|
+
console.log(chalk.gray(' Workflows regenerated — commit .github/workflows if using CI.'));
|
|
254
264
|
});
|
|
255
265
|
|
|
256
266
|
env
|
|
@@ -301,17 +311,7 @@ export function registerEnvCommand(program) {
|
|
|
301
311
|
}
|
|
302
312
|
await saveConfig(config, cwd);
|
|
303
313
|
|
|
304
|
-
|
|
305
|
-
isEnvEnabled(config.environments[n])
|
|
306
|
-
);
|
|
307
|
-
await writeWorkflowFile(
|
|
308
|
-
config.storage || [],
|
|
309
|
-
enabledNames,
|
|
310
|
-
config.environments,
|
|
311
|
-
cwd,
|
|
312
|
-
config.cli?.source,
|
|
313
|
-
config
|
|
314
|
-
);
|
|
314
|
+
await regenerateWorkflows(config, cwd);
|
|
315
315
|
|
|
316
316
|
console.log(chalk.green(`✓ Removed environment "${name}"`));
|
|
317
317
|
console.log(
|
package/src/commands/init.js
CHANGED
|
@@ -28,6 +28,8 @@ import {
|
|
|
28
28
|
promptServerDeployment,
|
|
29
29
|
buildServerEnvEntry,
|
|
30
30
|
getDockerEnvSecrets,
|
|
31
|
+
applyInitTriggerDefaults,
|
|
32
|
+
formatMultiEnvTriggerReminder,
|
|
31
33
|
SSH_BASED,
|
|
32
34
|
} from '../deployment/init-prompts.js';
|
|
33
35
|
import {
|
|
@@ -452,6 +454,8 @@ export function registerInitCommand(program) {
|
|
|
452
454
|
defaultEnvironment = picked.defaultEnvironment;
|
|
453
455
|
}
|
|
454
456
|
|
|
457
|
+
applyInitTriggerDefaults(environments, deploy, defaultEnvironment);
|
|
458
|
+
|
|
455
459
|
const version = await getProjectVersion(cwd);
|
|
456
460
|
let hasDocker =
|
|
457
461
|
(detectedFrontend?.hasDocker || detectedBackend?.hasDocker) ?? false;
|
|
@@ -571,6 +575,16 @@ export function registerInitCommand(program) {
|
|
|
571
575
|
console.log(' • .github/workflows/deployhub-rollback.yml');
|
|
572
576
|
console.log(' • .env.example');
|
|
573
577
|
console.log('');
|
|
578
|
+
|
|
579
|
+
if (deploy.length >= 2 && defaultEnvironment) {
|
|
580
|
+
console.log(
|
|
581
|
+
chalk.yellow(
|
|
582
|
+
formatMultiEnvTriggerReminder(String(defaultEnvironment), deploy)
|
|
583
|
+
)
|
|
584
|
+
);
|
|
585
|
+
console.log('');
|
|
586
|
+
}
|
|
587
|
+
|
|
574
588
|
printAuthorFooter();
|
|
575
589
|
});
|
|
576
590
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
2
|
import { loadConfig, loadEnv } from '../core/config.js';
|
|
3
|
+
import { getEnabledEnvironmentNames } from '../core/environments.js';
|
|
3
4
|
import {
|
|
4
5
|
writeWorkflowFile,
|
|
5
6
|
DEPLOY_WORKFLOW_FILENAME,
|
|
@@ -22,8 +23,10 @@ export function registerSyncWorkflowsCommand(program) {
|
|
|
22
23
|
const config = await loadConfig(cwd);
|
|
23
24
|
|
|
24
25
|
const storage = config.storage || [];
|
|
25
|
-
const deploy = config.deploy || [];
|
|
26
26
|
const environments = config.environments || {};
|
|
27
|
+
// Prefer enabled environments over legacy deploy[] so every reachable env
|
|
28
|
+
// gets its secrets into the regenerated workflow env blocks.
|
|
29
|
+
const deploy = getEnabledEnvironmentNames(config);
|
|
27
30
|
const cliSource = config.cli?.source;
|
|
28
31
|
|
|
29
32
|
await writeWorkflowFile(storage, deploy, environments, cwd, cliSource, config);
|
package/src/core/config.js
CHANGED
|
@@ -290,7 +290,7 @@ export function migrateConfigToEnvironments(raw) {
|
|
|
290
290
|
newEnvironments.default = {
|
|
291
291
|
enabled: true,
|
|
292
292
|
method,
|
|
293
|
-
trigger: '
|
|
293
|
+
trigger: 'push',
|
|
294
294
|
config: flatConfig,
|
|
295
295
|
};
|
|
296
296
|
for (const key of FLAT_DEPLOY_KEYS) {
|
|
@@ -323,7 +323,7 @@ export function migrateConfigToEnvironments(raw) {
|
|
|
323
323
|
newEnvironments[defaultEnvironment] = {
|
|
324
324
|
enabled: true,
|
|
325
325
|
method: 'ssh',
|
|
326
|
-
trigger: '
|
|
326
|
+
trigger: 'push',
|
|
327
327
|
config: {},
|
|
328
328
|
};
|
|
329
329
|
}
|
|
@@ -539,6 +539,57 @@ export function buildServerEnvEntry(
|
|
|
539
539
|
};
|
|
540
540
|
}
|
|
541
541
|
|
|
542
|
+
/**
|
|
543
|
+
* Apply init-time trigger defaults after environments are collected.
|
|
544
|
+
* - Exactly one env → always `push` (git push = auto-deploy).
|
|
545
|
+
* - Two or more → grandfathered/default gets `push`; all others stay `manual`.
|
|
546
|
+
*
|
|
547
|
+
* @param {Record<string, { trigger?: string }>} environments
|
|
548
|
+
* @param {string[]} deployNames
|
|
549
|
+
* @param {string|undefined|null} defaultEnvironment
|
|
550
|
+
*/
|
|
551
|
+
export function applyInitTriggerDefaults(environments, deployNames, defaultEnvironment) {
|
|
552
|
+
if (deployNames.length === 1 && environments[deployNames[0]]) {
|
|
553
|
+
environments[deployNames[0]].trigger = 'push';
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
if (deployNames.length >= 2 && defaultEnvironment) {
|
|
557
|
+
for (const name of deployNames) {
|
|
558
|
+
if (!environments[name]) continue;
|
|
559
|
+
environments[name].trigger =
|
|
560
|
+
name === defaultEnvironment ? 'push' : 'manual';
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* End-of-init reminder for multi-env setups (grandfathered = push, others = manual).
|
|
567
|
+
* @param {string} grandfathered
|
|
568
|
+
* @param {string[]} allEnvNames
|
|
569
|
+
* @returns {string}
|
|
570
|
+
*/
|
|
571
|
+
export function formatMultiEnvTriggerReminder(grandfathered, allEnvNames) {
|
|
572
|
+
const others = allEnvNames.filter((n) => n !== grandfathered);
|
|
573
|
+
const otherList =
|
|
574
|
+
others.length > 0 ? others.map((n) => `"${n}"`).join(', ') : '(none)';
|
|
575
|
+
const exampleEnv = others[0] || '<env-name>';
|
|
576
|
+
return [
|
|
577
|
+
'─────────────────────────────────────────────',
|
|
578
|
+
`By default, only your first environment ("${grandfathered}")`,
|
|
579
|
+
`auto-deploys on push. Your other environment(s) — ${otherList} — are set to manual and will only deploy via:`,
|
|
580
|
+
' deployhub deploy --env <name>',
|
|
581
|
+
'or GitHub Actions → Run workflow.',
|
|
582
|
+
'',
|
|
583
|
+
'To make an environment auto-deploy on push instead, open',
|
|
584
|
+
'deployhub.config.json and change its "trigger" to "push":',
|
|
585
|
+
' "environments": {',
|
|
586
|
+
` "${exampleEnv}": { "trigger": "push", ... }`,
|
|
587
|
+
' }',
|
|
588
|
+
'Then run: deployhub sync-workflows',
|
|
589
|
+
'─────────────────────────────────────────────',
|
|
590
|
+
].join('\n');
|
|
591
|
+
}
|
|
592
|
+
|
|
542
593
|
/**
|
|
543
594
|
* @param {Awaited<ReturnType<typeof promptServerDeployment>>} deployAnswers
|
|
544
595
|
* @returns {Record<string, string>|null}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'fs-extra';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import yaml from 'js-yaml';
|
|
4
|
+
import { fileURLToPath } from 'url';
|
|
4
5
|
import { getWorkflowHeaderComment } from './author.js';
|
|
5
6
|
import {
|
|
6
7
|
generateDeploymentEnvSection,
|
|
@@ -135,6 +136,34 @@ export function getCliInstallSpec(cliSource) {
|
|
|
135
136
|
return normalized;
|
|
136
137
|
}
|
|
137
138
|
|
|
139
|
+
/**
|
|
140
|
+
* Version/range suitable as a package.json dependency VALUE for this CLI
|
|
141
|
+
* (key is already NPM_PACKAGE — do not embed the package name again).
|
|
142
|
+
*
|
|
143
|
+
* @param {string} [cliSource]
|
|
144
|
+
* @returns {string}
|
|
145
|
+
*/
|
|
146
|
+
export function getCliPackageJsonDependencyVersion(cliSource) {
|
|
147
|
+
const normalized = normalizeCliSource(cliSource);
|
|
148
|
+
if (normalized === DEFAULT_NPM_CLI_SOURCE) {
|
|
149
|
+
try {
|
|
150
|
+
const pkgPath = path.join(
|
|
151
|
+
path.dirname(fileURLToPath(import.meta.url)),
|
|
152
|
+
'../../package.json'
|
|
153
|
+
);
|
|
154
|
+
const pkg = fs.readJsonSync(pkgPath);
|
|
155
|
+
if (typeof pkg.version === 'string' && pkg.version.trim()) {
|
|
156
|
+
return `^${pkg.version.trim()}`;
|
|
157
|
+
}
|
|
158
|
+
} catch {
|
|
159
|
+
// fall through
|
|
160
|
+
}
|
|
161
|
+
return 'latest';
|
|
162
|
+
}
|
|
163
|
+
// github: / file: specs are valid package.json dependency values as-is
|
|
164
|
+
return getCliInstallSpec(cliSource);
|
|
165
|
+
}
|
|
166
|
+
|
|
138
167
|
/**
|
|
139
168
|
* Shell command to run deployhub build from the installed scoped package.
|
|
140
169
|
* Uses node directly so it works reliably when installed from a private GitHub repo.
|
|
@@ -287,31 +316,51 @@ function upsertWorkflowEnvLine(envVars, lhs, valueExpr) {
|
|
|
287
316
|
envVars.add(`${linePrefix}${valueExpr}`);
|
|
288
317
|
}
|
|
289
318
|
|
|
319
|
+
/**
|
|
320
|
+
* Enabled environment names from the live `environments` map (preferred over
|
|
321
|
+
* a possibly-stale `deploy[]` argument passed into workflow generators).
|
|
322
|
+
* @param {Record<string, { type?: string, method?: string }>} environments
|
|
323
|
+
* @returns {string[]}
|
|
324
|
+
*/
|
|
325
|
+
function listEnabledEnvironmentNames(environments) {
|
|
326
|
+
return Object.keys(environments || {}).filter((n) => isEnvEnabled(environments[n]));
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Push-triggered enabled envs — same set `pipelineDeployTargets` deploys in GHA.
|
|
331
|
+
* @param {Record<string, { type?: string, method?: string }>} environments
|
|
332
|
+
* @returns {string[]}
|
|
333
|
+
*/
|
|
334
|
+
function listPushEnvironmentNames(environments) {
|
|
335
|
+
return listEnabledEnvironmentNames(environments).filter(
|
|
336
|
+
(n) => getEnvTrigger(environments[n]) === 'push'
|
|
337
|
+
);
|
|
338
|
+
}
|
|
339
|
+
|
|
290
340
|
/**
|
|
291
341
|
* Shared env entries for deploy and rollback workflows (same secret resolution).
|
|
292
|
-
* Multi-env:
|
|
293
|
-
*
|
|
294
|
-
*
|
|
295
|
-
*
|
|
296
|
-
*
|
|
342
|
+
* Multi-env: each environment contributes its own CI secret names (grandfathered
|
|
343
|
+
* unprefixed SSH_HOST, or PRODUCTION_SSH_HOST, etc.). Prefixed envs are NOT
|
|
344
|
+
* last-wins-mapped onto unprefixed keys — that would overwrite the grandfathered
|
|
345
|
+
* binding and leave production looking fine in YAML while development silently
|
|
346
|
+
* inherits the wrong credentials. `applyEnvSecretOverlay` remaps PREFIX_* →
|
|
347
|
+
* unprefixed names at deploy time for non-grandfathered targets.
|
|
297
348
|
*
|
|
298
349
|
* @param {string[]} storageProviders
|
|
299
|
-
* @param {string[]} deployEnvironments
|
|
350
|
+
* @param {string[]} deployEnvironments — environments whose secrets to inject
|
|
300
351
|
* @param {Record<string, { type?: string, method?: string }>} environments
|
|
301
352
|
* @param {import('../core/config.js').DeployHubConfig} [config]
|
|
302
|
-
* @param {{ mapForEnv?: string|null }} [options] — when set, only map that env's secrets to unprefixed keys
|
|
303
353
|
* @returns {Set<string>}
|
|
304
354
|
*/
|
|
305
355
|
export function buildWorkflowEnvEntries(
|
|
306
356
|
storageProviders,
|
|
307
357
|
deployEnvironments,
|
|
308
358
|
environments,
|
|
309
|
-
config = null
|
|
310
|
-
options = {}
|
|
359
|
+
config = null
|
|
311
360
|
) {
|
|
312
361
|
/** @type {Set<string>} */
|
|
313
362
|
const envVars = new Set([
|
|
314
|
-
`DEPLOYHUB_ENV: ${
|
|
363
|
+
`DEPLOYHUB_ENV: ${deployEnvironments[0] || 'production'}`,
|
|
315
364
|
]);
|
|
316
365
|
|
|
317
366
|
for (const provider of storageProviders) {
|
|
@@ -321,13 +370,9 @@ export function buildWorkflowEnvEntries(
|
|
|
321
370
|
}
|
|
322
371
|
}
|
|
323
372
|
|
|
324
|
-
const targets = options.mapForEnv
|
|
325
|
-
? [options.mapForEnv]
|
|
326
|
-
: deployEnvironments;
|
|
327
|
-
|
|
328
373
|
const cfg = { ...(config || {}), environments };
|
|
329
374
|
|
|
330
|
-
for (const envName of
|
|
375
|
+
for (const envName of deployEnvironments) {
|
|
331
376
|
const env = environments[envName];
|
|
332
377
|
if (!env) continue;
|
|
333
378
|
|
|
@@ -338,26 +383,26 @@ export function buildWorkflowEnvEntries(
|
|
|
338
383
|
const secretName = envUsesPrefixedSecrets(envName, cfg)
|
|
339
384
|
? prefixSecretKey(envName, key)
|
|
340
385
|
: key;
|
|
341
|
-
//
|
|
342
|
-
|
|
343
|
-
upsertWorkflowEnvLine(envVars, secretName, `\${{ secrets.${secretName} }}`);
|
|
344
|
-
}
|
|
345
|
-
// Unprefixed mapping for CLI defaults (last target wins in static YAML;
|
|
346
|
-
// applyEnvSecretOverlay restores the correct env's values at deploy time).
|
|
347
|
-
upsertWorkflowEnvLine(envVars, key, `\${{ secrets.${secretName} }}`);
|
|
386
|
+
// Bind process.env[secretName] for this environment (prefixed or grandfathered).
|
|
387
|
+
upsertWorkflowEnvLine(envVars, secretName, `\${{ secrets.${secretName} }}`);
|
|
348
388
|
}
|
|
349
389
|
}
|
|
350
390
|
|
|
351
|
-
applyKubernetesWorkflowEnv(
|
|
391
|
+
applyKubernetesWorkflowEnv(deployEnvironments, environments, envVars);
|
|
352
392
|
return envVars;
|
|
353
393
|
}
|
|
354
394
|
|
|
355
395
|
/**
|
|
396
|
+
* Choice options for workflow_dispatch — enabled environments only, plus `all`.
|
|
397
|
+
* Disabled envs are omitted so selecting them cannot waste a CI run.
|
|
398
|
+
*
|
|
356
399
|
* @param {Record<string, unknown>} environments
|
|
357
400
|
* @returns {string}
|
|
358
401
|
*/
|
|
359
402
|
function formatEnvironmentChoiceOptions(environments) {
|
|
360
|
-
const names = Object.keys(environments || {})
|
|
403
|
+
const names = Object.keys(environments || {}).filter((n) =>
|
|
404
|
+
isEnvEnabled(environments[n])
|
|
405
|
+
);
|
|
361
406
|
const options = [...names, 'all'];
|
|
362
407
|
return options.map((n) => ` - ${n}`).join('\n');
|
|
363
408
|
}
|
|
@@ -412,25 +457,40 @@ export function generateWorkflowYaml(
|
|
|
412
457
|
config = null
|
|
413
458
|
) {
|
|
414
459
|
const envNames = Object.keys(environments || {});
|
|
460
|
+
// Secret injection must follow live environments (same as pipelineDeployTargets),
|
|
461
|
+
// not a possibly-stale deploy[] argument — otherwise push-deployed envs missing
|
|
462
|
+
// from deploy[] get no secrets in the job env block.
|
|
463
|
+
const enabledEnvs = listEnabledEnvironmentNames(environments);
|
|
464
|
+
const pushEnvs = listPushEnvironmentNames(environments);
|
|
415
465
|
const allDeployNames =
|
|
416
|
-
|
|
466
|
+
enabledEnvs.length > 0
|
|
467
|
+
? enabledEnvs
|
|
468
|
+
: deployEnvironments.length > 0
|
|
469
|
+
? deployEnvironments
|
|
470
|
+
: envNames;
|
|
417
471
|
|
|
418
|
-
//
|
|
419
|
-
const pushEnvs = allDeployNames.filter(
|
|
420
|
-
(n) => isEnvEnabled(environments[n]) && getEnvTrigger(environments[n]) === 'push'
|
|
421
|
-
);
|
|
422
|
-
|
|
423
|
-
// Secrets for build job: storage + all push envs (or default if none are push).
|
|
472
|
+
// Build step: union of secrets for every push-triggered env (build deploys all of them).
|
|
424
473
|
const buildSecretEnvs =
|
|
425
474
|
pushEnvs.length > 0 ? pushEnvs : allDeployNames.slice(0, 1);
|
|
426
475
|
|
|
427
|
-
|
|
476
|
+
// workflow_dispatch step: union for ALL enabled envs (dropdown can pick any / all).
|
|
477
|
+
const dispatchSecretEnvs = allDeployNames;
|
|
478
|
+
|
|
479
|
+
const buildEnvVars = buildWorkflowEnvEntries(
|
|
428
480
|
storageProviders,
|
|
429
481
|
buildSecretEnvs,
|
|
430
482
|
environments,
|
|
431
483
|
config
|
|
432
484
|
);
|
|
433
|
-
const
|
|
485
|
+
const buildEnvBlock = formatWorkflowEnvBlock(buildEnvVars);
|
|
486
|
+
|
|
487
|
+
const dispatchEnvVars = buildWorkflowEnvEntries(
|
|
488
|
+
storageProviders,
|
|
489
|
+
dispatchSecretEnvs,
|
|
490
|
+
environments,
|
|
491
|
+
config
|
|
492
|
+
);
|
|
493
|
+
const dispatchEnvBlock = formatWorkflowEnvBlock(dispatchEnvVars);
|
|
434
494
|
|
|
435
495
|
const installSpec = getCliInstallSpec(cliSource);
|
|
436
496
|
const backendSteps = getBackendSetupSteps(config);
|
|
@@ -467,7 +527,7 @@ ${envChoiceOptions}
|
|
|
467
527
|
? ` - name: Deploy (workflow_dispatch)
|
|
468
528
|
if: github.event_name == 'workflow_dispatch'
|
|
469
529
|
env:
|
|
470
|
-
${
|
|
530
|
+
${dispatchEnvBlock}
|
|
471
531
|
run: |
|
|
472
532
|
ENV_INPUT="\${{ inputs.environment }}"
|
|
473
533
|
if [ -z "$ENV_INPUT" ] || [ "$ENV_INPUT" = "all" ]; then
|
|
@@ -497,7 +557,7 @@ ${kubernetesSteps}${githubGitConfigStep} - name: Install project dependenci
|
|
|
497
557
|
- name: Build (and auto-deploy push-triggered envs)
|
|
498
558
|
run: ${getCliBuildCommand()}
|
|
499
559
|
env:
|
|
500
|
-
${
|
|
560
|
+
${buildEnvBlock}
|
|
501
561
|
${manualDeployStep}`;
|
|
502
562
|
|
|
503
563
|
return workflow;
|
|
@@ -529,10 +589,13 @@ export function generateRollbackWorkflowYaml(
|
|
|
529
589
|
config = null
|
|
530
590
|
) {
|
|
531
591
|
const envNames = Object.keys(environments || {});
|
|
592
|
+
const enabledEnvs = listEnabledEnvironmentNames(environments);
|
|
532
593
|
const allDeployNames =
|
|
533
|
-
|
|
534
|
-
?
|
|
535
|
-
:
|
|
594
|
+
enabledEnvs.length > 0
|
|
595
|
+
? enabledEnvs
|
|
596
|
+
: deployEnvironments.length > 0
|
|
597
|
+
? deployEnvironments
|
|
598
|
+
: envNames.filter((n) => isEnvEnabled(environments[n]));
|
|
536
599
|
|
|
537
600
|
const envVars = buildWorkflowEnvEntries(
|
|
538
601
|
storageProviders,
|
|
@@ -727,11 +790,14 @@ export function expectedWorkflowSecretKeysFromConfig(config, kind = 'rollback')
|
|
|
727
790
|
/** @type {string[]} */
|
|
728
791
|
let targets;
|
|
729
792
|
if (kind === 'deploy') {
|
|
730
|
-
const
|
|
731
|
-
const
|
|
793
|
+
const pushEnvs = listPushEnvironmentNames(environments);
|
|
794
|
+
const enabled = listEnabledEnvironmentNames(environments);
|
|
795
|
+
// Deploy workflow Build step uses push envs; doctor also flags dispatch-needed
|
|
796
|
+
// secrets by using the broader enabled set via kind === 'rollback' / checklist.
|
|
732
797
|
targets = pushEnvs.length > 0 ? pushEnvs : enabled.slice(0, 1);
|
|
733
798
|
} else {
|
|
734
|
-
targets = allNames;
|
|
799
|
+
targets = allNames.length > 0 ? listEnabledEnvironmentNames(environments) : allNames;
|
|
800
|
+
if (targets.length === 0) targets = allNames;
|
|
735
801
|
}
|
|
736
802
|
|
|
737
803
|
const entries = buildWorkflowEnvEntries(
|
|
@@ -785,7 +851,7 @@ export function detectWorkflowConfigDrift(yamlText, config, filename = DEPLOY_WO
|
|
|
785
851
|
return { drifted: false, missingEnvs, missingSecrets, summary: '' };
|
|
786
852
|
}
|
|
787
853
|
|
|
788
|
-
const envNames =
|
|
854
|
+
const envNames = listEnabledEnvironmentNames(config.environments || {});
|
|
789
855
|
const root = /** @type {Record<string, any>} */ (parsed);
|
|
790
856
|
const options = root?.on?.workflow_dispatch?.inputs?.environment?.options;
|
|
791
857
|
|
|
@@ -883,7 +949,9 @@ export async function addDeployhubToPackageJson(cliSource, cwd = process.cwd())
|
|
|
883
949
|
|
|
884
950
|
const pkg = await fs.readJson(pkgPath);
|
|
885
951
|
pkg.devDependencies = pkg.devDependencies || {};
|
|
886
|
-
|
|
952
|
+
// package.json value must be a semver range / "latest" / git URL — never "name@version"
|
|
953
|
+
// (that form is only for `npm install <spec>` via getCliInstallSpec).
|
|
954
|
+
pkg.devDependencies[NPM_PACKAGE] = getCliPackageJsonDependencyVersion(cliSource);
|
|
887
955
|
delete pkg.devDependencies.deployhub;
|
|
888
956
|
pkg.scripts = pkg.scripts || {};
|
|
889
957
|
pkg.scripts['deployhub:build'] = 'deployhub build';
|