@akash-chowdhury-24/deployhub 1.0.15 → 2.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 +50 -55
- package/package.json +1 -1
- package/src/commands/doctor.js +1 -141
- package/src/commands/init.js +25 -156
- package/src/core/config.js +2 -13
- package/src/core/stages.js +0 -11
- package/src/deployment/index.js +0 -72
- package/src/rollback/engine.js +6 -39
- package/src/utils/github-actions.js +6 -96
- package/src/deployment/providers/platforms/_shared.js +0 -167
- package/src/deployment/providers/platforms/aws-amplify.js +0 -361
- package/src/deployment/providers/platforms/azure-static-web-apps.js +0 -68
- package/src/deployment/providers/platforms/cloudflare-pages.js +0 -103
- package/src/deployment/providers/platforms/firebase-app-hosting.js +0 -95
- package/src/deployment/providers/platforms/firebase-hosting.js +0 -99
- package/src/deployment/providers/platforms/index.js +0 -44
- package/src/deployment/providers/platforms/netlify.js +0 -102
- package/src/deployment/providers/platforms/vercel.js +0 -92
- package/src/utils/firebase-config-generator.js +0 -35
- package/src/utils/init-platform.js +0 -236
- package/src/utils/platform-env.js +0 -132
package/src/deployment/index.js
CHANGED
|
@@ -4,7 +4,6 @@ import { createEc2Provider } from './providers/ec2.js';
|
|
|
4
4
|
import { createAzureVmProvider } from './providers/azure-vm.js';
|
|
5
5
|
import { createGcpVmProvider } from './providers/gcp-vm.js';
|
|
6
6
|
import { createKubernetesProvider } from './providers/kubernetes.js';
|
|
7
|
-
import { createPlatformProvider } from './providers/platforms/index.js';
|
|
8
7
|
import { createLogger } from '../logger/index.js';
|
|
9
8
|
|
|
10
9
|
/** @type {Record<string, Function>} */
|
|
@@ -17,25 +16,6 @@ const PROVIDER_FACTORIES = {
|
|
|
17
16
|
kubernetes: createKubernetesProvider,
|
|
18
17
|
};
|
|
19
18
|
|
|
20
|
-
/**
|
|
21
|
-
* @param {Record<string, unknown>} environment
|
|
22
|
-
* @returns {boolean}
|
|
23
|
-
*/
|
|
24
|
-
function isPlatformDeployment(environment) {
|
|
25
|
-
return environment.deploymentType === 'platform';
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* @param {Record<string, unknown>} environment
|
|
30
|
-
* @returns {boolean}
|
|
31
|
-
*/
|
|
32
|
-
function isHybridEnvironment(environment) {
|
|
33
|
-
return (
|
|
34
|
-
environment.frontendDeploymentType === 'platform' &&
|
|
35
|
-
(environment.backendDeploymentType === 'server' || !!environment.type)
|
|
36
|
-
);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
19
|
/**
|
|
40
20
|
* @param {string} type
|
|
41
21
|
* @param {import('../core/config.js').DeployHubConfig} config
|
|
@@ -48,10 +28,6 @@ export function getDeploymentProvider(type, config, envName, env = process.env)
|
|
|
48
28
|
throw new Error(`Environment "${envName}" not found in config`);
|
|
49
29
|
}
|
|
50
30
|
|
|
51
|
-
if (isPlatformDeployment(environment)) {
|
|
52
|
-
return createPlatformProvider(environment.platform, config, envName, env);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
31
|
const providerType = type || environment.type;
|
|
56
32
|
const factory = PROVIDER_FACTORIES[providerType];
|
|
57
33
|
if (!factory) {
|
|
@@ -81,34 +57,6 @@ export async function deployToAll(config, artifactDir, envNames) {
|
|
|
81
57
|
throw new Error(`Environment "${envName}" not found in config`);
|
|
82
58
|
}
|
|
83
59
|
|
|
84
|
-
if (isHybridEnvironment(envConfig)) {
|
|
85
|
-
log.info(`Deploying hybrid target ${envName} (platform frontend + server backend)...`);
|
|
86
|
-
|
|
87
|
-
const platformProvider = createPlatformProvider(
|
|
88
|
-
envConfig.platform,
|
|
89
|
-
config,
|
|
90
|
-
envName
|
|
91
|
-
);
|
|
92
|
-
await platformProvider.deploy(artifactDir);
|
|
93
|
-
log.success(`Frontend deployed to ${envConfig.platform}`);
|
|
94
|
-
|
|
95
|
-
const serverProvider = getDeploymentProvider(envConfig.type, config, envName);
|
|
96
|
-
await serverProvider.deploy(artifactDir);
|
|
97
|
-
log.success(`Backend deployed via ${envConfig.type}`);
|
|
98
|
-
|
|
99
|
-
deployed.push(envName);
|
|
100
|
-
continue;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (isPlatformDeployment(envConfig)) {
|
|
104
|
-
const provider = createPlatformProvider(envConfig.platform, config, envName);
|
|
105
|
-
log.info(`Deploying to ${envName} (${envConfig.platform})...`);
|
|
106
|
-
await provider.deploy(artifactDir);
|
|
107
|
-
deployed.push(envName);
|
|
108
|
-
log.success(`Deployed to ${envName}`);
|
|
109
|
-
continue;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
60
|
const provider = getDeploymentProvider(envConfig.type, config, envName);
|
|
113
61
|
log.info(`Deploying to ${envName} (${envConfig.type})...`);
|
|
114
62
|
await provider.deploy(artifactDir);
|
|
@@ -128,26 +76,6 @@ export async function rollbackAll(config, artifactDir, envNames) {
|
|
|
128
76
|
const targets = envNames || config.deploy || [];
|
|
129
77
|
for (const envName of targets) {
|
|
130
78
|
const envConfig = config.environments[envName];
|
|
131
|
-
|
|
132
|
-
if (isHybridEnvironment(envConfig)) {
|
|
133
|
-
const platformProvider = createPlatformProvider(
|
|
134
|
-
envConfig.platform,
|
|
135
|
-
config,
|
|
136
|
-
envName
|
|
137
|
-
);
|
|
138
|
-
await platformProvider.rollback(artifactDir);
|
|
139
|
-
|
|
140
|
-
const serverProvider = getDeploymentProvider(envConfig.type, config, envName);
|
|
141
|
-
await serverProvider.rollback(artifactDir);
|
|
142
|
-
continue;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
if (isPlatformDeployment(envConfig)) {
|
|
146
|
-
const provider = createPlatformProvider(envConfig.platform, config, envName);
|
|
147
|
-
await provider.rollback(artifactDir);
|
|
148
|
-
continue;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
79
|
const provider = getDeploymentProvider(envConfig.type, config, envName);
|
|
152
80
|
await provider.rollback(artifactDir);
|
|
153
81
|
}
|
package/src/rollback/engine.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { downloadFromFirst } from '../storage/index.js';
|
|
2
|
-
import {
|
|
2
|
+
import { getDeploymentProvider } from '../deployment/index.js';
|
|
3
3
|
import { extractArtifact } from '../artifact/engine.js';
|
|
4
4
|
import { createLogger } from '../logger/index.js';
|
|
5
5
|
import fs from 'fs-extra';
|
|
@@ -10,48 +10,15 @@ import path from 'path';
|
|
|
10
10
|
* @param {string} artifactDir
|
|
11
11
|
* @param {string} envName
|
|
12
12
|
*/
|
|
13
|
-
async function
|
|
13
|
+
async function rollbackTarget(config, artifactDir, envName) {
|
|
14
14
|
const envConfig = config.environments[envName];
|
|
15
15
|
if (!envConfig) {
|
|
16
16
|
throw new Error(`Environment "${envName}" not found in config`);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
const data = await fs.readJson(deploymentPath);
|
|
22
|
-
const deployments = data.deployments || data.platformDeployments || [];
|
|
23
|
-
const record = deployments.find((d) => d.environmentName === envName) || data.lastDeployment;
|
|
24
|
-
if (record?.platform) {
|
|
25
|
-
const log = createLogger('rollback');
|
|
26
|
-
log.info(
|
|
27
|
-
`Rolling back ${envName} on ${record.platform} (deploy ${record.deployId || record.deploymentId || 'previous'})...`
|
|
28
|
-
);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
if (envConfig.deploymentType === 'platform' || envConfig.frontendDeploymentType === 'platform') {
|
|
33
|
-
const platform = envConfig.platform;
|
|
34
|
-
if (!platform) {
|
|
35
|
-
throw new Error(`No platform configured for environment "${envName}"`);
|
|
36
|
-
}
|
|
37
|
-
const provider = createPlatformProvider(platform, config, envName);
|
|
38
|
-
await provider.rollback(artifactDir);
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (
|
|
43
|
-
envConfig.frontendDeploymentType === 'platform' &&
|
|
44
|
-
(envConfig.backendDeploymentType === 'server' || envConfig.type)
|
|
45
|
-
) {
|
|
46
|
-
const platformProvider = createPlatformProvider(envConfig.platform, config, envName);
|
|
47
|
-
await platformProvider.rollback(artifactDir);
|
|
48
|
-
const { getDeploymentProvider } = await import('../deployment/index.js');
|
|
49
|
-
const serverProvider = getDeploymentProvider(envConfig.type, config, envName);
|
|
50
|
-
await serverProvider.rollback(artifactDir);
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
19
|
+
const log = createLogger('rollback');
|
|
20
|
+
log.info(`Rolling back ${envName} (${envConfig.type || 'server'})...`);
|
|
53
21
|
|
|
54
|
-
const { getDeploymentProvider } = await import('../deployment/index.js');
|
|
55
22
|
const provider = getDeploymentProvider(envConfig.type, config, envName);
|
|
56
23
|
await provider.rollback(artifactDir);
|
|
57
24
|
}
|
|
@@ -90,9 +57,9 @@ export async function rollbackToVersion(config, version, cwd = process.cwd()) {
|
|
|
90
57
|
return artifactDir;
|
|
91
58
|
}
|
|
92
59
|
|
|
93
|
-
log.info('
|
|
60
|
+
log.info('Redeploying previous artifact to server targets...');
|
|
94
61
|
for (const envName of targets) {
|
|
95
|
-
await
|
|
62
|
+
await rollbackTarget(config, artifactDir, envName);
|
|
96
63
|
}
|
|
97
64
|
|
|
98
65
|
log.success(`Rollback to v${version} complete`);
|
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import fs from 'fs-extra';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import {
|
|
4
|
-
PLATFORM_ENV_MAP,
|
|
5
|
-
PLATFORM_CLI_MAP,
|
|
6
|
-
PLATFORM_CHOICES,
|
|
7
|
-
getPlatformEnvExample,
|
|
8
|
-
} from './platform-env.js';
|
|
9
3
|
import { getWorkflowHeaderComment } from './author.js';
|
|
10
4
|
|
|
11
5
|
/** @typedef {'aws'|'azure'|'gcp'|'gdrive'|'dropbox'|'local'|'ftp'|'ssh'} ProviderEnvKey */
|
|
@@ -47,10 +41,6 @@ const PROVIDER_LABELS = {
|
|
|
47
41
|
ssh: 'SSH Deployment',
|
|
48
42
|
};
|
|
49
43
|
|
|
50
|
-
const PLATFORM_LABELS = Object.fromEntries(
|
|
51
|
-
PLATFORM_CHOICES.map(({ name, value }) => [value, name])
|
|
52
|
-
);
|
|
53
|
-
|
|
54
44
|
const ENV_VAR_DEFAULTS = {
|
|
55
45
|
AWS_REGION: 'us-east-1',
|
|
56
46
|
FTP_PORT: '21',
|
|
@@ -208,54 +198,6 @@ function getBackendSetupSteps(config) {
|
|
|
208
198
|
return steps;
|
|
209
199
|
}
|
|
210
200
|
|
|
211
|
-
/**
|
|
212
|
-
* @param {Record<string, unknown>[]} environments
|
|
213
|
-
* @returns {string[]}
|
|
214
|
-
*/
|
|
215
|
-
function getPlatformInstallSteps(environments) {
|
|
216
|
-
/** @type {Set<string>} */
|
|
217
|
-
const steps = new Set();
|
|
218
|
-
|
|
219
|
-
for (const env of environments) {
|
|
220
|
-
if (env.deploymentType !== 'platform' && env.frontendDeploymentType !== 'platform') {
|
|
221
|
-
continue;
|
|
222
|
-
}
|
|
223
|
-
const platform = env.platform;
|
|
224
|
-
if (!platform) continue;
|
|
225
|
-
const cli = PLATFORM_CLI_MAP[platform];
|
|
226
|
-
if (cli?.globalInstall) {
|
|
227
|
-
steps.add(` - name: Install ${platform} CLI\n run: ${cli.globalInstall}`);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
return Array.from(steps);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* @param {string[]} deployEnvironments
|
|
236
|
-
* @param {Record<string, Record<string, unknown>>} environments
|
|
237
|
-
*/
|
|
238
|
-
function collectPlatformEnvVars(deployEnvironments, environments) {
|
|
239
|
-
/** @type {Set<string>} */
|
|
240
|
-
const envVars = new Set();
|
|
241
|
-
|
|
242
|
-
for (const envName of deployEnvironments) {
|
|
243
|
-
const env = environments[envName];
|
|
244
|
-
if (!env) continue;
|
|
245
|
-
|
|
246
|
-
if (env.deploymentType === 'platform' || env.frontendDeploymentType === 'platform') {
|
|
247
|
-
const platform = env.platform;
|
|
248
|
-
if (!platform) continue;
|
|
249
|
-
const keys = PLATFORM_ENV_MAP[platform] || [];
|
|
250
|
-
for (const key of keys) {
|
|
251
|
-
envVars.add(`${key}: \${{ secrets.${key} }}`);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
return envVars;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
201
|
/**
|
|
260
202
|
* @param {string[]} storageProviders
|
|
261
203
|
* @param {string[]} deployEnvironments
|
|
@@ -285,11 +227,9 @@ export function generateWorkflowYaml(
|
|
|
285
227
|
const env = environments[envName];
|
|
286
228
|
if (!env) continue;
|
|
287
229
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
envVars.add(`${key}: \${{ secrets.${key} }}`);
|
|
292
|
-
}
|
|
230
|
+
const keys = PROVIDER_ENV_MAP[env.type] || [];
|
|
231
|
+
for (const key of keys) {
|
|
232
|
+
envVars.add(`${key}: \${{ secrets.${key} }}`);
|
|
293
233
|
}
|
|
294
234
|
|
|
295
235
|
if (env.type === 'ssh' && config) {
|
|
@@ -302,10 +242,6 @@ export function generateWorkflowYaml(
|
|
|
302
242
|
}
|
|
303
243
|
}
|
|
304
244
|
|
|
305
|
-
for (const line of collectPlatformEnvVars(deployEnvironments, environments)) {
|
|
306
|
-
envVars.add(line);
|
|
307
|
-
}
|
|
308
|
-
|
|
309
245
|
const envBlock = Array.from(envVars)
|
|
310
246
|
.map((line) => ` ${line}`)
|
|
311
247
|
.join('\n');
|
|
@@ -317,11 +253,6 @@ export function generateWorkflowYaml(
|
|
|
317
253
|
? `${getGithubGitConfigStep()}\n`
|
|
318
254
|
: '';
|
|
319
255
|
|
|
320
|
-
const envList = deployEnvironments
|
|
321
|
-
.map((name) => environments[name])
|
|
322
|
-
.filter(Boolean);
|
|
323
|
-
const platformSteps = getPlatformInstallSteps(envList).join('\n');
|
|
324
|
-
|
|
325
256
|
const projectType = config?.projectType || 'frontend';
|
|
326
257
|
const installDepsCommand =
|
|
327
258
|
projectType === 'backend' || projectType === 'both'
|
|
@@ -342,7 +273,7 @@ ${uniqueBackendSteps ? `${uniqueBackendSteps}\n` : ''} - uses: actions/setu
|
|
|
342
273
|
node-version: '20'
|
|
343
274
|
${githubGitConfigStep} - name: Install project dependencies
|
|
344
275
|
run: ${installDepsCommand}
|
|
345
|
-
|
|
276
|
+
- name: Install DeployHub CLI
|
|
346
277
|
run: npm install ${installSpec} --no-save
|
|
347
278
|
- run: ${getCliBuildCommand()}
|
|
348
279
|
env:
|
|
@@ -481,16 +412,8 @@ export function getRequiredSecrets(
|
|
|
481
412
|
const env = environments[envName];
|
|
482
413
|
if (!env) continue;
|
|
483
414
|
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
if (platform) {
|
|
487
|
-
const keys = PLATFORM_ENV_MAP[platform] || [];
|
|
488
|
-
keys.forEach((k) => secrets.add(k));
|
|
489
|
-
}
|
|
490
|
-
} else {
|
|
491
|
-
const keys = PROVIDER_ENV_MAP[env.type] || [];
|
|
492
|
-
keys.forEach((k) => secrets.add(k));
|
|
493
|
-
}
|
|
415
|
+
const keys = PROVIDER_ENV_MAP[env.type] || [];
|
|
416
|
+
keys.forEach((k) => secrets.add(k));
|
|
494
417
|
|
|
495
418
|
if (env.type === 'ssh' && config) {
|
|
496
419
|
const projectType = config.projectType || 'frontend';
|
|
@@ -560,19 +483,6 @@ export function generateEnvExampleContent(
|
|
|
560
483
|
const env = environments[envName];
|
|
561
484
|
if (!env) continue;
|
|
562
485
|
|
|
563
|
-
if (env.deploymentType === 'platform' || env.frontendDeploymentType === 'platform') {
|
|
564
|
-
const platform = env.platform;
|
|
565
|
-
if (platform) {
|
|
566
|
-
const examples = getPlatformEnvExample(platform);
|
|
567
|
-
addSection(
|
|
568
|
-
PLATFORM_LABELS[platform] || platform,
|
|
569
|
-
Object.keys(examples),
|
|
570
|
-
examples
|
|
571
|
-
);
|
|
572
|
-
}
|
|
573
|
-
continue;
|
|
574
|
-
}
|
|
575
|
-
|
|
576
486
|
const keys = PROVIDER_ENV_MAP[env.type] || [];
|
|
577
487
|
if (keys.length > 0) {
|
|
578
488
|
addSection(PROVIDER_LABELS[env.type] || env.type, keys);
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
import fs from 'fs-extra';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import { execa } from 'execa';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @param {import('../../../core/config.js').DeployHubConfig} config
|
|
7
|
-
* @returns {string}
|
|
8
|
-
*/
|
|
9
|
-
export function getBuildOutputDir(config) {
|
|
10
|
-
if (config.projectType === 'both' && config.frontend?.buildOutput) {
|
|
11
|
-
return config.frontend.buildOutput;
|
|
12
|
-
}
|
|
13
|
-
return config.buildOutput || 'dist';
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* @param {import('../../../core/config.js').DeployHubConfig} config
|
|
18
|
-
* @param {string} [cwd]
|
|
19
|
-
* @returns {string}
|
|
20
|
-
*/
|
|
21
|
-
export function resolveBuildOutputPath(config, cwd = process.cwd()) {
|
|
22
|
-
return path.join(cwd, getBuildOutputDir(config));
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* @param {string} artifactDir
|
|
27
|
-
* @param {Record<string, unknown>} record
|
|
28
|
-
* @param {string} [environmentName]
|
|
29
|
-
*/
|
|
30
|
-
export async function saveDeploymentRecord(artifactDir, record, environmentName = '') {
|
|
31
|
-
const deploymentPath = path.join(artifactDir, 'deployment.json');
|
|
32
|
-
let existing = { targets: [], deployedAt: new Date().toISOString(), deployments: [] };
|
|
33
|
-
|
|
34
|
-
if (await fs.pathExists(deploymentPath)) {
|
|
35
|
-
existing = await fs.readJson(deploymentPath);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const timestamp = new Date().toISOString();
|
|
39
|
-
const envName = record.environmentName || environmentName || record.envName || '';
|
|
40
|
-
|
|
41
|
-
/** @type {Record<string, unknown>} */
|
|
42
|
-
const entry = {
|
|
43
|
-
...record,
|
|
44
|
-
platform: record.platform,
|
|
45
|
-
deployId: record.deployId || record.deploymentId || '',
|
|
46
|
-
deployUrl: record.deployUrl || record.deploymentUrl || '',
|
|
47
|
-
deploymentId: record.deploymentId || record.deployId || '',
|
|
48
|
-
deploymentUrl: record.deploymentUrl || record.deployUrl || '',
|
|
49
|
-
timestamp,
|
|
50
|
-
environmentName: envName,
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
const deployments = existing.deployments || existing.platformDeployments || [];
|
|
54
|
-
deployments.push(entry);
|
|
55
|
-
|
|
56
|
-
await fs.writeJson(
|
|
57
|
-
deploymentPath,
|
|
58
|
-
{
|
|
59
|
-
...existing,
|
|
60
|
-
deployments,
|
|
61
|
-
platformDeployments: deployments,
|
|
62
|
-
lastDeployment: entry,
|
|
63
|
-
deployedAt: timestamp,
|
|
64
|
-
},
|
|
65
|
-
{ spaces: 2 }
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* @param {string} artifactDir
|
|
71
|
-
* @returns {Promise<Record<string, unknown>|null>}
|
|
72
|
-
*/
|
|
73
|
-
export async function readLastPlatformDeployment(artifactDir) {
|
|
74
|
-
const deploymentPath = path.join(artifactDir, 'deployment.json');
|
|
75
|
-
if (!(await fs.pathExists(deploymentPath))) return null;
|
|
76
|
-
const data = await fs.readJson(deploymentPath);
|
|
77
|
-
const deployments = data.deployments || data.platformDeployments || [];
|
|
78
|
-
return data.lastDeployment || deployments.at(-1) || null;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* @param {string} artifactDir
|
|
83
|
-
* @returns {Promise<Record<string, unknown>|null>}
|
|
84
|
-
*/
|
|
85
|
-
export async function readPreviousPlatformDeployment(artifactDir) {
|
|
86
|
-
const deploymentPath = path.join(artifactDir, 'deployment.json');
|
|
87
|
-
if (!(await fs.pathExists(deploymentPath))) return null;
|
|
88
|
-
const data = await fs.readJson(deploymentPath);
|
|
89
|
-
const deployments = data.deployments || data.platformDeployments || [];
|
|
90
|
-
if (deployments.length < 2) return null;
|
|
91
|
-
return deployments[deployments.length - 2];
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* @param {string} artifactDir
|
|
96
|
-
* @param {string} [environmentName]
|
|
97
|
-
* @returns {Promise<Record<string, unknown>|null>}
|
|
98
|
-
*/
|
|
99
|
-
export async function readDeploymentForEnvironment(artifactDir, environmentName) {
|
|
100
|
-
const deploymentPath = path.join(artifactDir, 'deployment.json');
|
|
101
|
-
if (!(await fs.pathExists(deploymentPath))) return null;
|
|
102
|
-
const data = await fs.readJson(deploymentPath);
|
|
103
|
-
const deployments = data.deployments || data.platformDeployments || [];
|
|
104
|
-
if (environmentName) {
|
|
105
|
-
const match = deployments.filter((d) => d.environmentName === environmentName);
|
|
106
|
-
return match.at(-1) || null;
|
|
107
|
-
}
|
|
108
|
-
return data.lastDeployment || deployments.at(-1) || null;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* @param {string} command
|
|
113
|
-
* @param {string} [cwd]
|
|
114
|
-
* @param {Record<string, string>} [env]
|
|
115
|
-
*/
|
|
116
|
-
export async function runCli(command, cwd = process.cwd(), env = process.env) {
|
|
117
|
-
const [cmd, ...args] = command.split(' ');
|
|
118
|
-
const result = await execa(cmd, args, {
|
|
119
|
-
cwd,
|
|
120
|
-
env: { ...process.env, ...env },
|
|
121
|
-
shell: true,
|
|
122
|
-
reject: false,
|
|
123
|
-
});
|
|
124
|
-
return result;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/**
|
|
128
|
-
* @param {string} binary
|
|
129
|
-
* @returns {Promise<boolean>}
|
|
130
|
-
*/
|
|
131
|
-
export async function isCliInstalled(binary) {
|
|
132
|
-
try {
|
|
133
|
-
const result = await execa(binary, ['--version'], { reject: false });
|
|
134
|
-
return result.exitCode === 0;
|
|
135
|
-
} catch {
|
|
136
|
-
return false;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* @param {string} url
|
|
142
|
-
* @returns {Promise<boolean>}
|
|
143
|
-
*/
|
|
144
|
-
export async function checkUrlHealth(url) {
|
|
145
|
-
try {
|
|
146
|
-
const axios = (await import('axios')).default;
|
|
147
|
-
const response = await axios.get(url, {
|
|
148
|
-
timeout: 30000,
|
|
149
|
-
validateStatus: () => true,
|
|
150
|
-
});
|
|
151
|
-
return response.status >= 200 && response.status < 400;
|
|
152
|
-
} catch {
|
|
153
|
-
return false;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
export default {
|
|
158
|
-
getBuildOutputDir,
|
|
159
|
-
resolveBuildOutputPath,
|
|
160
|
-
saveDeploymentRecord,
|
|
161
|
-
readLastPlatformDeployment,
|
|
162
|
-
readPreviousPlatformDeployment,
|
|
163
|
-
readDeploymentForEnvironment,
|
|
164
|
-
runCli,
|
|
165
|
-
isCliInstalled,
|
|
166
|
-
checkUrlHealth,
|
|
167
|
-
};
|