@akash-chowdhury-24/deployhub 1.0.16 → 2.0.2
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 +264 -59
- package/package.json +4 -3
- package/src/commands/doctor.js +168 -170
- package/src/commands/init.js +80 -371
- package/src/commands/rollback.js +1 -1
- package/src/core/config.js +17 -13
- package/src/core/stages.js +0 -11
- package/src/deployment/deployment-env.js +625 -0
- package/src/deployment/index.js +0 -72
- package/src/deployment/init-helpers.js +389 -0
- package/src/deployment/init-prompts.js +432 -0
- package/src/deployment/providers/azure-vm.js +85 -2
- package/src/deployment/providers/docker.js +101 -8
- package/src/deployment/providers/ec2.js +88 -2
- package/src/deployment/providers/gcp-vm.js +89 -2
- package/src/deployment/providers/kubernetes.js +104 -7
- package/src/deployment/providers/ssh.js +21 -4
- package/src/utils/github-actions.js +28 -131
- package/src/utils/rollback/engine.js +69 -0
- package/src/deployment/providers/platforms/_shared.js +0 -167
- package/src/deployment/providers/platforms/aws-amplify.js +0 -367
- 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/rollback/engine.js +0 -102
- 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
|
@@ -1,236 +0,0 @@
|
|
|
1
|
-
import inquirer from 'inquirer';
|
|
2
|
-
import chalk from 'chalk';
|
|
3
|
-
import fs from 'fs-extra';
|
|
4
|
-
import path from 'path';
|
|
5
|
-
import { execa } from 'execa';
|
|
6
|
-
import {
|
|
7
|
-
PLATFORM_CHOICES,
|
|
8
|
-
PLATFORM_COMPARISON,
|
|
9
|
-
getPlatformEnvExample,
|
|
10
|
-
} from './platform-env.js';
|
|
11
|
-
import { ensureFirebaseJson } from './firebase-config-generator.js';
|
|
12
|
-
import { appendEnv } from '../core/config.js';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @param {string} platform
|
|
16
|
-
* @param {string} projectName
|
|
17
|
-
* @param {string} buildOutput
|
|
18
|
-
* @param {string} [cwd]
|
|
19
|
-
* @returns {Promise<Record<string, unknown>>}
|
|
20
|
-
*/
|
|
21
|
-
export async function promptPlatformQuestions(
|
|
22
|
-
platform,
|
|
23
|
-
projectName,
|
|
24
|
-
buildOutput,
|
|
25
|
-
cwd = process.cwd()
|
|
26
|
-
) {
|
|
27
|
-
/** @type {Record<string, unknown>} */
|
|
28
|
-
const config = { platform };
|
|
29
|
-
|
|
30
|
-
switch (platform) {
|
|
31
|
-
case 'vercel': {
|
|
32
|
-
const answers = await inquirer.prompt([
|
|
33
|
-
{
|
|
34
|
-
type: 'input',
|
|
35
|
-
name: 'projectName',
|
|
36
|
-
message: 'Vercel project name:',
|
|
37
|
-
default: projectName,
|
|
38
|
-
},
|
|
39
|
-
{
|
|
40
|
-
type: 'confirm',
|
|
41
|
-
name: 'vercelLinked',
|
|
42
|
-
message: 'Have you already linked this project with Vercel?',
|
|
43
|
-
default: fs.existsSync(path.join(cwd, '.vercel', 'project.json')),
|
|
44
|
-
},
|
|
45
|
-
]);
|
|
46
|
-
config.projectName = answers.projectName;
|
|
47
|
-
|
|
48
|
-
if (!answers.vercelLinked) {
|
|
49
|
-
console.log(chalk.gray('Running vercel link — follow the prompts...'));
|
|
50
|
-
try {
|
|
51
|
-
await execa('vercel', ['link'], { cwd, stdio: 'inherit' });
|
|
52
|
-
} catch {
|
|
53
|
-
console.log(
|
|
54
|
-
chalk.yellow(
|
|
55
|
-
'Could not run vercel link automatically. Run it manually, then add VERCEL_ORG_ID and VERCEL_PROJECT_ID to .env'
|
|
56
|
-
)
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
break;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
case 'netlify': {
|
|
64
|
-
const answers = await inquirer.prompt([
|
|
65
|
-
{
|
|
66
|
-
type: 'input',
|
|
67
|
-
name: 'siteId',
|
|
68
|
-
message: 'Netlify site ID (from Netlify dashboard):',
|
|
69
|
-
},
|
|
70
|
-
]);
|
|
71
|
-
config.siteId = answers.siteId;
|
|
72
|
-
break;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
case 'cloudflare-pages': {
|
|
76
|
-
const answers = await inquirer.prompt([
|
|
77
|
-
{
|
|
78
|
-
type: 'input',
|
|
79
|
-
name: 'projectName',
|
|
80
|
-
message: 'Cloudflare Pages project name:',
|
|
81
|
-
default: projectName,
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
type: 'input',
|
|
85
|
-
name: 'accountId',
|
|
86
|
-
message: 'Cloudflare account ID (from dashboard):',
|
|
87
|
-
},
|
|
88
|
-
]);
|
|
89
|
-
config.projectName = answers.projectName;
|
|
90
|
-
config.accountId = answers.accountId;
|
|
91
|
-
break;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
case 'aws-amplify': {
|
|
95
|
-
const answers = await inquirer.prompt([
|
|
96
|
-
{
|
|
97
|
-
type: 'input',
|
|
98
|
-
name: 'appId',
|
|
99
|
-
message: 'Amplify App ID (from AWS console):',
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
type: 'input',
|
|
103
|
-
name: 'region',
|
|
104
|
-
message: 'AWS region:',
|
|
105
|
-
default: 'us-east-1',
|
|
106
|
-
},
|
|
107
|
-
{
|
|
108
|
-
type: 'input',
|
|
109
|
-
name: 'branch',
|
|
110
|
-
message: 'Amplify branch name (auto-created for manual zip deploys):',
|
|
111
|
-
default: 'main',
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
type: 'confirm',
|
|
115
|
-
name: 'githubConnected',
|
|
116
|
-
message: 'GitHub already connected to Amplify?',
|
|
117
|
-
default: true,
|
|
118
|
-
},
|
|
119
|
-
]);
|
|
120
|
-
config.appId = answers.appId;
|
|
121
|
-
config.region = answers.region;
|
|
122
|
-
config.branch = answers.branch;
|
|
123
|
-
config.githubConnected = answers.githubConnected;
|
|
124
|
-
break;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
case 'azure-static-web-apps': {
|
|
128
|
-
const answers = await inquirer.prompt([
|
|
129
|
-
{
|
|
130
|
-
type: 'input',
|
|
131
|
-
name: 'resourceName',
|
|
132
|
-
message: 'Resource name:',
|
|
133
|
-
default: projectName,
|
|
134
|
-
},
|
|
135
|
-
]);
|
|
136
|
-
config.resourceName = answers.resourceName;
|
|
137
|
-
break;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
case 'firebase-hosting': {
|
|
141
|
-
const answers = await inquirer.prompt([
|
|
142
|
-
{
|
|
143
|
-
type: 'input',
|
|
144
|
-
name: 'projectId',
|
|
145
|
-
message: 'Firebase project ID:',
|
|
146
|
-
default: projectName,
|
|
147
|
-
},
|
|
148
|
-
]);
|
|
149
|
-
config.projectId = answers.projectId;
|
|
150
|
-
await ensureFirebaseJson(buildOutput, cwd);
|
|
151
|
-
console.log(chalk.green('✓ firebase.json generated'));
|
|
152
|
-
break;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
case 'firebase-app-hosting': {
|
|
156
|
-
const answers = await inquirer.prompt([
|
|
157
|
-
{
|
|
158
|
-
type: 'input',
|
|
159
|
-
name: 'projectId',
|
|
160
|
-
message: 'Firebase project ID:',
|
|
161
|
-
default: projectName,
|
|
162
|
-
},
|
|
163
|
-
{
|
|
164
|
-
type: 'input',
|
|
165
|
-
name: 'backendName',
|
|
166
|
-
message: 'Backend name:',
|
|
167
|
-
default: `${projectName}-backend`,
|
|
168
|
-
},
|
|
169
|
-
]);
|
|
170
|
-
config.projectId = answers.projectId;
|
|
171
|
-
config.backendName = answers.backendName;
|
|
172
|
-
break;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
default:
|
|
176
|
-
break;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
return config;
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
* @param {string} platform
|
|
184
|
-
* @param {string} [cwd]
|
|
185
|
-
*/
|
|
186
|
-
export async function appendPlatformEnvExample(platform, cwd = process.cwd()) {
|
|
187
|
-
const examples = getPlatformEnvExample(platform);
|
|
188
|
-
await appendEnv(examples, cwd);
|
|
189
|
-
|
|
190
|
-
const envExamplePath = path.join(cwd, '.env.example');
|
|
191
|
-
if (!(await fs.pathExists(envExamplePath))) return;
|
|
192
|
-
|
|
193
|
-
let content = await fs.readFile(envExamplePath, 'utf-8');
|
|
194
|
-
const sectionHeader = `\n# ${platform} deployment\n`;
|
|
195
|
-
const lines = Object.keys(examples)
|
|
196
|
-
.map((key) => `${key}=`)
|
|
197
|
-
.join('\n');
|
|
198
|
-
|
|
199
|
-
if (!content.includes(`${platform} deployment`)) {
|
|
200
|
-
content += `${sectionHeader}${lines}\n`;
|
|
201
|
-
await fs.writeFile(envExamplePath, content);
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
export function showPlatformComparison() {
|
|
206
|
-
console.log('');
|
|
207
|
-
console.log(chalk.bold('Platform comparison:'));
|
|
208
|
-
console.log(chalk.gray(PLATFORM_COMPARISON));
|
|
209
|
-
console.log('');
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* @param {string} platform
|
|
214
|
-
* @param {string} projectName
|
|
215
|
-
* @returns {string}
|
|
216
|
-
*/
|
|
217
|
-
export function suggestHealthUrl(platform, projectName) {
|
|
218
|
-
const urls = {
|
|
219
|
-
vercel: `https://${projectName}.vercel.app`,
|
|
220
|
-
netlify: `https://${projectName}.netlify.app`,
|
|
221
|
-
'cloudflare-pages': `https://${projectName}.pages.dev`,
|
|
222
|
-
'firebase-hosting': `https://${projectName}.web.app`,
|
|
223
|
-
'firebase-app-hosting': `https://${projectName}.web.app`,
|
|
224
|
-
};
|
|
225
|
-
return urls[platform] || '';
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
export { PLATFORM_CHOICES };
|
|
229
|
-
|
|
230
|
-
export default {
|
|
231
|
-
promptPlatformQuestions,
|
|
232
|
-
appendPlatformEnvExample,
|
|
233
|
-
showPlatformComparison,
|
|
234
|
-
suggestHealthUrl,
|
|
235
|
-
PLATFORM_CHOICES,
|
|
236
|
-
};
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
/** Platform deployment environment variables and CLI metadata. */
|
|
2
|
-
|
|
3
|
-
export const PLATFORM_ENV_MAP = {
|
|
4
|
-
vercel: ['VERCEL_TOKEN', 'VERCEL_ORG_ID', 'VERCEL_PROJECT_ID'],
|
|
5
|
-
netlify: ['NETLIFY_AUTH_TOKEN', 'NETLIFY_SITE_ID'],
|
|
6
|
-
'cloudflare-pages': [
|
|
7
|
-
'CLOUDFLARE_API_TOKEN',
|
|
8
|
-
'CLOUDFLARE_ACCOUNT_ID',
|
|
9
|
-
'CF_PROJECT_NAME',
|
|
10
|
-
],
|
|
11
|
-
'aws-amplify': [
|
|
12
|
-
'AWS_ACCESS_KEY_ID',
|
|
13
|
-
'AWS_SECRET_ACCESS_KEY',
|
|
14
|
-
'AWS_REGION',
|
|
15
|
-
'AMPLIFY_APP_ID',
|
|
16
|
-
],
|
|
17
|
-
'azure-static-web-apps': ['AZURE_STATIC_WEB_APPS_TOKEN'],
|
|
18
|
-
'firebase-hosting': ['FIREBASE_TOKEN', 'FIREBASE_PROJECT_ID'],
|
|
19
|
-
'firebase-app-hosting': [
|
|
20
|
-
'FIREBASE_TOKEN',
|
|
21
|
-
'FIREBASE_PROJECT_ID',
|
|
22
|
-
'FIREBASE_APP_HOSTING_BACKEND',
|
|
23
|
-
],
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
export const PLATFORM_CLI_MAP = {
|
|
27
|
-
vercel: { install: 'vercel', binary: 'vercel', globalInstall: 'npm install -g vercel' },
|
|
28
|
-
netlify: {
|
|
29
|
-
install: 'netlify-cli',
|
|
30
|
-
binary: 'netlify',
|
|
31
|
-
globalInstall: 'npm install -g netlify-cli',
|
|
32
|
-
},
|
|
33
|
-
'cloudflare-pages': {
|
|
34
|
-
install: 'wrangler',
|
|
35
|
-
binary: 'wrangler',
|
|
36
|
-
globalInstall: 'npm install -g wrangler',
|
|
37
|
-
},
|
|
38
|
-
'aws-amplify': {
|
|
39
|
-
install: 'aws-cli',
|
|
40
|
-
binary: 'aws',
|
|
41
|
-
globalInstall: null,
|
|
42
|
-
},
|
|
43
|
-
'azure-static-web-apps': {
|
|
44
|
-
install: '@azure/static-web-apps-cli',
|
|
45
|
-
binary: 'swa',
|
|
46
|
-
globalInstall: 'npm install -g @azure/static-web-apps-cli',
|
|
47
|
-
},
|
|
48
|
-
'firebase-hosting': {
|
|
49
|
-
install: 'firebase-tools',
|
|
50
|
-
binary: 'firebase',
|
|
51
|
-
globalInstall: 'npm install -g firebase-tools',
|
|
52
|
-
},
|
|
53
|
-
'firebase-app-hosting': {
|
|
54
|
-
install: 'firebase-tools',
|
|
55
|
-
binary: 'firebase',
|
|
56
|
-
globalInstall: 'npm install -g firebase-tools',
|
|
57
|
-
},
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
export const PLATFORM_CHOICES = [
|
|
61
|
-
{ name: 'Vercel', value: 'vercel' },
|
|
62
|
-
{ name: 'Netlify', value: 'netlify' },
|
|
63
|
-
{ name: 'Cloudflare Pages', value: 'cloudflare-pages' },
|
|
64
|
-
{ name: 'AWS Amplify', value: 'aws-amplify' },
|
|
65
|
-
{ name: 'Azure Static Web Apps', value: 'azure-static-web-apps' },
|
|
66
|
-
{ name: 'Firebase Hosting', value: 'firebase-hosting' },
|
|
67
|
-
{ name: 'Firebase App Hosting', value: 'firebase-app-hosting' },
|
|
68
|
-
];
|
|
69
|
-
|
|
70
|
-
export const PLATFORM_COMPARISON = `
|
|
71
|
-
Platform Best for
|
|
72
|
-
─────────────────────────────────────────────────────────────
|
|
73
|
-
Vercel Next.js (best experience), React
|
|
74
|
-
Netlify React, Vue, Svelte — simplest setup
|
|
75
|
-
Cloudflare Pages Static sites, Astro, React — fastest CDN
|
|
76
|
-
AWS Amplify React, Next.js, Vue, Angular — AWS ecosystem
|
|
77
|
-
Azure Static Web Apps React, Angular, Blazor — Azure ecosystem
|
|
78
|
-
Firebase Hosting Static SPAs — Google ecosystem
|
|
79
|
-
Firebase App Hosting Next.js, Angular with SSR — Google ecosystem
|
|
80
|
-
|
|
81
|
-
All platforms include: free SSL, global CDN, custom domain, auto-deploy
|
|
82
|
-
`;
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* @param {string} platform
|
|
86
|
-
* @returns {Record<string, string>}
|
|
87
|
-
*/
|
|
88
|
-
export function getPlatformEnvExample(platform) {
|
|
89
|
-
const examples = {
|
|
90
|
-
vercel: {
|
|
91
|
-
VERCEL_TOKEN: '',
|
|
92
|
-
VERCEL_ORG_ID: '',
|
|
93
|
-
VERCEL_PROJECT_ID: '',
|
|
94
|
-
},
|
|
95
|
-
netlify: {
|
|
96
|
-
NETLIFY_AUTH_TOKEN: '',
|
|
97
|
-
NETLIFY_SITE_ID: '',
|
|
98
|
-
},
|
|
99
|
-
'cloudflare-pages': {
|
|
100
|
-
CLOUDFLARE_API_TOKEN: '',
|
|
101
|
-
CLOUDFLARE_ACCOUNT_ID: '',
|
|
102
|
-
CF_PROJECT_NAME: '',
|
|
103
|
-
},
|
|
104
|
-
'aws-amplify': {
|
|
105
|
-
AWS_ACCESS_KEY_ID: '',
|
|
106
|
-
AWS_SECRET_ACCESS_KEY: '',
|
|
107
|
-
AWS_REGION: 'us-east-1',
|
|
108
|
-
AMPLIFY_APP_ID: '',
|
|
109
|
-
},
|
|
110
|
-
'azure-static-web-apps': {
|
|
111
|
-
AZURE_STATIC_WEB_APPS_TOKEN: '',
|
|
112
|
-
},
|
|
113
|
-
'firebase-hosting': {
|
|
114
|
-
FIREBASE_TOKEN: '',
|
|
115
|
-
FIREBASE_PROJECT_ID: '',
|
|
116
|
-
},
|
|
117
|
-
'firebase-app-hosting': {
|
|
118
|
-
FIREBASE_TOKEN: '',
|
|
119
|
-
FIREBASE_PROJECT_ID: '',
|
|
120
|
-
FIREBASE_APP_HOSTING_BACKEND: '',
|
|
121
|
-
},
|
|
122
|
-
};
|
|
123
|
-
return examples[platform] || {};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
export default {
|
|
127
|
-
PLATFORM_ENV_MAP,
|
|
128
|
-
PLATFORM_CLI_MAP,
|
|
129
|
-
PLATFORM_CHOICES,
|
|
130
|
-
PLATFORM_COMPARISON,
|
|
131
|
-
getPlatformEnvExample,
|
|
132
|
-
};
|