@akash-chowdhury-24/deployhub 2.0.0 → 2.0.3

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.
@@ -1,6 +1,11 @@
1
1
  import fs from 'fs-extra';
2
2
  import path from 'path';
3
3
  import { getWorkflowHeaderComment } from './author.js';
4
+ import {
5
+ generateDeploymentEnvSection,
6
+ getDeploymentSecretKeys,
7
+ DEPLOYMENT_ENV_KEYS,
8
+ } from '../deployment/deployment-env.js';
4
9
 
5
10
  /** @typedef {'aws'|'azure'|'gcp'|'gdrive'|'dropbox'|'local'|'ftp'|'ssh'} ProviderEnvKey */
6
11
 
@@ -22,23 +27,27 @@ const PROVIDER_ENV_MAP = {
22
27
  dropbox: ['DROPBOX_ACCESS_TOKEN'],
23
28
  local: [],
24
29
  ftp: ['FTP_HOST', 'FTP_USER', 'FTP_PASSWORD'],
25
- ssh: ['SSH_HOST', 'SSH_USER', 'SSH_KEY'],
30
+ ssh: DEPLOYMENT_ENV_KEYS.ssh,
31
+ docker: DEPLOYMENT_ENV_KEYS.docker,
32
+ ec2: DEPLOYMENT_ENV_KEYS.ec2,
33
+ 'azure-vm': DEPLOYMENT_ENV_KEYS['azure-vm'],
34
+ 'gcp-vm': DEPLOYMENT_ENV_KEYS['gcp-vm'],
35
+ kubernetes: DEPLOYMENT_ENV_KEYS.kubernetes,
26
36
  };
27
37
 
28
- const BACKEND_SSH_ENV_VARS = [
29
- 'SSH_DEPLOY_PATH',
30
- 'SSH_APP_NAME',
31
- 'SSH_PORT',
32
- ];
33
-
34
38
  const PROVIDER_LABELS = {
35
39
  aws: 'AWS S3',
36
40
  azure: 'Azure Blob',
37
- gcp: 'GCP',
41
+ gcp: 'GCP Storage',
38
42
  gdrive: 'Google Drive',
39
43
  dropbox: 'Dropbox',
40
44
  ftp: 'FTP',
41
45
  ssh: 'SSH Deployment',
46
+ docker: 'Docker Deployment',
47
+ ec2: 'AWS EC2 Deployment',
48
+ 'azure-vm': 'Azure VM Deployment',
49
+ 'gcp-vm': 'GCP VM Deployment',
50
+ kubernetes: 'Kubernetes Deployment',
42
51
  };
43
52
 
44
53
  const ENV_VAR_DEFAULTS = {
@@ -46,6 +55,7 @@ const ENV_VAR_DEFAULTS = {
46
55
  FTP_PORT: '21',
47
56
  FTP_PATH: '/uploads',
48
57
  SSH_DEPLOY_PATH: '/var/www/app',
58
+ SSH_SSH_PORT: '22',
49
59
  SMTP_PORT: '587',
50
60
  };
51
61
 
@@ -227,19 +237,10 @@ export function generateWorkflowYaml(
227
237
  const env = environments[envName];
228
238
  if (!env) continue;
229
239
 
230
- const keys = PROVIDER_ENV_MAP[env.type] || [];
240
+ const keys = getDeploymentSecretKeys(env.type, config);
231
241
  for (const key of keys) {
232
242
  envVars.add(`${key}: \${{ secrets.${key} }}`);
233
243
  }
234
-
235
- if (env.type === 'ssh' && config) {
236
- const projectType = config.projectType || 'frontend';
237
- if (projectType === 'backend' || projectType === 'both') {
238
- for (const key of BACKEND_SSH_ENV_VARS) {
239
- envVars.add(`${key}: \${{ secrets.${key} }}`);
240
- }
241
- }
242
- }
243
244
  }
244
245
 
245
246
  const envBlock = Array.from(envVars)
@@ -412,15 +413,8 @@ export function getRequiredSecrets(
412
413
  const env = environments[envName];
413
414
  if (!env) continue;
414
415
 
415
- const keys = PROVIDER_ENV_MAP[env.type] || [];
416
+ const keys = getDeploymentSecretKeys(env.type, config);
416
417
  keys.forEach((k) => secrets.add(k));
417
-
418
- if (env.type === 'ssh' && config) {
419
- const projectType = config.projectType || 'frontend';
420
- if (projectType === 'backend' || projectType === 'both') {
421
- BACKEND_SSH_ENV_VARS.forEach((k) => secrets.add(k));
422
- }
423
- }
424
418
  }
425
419
 
426
420
  return Array.from(secrets);
@@ -481,18 +475,11 @@ export function generateEnvExampleContent(
481
475
 
482
476
  for (const envName of deployEnvironments) {
483
477
  const env = environments[envName];
484
- if (!env) continue;
485
-
486
- const keys = PROVIDER_ENV_MAP[env.type] || [];
487
- if (keys.length > 0) {
488
- addSection(PROVIDER_LABELS[env.type] || env.type, keys);
489
- }
478
+ if (!env?.type) continue;
490
479
 
491
- if (env.type === 'ssh' && config) {
492
- const projectType = config.projectType || 'frontend';
493
- if (projectType === 'backend' || projectType === 'both') {
494
- addSection('SSH Deployment (backend)', BACKEND_SSH_ENV_VARS);
495
- }
480
+ const deploySection = generateDeploymentEnvSection(env.type, config, environments);
481
+ if (deploySection) {
482
+ sections.push(`${deploySection}\n`);
496
483
  }
497
484
  }
498
485
 
@@ -1,12 +1,12 @@
1
- import { downloadFromFirst } from '../storage/index.js';
2
- import { getDeploymentProvider } from '../deployment/index.js';
3
- import { extractArtifact } from '../artifact/engine.js';
4
- import { createLogger } from '../logger/index.js';
1
+ import { downloadFromFirst } from '../../storage/index.js';
2
+ import { getDeploymentProvider } from '../../deployment/index.js';
3
+ import { extractArtifact } from '../../artifact/engine.js';
4
+ import { createLogger } from '../../logger/index.js';
5
5
  import fs from 'fs-extra';
6
6
  import path from 'path';
7
7
 
8
8
  /**
9
- * @param {import('../core/config.js').DeployHubConfig} config
9
+ * @param {import('../../core/config.js').DeployHubConfig} config
10
10
  * @param {string} artifactDir
11
11
  * @param {string} envName
12
12
  */
@@ -24,7 +24,7 @@ async function rollbackTarget(config, artifactDir, envName) {
24
24
  }
25
25
 
26
26
  /**
27
- * @param {import('../core/config.js').DeployHubConfig} config
27
+ * @param {import('../../core/config.js').DeployHubConfig} config
28
28
  * @param {string} version
29
29
  * @param {string} [cwd]
30
30
  */
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Wrap a value for safe interpolation into a POSIX shell command string.
3
+ * Uses single quotes; embedded single quotes are escaped as '\''.
4
+ * @param {string} value
5
+ * @returns {string}
6
+ */
7
+ export function shellQuote(value) {
8
+ if (value == null) return "''";
9
+ return `'${String(value).replace(/'/g, `'\\''`)}'`;
10
+ }
11
+
12
+ /**
13
+ * @param {string} command
14
+ * @param {number|null|undefined} code
15
+ * @param {string} [stderr]
16
+ * @param {string} [stdout]
17
+ * @returns {string}
18
+ */
19
+ export function formatRemoteCommandFailure(command, code, stderr, stdout) {
20
+ const cmdName = command.trim().split(/\s+/)[0] || 'command';
21
+ const detail = (stderr || stdout || '').trim();
22
+ return `Deploy failed: ${cmdName} exited with code ${code}${detail ? `: ${detail}` : ''}`;
23
+ }
24
+
25
+ /**
26
+ * Remote shell command that verifies write access to a deploy directory.
27
+ * @param {string} deployPath
28
+ * @returns {string}
29
+ */
30
+ export function buildDeployPathWriteTestCommand(deployPath) {
31
+ const dir = shellQuote(deployPath);
32
+ const testFile = shellQuote(`${deployPath}/.deployhub-write-test`);
33
+ return `mkdir -p ${dir} && touch ${testFile} && rm -f ${testFile}`;
34
+ }
35
+
36
+ /**
37
+ * @param {string} deployPath
38
+ * @param {string} sshUser
39
+ * @param {string} [errorDetail]
40
+ * @returns {string}
41
+ */
42
+ export function formatDeployPathWriteFailure(deployPath, sshUser, errorDetail) {
43
+ const reason = errorDetail ? ` (${errorDetail.trim()})` : '';
44
+ const quotedPath = shellQuote(deployPath);
45
+ return (
46
+ `Cannot write to ${deployPath} on the server${reason}.\n` +
47
+ ` Run this on your server first:\n` +
48
+ ` sudo mkdir -p ${quotedPath}\n` +
49
+ ` sudo chown ${sshUser}:${sshUser} ${quotedPath}\n` +
50
+ ` (replace ${sshUser} with your actual SSH_USER if different)`
51
+ );
52
+ }
53
+
54
+ /**
55
+ * @param {string} name
56
+ * @returns {string}
57
+ */
58
+ export function toKebabCase(name) {
59
+ return name
60
+ .trim()
61
+ .replace(/\s+/g, '-')
62
+ .replace(/[^a-zA-Z0-9-_]/g, '')
63
+ .toLowerCase();
64
+ }