@akash-chowdhury-24/deployhub 1.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/LICENSE +21 -0
- package/README.md +176 -0
- package/install.ps1 +55 -0
- package/install.sh +99 -0
- package/package.json +86 -0
- package/src/adapters/dotnet.adapter.js +41 -0
- package/src/adapters/go.adapter.js +40 -0
- package/src/adapters/index.js +48 -0
- package/src/adapters/java.adapter.js +46 -0
- package/src/adapters/node.adapter.js +77 -0
- package/src/adapters/php.adapter.js +43 -0
- package/src/adapters/python.adapter.js +54 -0
- package/src/adapters/rails.adapter.js +66 -0
- package/src/artifact/engine.js +473 -0
- package/src/cli/index.js +45 -0
- package/src/commands/artifact.js +88 -0
- package/src/commands/build.js +44 -0
- package/src/commands/clean.js +50 -0
- package/src/commands/deploy.js +82 -0
- package/src/commands/doctor.js +630 -0
- package/src/commands/init.js +795 -0
- package/src/commands/logs.js +33 -0
- package/src/commands/rollback.js +50 -0
- package/src/commands/storage.js +116 -0
- package/src/commands/update.js +63 -0
- package/src/commands/verify.js +55 -0
- package/src/core/config.js +168 -0
- package/src/core/pipeline.js +77 -0
- package/src/core/stages.js +210 -0
- package/src/deployment/index.js +156 -0
- package/src/deployment/providers/azure-vm.js +7 -0
- package/src/deployment/providers/docker.js +30 -0
- package/src/deployment/providers/ec2.js +7 -0
- package/src/deployment/providers/gcp-vm.js +7 -0
- package/src/deployment/providers/kubernetes.js +30 -0
- package/src/deployment/providers/platforms/_shared.js +167 -0
- package/src/deployment/providers/platforms/aws-amplify.js +164 -0
- package/src/deployment/providers/platforms/azure-static-web-apps.js +68 -0
- package/src/deployment/providers/platforms/cloudflare-pages.js +103 -0
- package/src/deployment/providers/platforms/firebase-app-hosting.js +95 -0
- package/src/deployment/providers/platforms/firebase-hosting.js +99 -0
- package/src/deployment/providers/platforms/index.js +44 -0
- package/src/deployment/providers/platforms/netlify.js +102 -0
- package/src/deployment/providers/platforms/vercel.js +92 -0
- package/src/deployment/providers/ssh.js +365 -0
- package/src/detectors/angular.js +23 -0
- package/src/detectors/backend.detector.js +304 -0
- package/src/detectors/dotnet.js +18 -0
- package/src/detectors/frontend.detector.js +219 -0
- package/src/detectors/go.js +20 -0
- package/src/detectors/index.js +78 -0
- package/src/detectors/java.js +24 -0
- package/src/detectors/nextjs.js +23 -0
- package/src/detectors/node.js +28 -0
- package/src/detectors/php.js +17 -0
- package/src/detectors/python.js +22 -0
- package/src/detectors/react.js +29 -0
- package/src/detectors/vue.js +23 -0
- package/src/logger/index.js +44 -0
- package/src/notifications/email.js +53 -0
- package/src/notifications/index.js +34 -0
- package/src/notifications/slack.js +18 -0
- package/src/notifications/webhook.js +21 -0
- package/src/rollback/engine.js +102 -0
- package/src/storage/index.js +109 -0
- package/src/storage/providers/aws.js +96 -0
- package/src/storage/providers/azure.js +45 -0
- package/src/storage/providers/dropbox.js +49 -0
- package/src/storage/providers/ftp.js +69 -0
- package/src/storage/providers/gcp.js +45 -0
- package/src/storage/providers/gdrive.js +80 -0
- package/src/storage/providers/local.js +61 -0
- package/src/utils/author.js +141 -0
- package/src/utils/checksums.js +53 -0
- package/src/utils/firebase-config-generator.js +35 -0
- package/src/utils/github-actions.js +389 -0
- package/src/utils/init-platform.js +229 -0
- package/src/utils/nginx.js +34 -0
- package/src/utils/platform-env.js +132 -0
- package/src/utils/version.js +31 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Akash Chowdhury
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# DeployHub
|
|
2
|
+
|
|
3
|
+
Zero-configuration deployment and artifact manager for Node.js projects. When you push to GitHub, DeployHub automatically detects your project type, builds it, creates a versioned artifact, uploads to cloud storage, and optionally deploys to your server.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @akash-chowdhury-24/deployhub
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Or use locally in your project:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install deployhub
|
|
15
|
+
npx @akash-chowdhury-24/deployhub init
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Quick Start
|
|
19
|
+
|
|
20
|
+
### 1. Initialize
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
deployhub init
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
This interactive wizard will:
|
|
27
|
+
|
|
28
|
+
- Detect your framework (React, Vue, Next.js, Node, Python, etc.)
|
|
29
|
+
- Configure build commands and output directory
|
|
30
|
+
- Set up storage providers (AWS, Google Drive, Azure, GCP, Dropbox, Local)
|
|
31
|
+
- Optionally configure deployment targets (SSH, Docker, EC2, Kubernetes, etc.)
|
|
32
|
+
- Generate `deployhub.config.json`
|
|
33
|
+
- Generate `.github/workflows/deployhub.yml`
|
|
34
|
+
- Generate `.env.example`
|
|
35
|
+
|
|
36
|
+
### 2. Configure credentials
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
cp .env.example .env
|
|
40
|
+
# Edit .env with your credentials
|
|
41
|
+
|
|
42
|
+
deployhub storage add aws
|
|
43
|
+
deployhub storage add gdrive
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 3. Run pre-flight checks
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
deployhub doctor
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 4. Deploy
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
deployhub build
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Or push to `main` — GitHub Actions runs `deployhub build` automatically.
|
|
59
|
+
|
|
60
|
+
## Commands
|
|
61
|
+
|
|
62
|
+
| Command | Description |
|
|
63
|
+
|---------|-------------|
|
|
64
|
+
| `deployhub init` | Interactive project setup |
|
|
65
|
+
| `deployhub build` | Full pipeline: detect → install → test → build → artifact → storage → deploy |
|
|
66
|
+
| `deployhub artifact create` | Create artifact from current build |
|
|
67
|
+
| `deployhub artifact list` | List all artifacts |
|
|
68
|
+
| `deployhub artifact restore <version>` | Download and extract an artifact |
|
|
69
|
+
| `deployhub storage add <provider>` | Add storage provider credentials |
|
|
70
|
+
| `deployhub storage list` | List storage providers and connection status |
|
|
71
|
+
| `deployhub deploy` | Deploy latest artifact |
|
|
72
|
+
| `deployhub rollback [version]` | Rollback to a previous version |
|
|
73
|
+
| `deployhub logs` | Show logs from last deployment |
|
|
74
|
+
| `deployhub doctor` | Pre-flight checks |
|
|
75
|
+
| `deployhub verify` | Health check on configured endpoint |
|
|
76
|
+
| `deployhub clean` | Remove old local artifacts |
|
|
77
|
+
| `deployhub update` | Check for CLI updates |
|
|
78
|
+
|
|
79
|
+
## GitHub Secrets
|
|
80
|
+
|
|
81
|
+
Add these secrets in your repository (Settings → Secrets and variables → Actions). Only add secrets for providers you selected during `init`:
|
|
82
|
+
|
|
83
|
+
| Secret | Provider |
|
|
84
|
+
|--------|----------|
|
|
85
|
+
| `AWS_ACCESS_KEY_ID` | AWS S3 |
|
|
86
|
+
| `AWS_SECRET_ACCESS_KEY` | AWS S3 |
|
|
87
|
+
| `AWS_BUCKET` | AWS S3 |
|
|
88
|
+
| `AWS_REGION` | AWS S3 |
|
|
89
|
+
| `GDRIVE_CLIENT_ID` | Google Drive |
|
|
90
|
+
| `GDRIVE_CLIENT_SECRET` | Google Drive |
|
|
91
|
+
| `GDRIVE_REFRESH_TOKEN` | Google Drive |
|
|
92
|
+
| `GDRIVE_FOLDER_ID` | Google Drive |
|
|
93
|
+
| `AZURE_CONNECTION_STRING` | Azure Blob |
|
|
94
|
+
| `AZURE_CONTAINER` | Azure Blob |
|
|
95
|
+
| `GCP_PROJECT_ID` | GCP Storage |
|
|
96
|
+
| `GCP_KEY_FILE` | GCP Storage |
|
|
97
|
+
| `GCP_BUCKET` | GCP Storage |
|
|
98
|
+
| `DROPBOX_ACCESS_TOKEN` | Dropbox |
|
|
99
|
+
| `SSH_HOST` | SSH deployment |
|
|
100
|
+
| `SSH_USER` | SSH deployment |
|
|
101
|
+
| `SSH_KEY` | SSH deployment |
|
|
102
|
+
|
|
103
|
+
## `deployhub doctor` Output
|
|
104
|
+
|
|
105
|
+
The doctor command runs independent checks and always completes without crashing:
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
Checking Git... ✓ Git installed, repo detected, remote set
|
|
109
|
+
Checking Docker... ✓ Docker running
|
|
110
|
+
Checking Build command... ✓ "npm run build" found in package.json
|
|
111
|
+
Checking AWS... ✓ Credentials valid, bucket accessible
|
|
112
|
+
Checking Google Drive... ✓ Connected
|
|
113
|
+
Checking SSH target... ✓ Can reach host
|
|
114
|
+
Checking Health endpoint... ✓ URL reachable (HTTP 200)
|
|
115
|
+
Checking Secrets... ✓ All required env vars present
|
|
116
|
+
Checking GitHub Actions... ✓ Workflow file exists at .github/workflows/deployhub.yml
|
|
117
|
+
Checking Storage write... ✓ Test upload succeeded
|
|
118
|
+
|
|
119
|
+
✓ Ready to deploy (10/10 checks passed)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
If checks fail:
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
Checking AWS... ✗ Missing: AWS_SECRET_ACCESS_KEY
|
|
126
|
+
Checking Health endpoint... ✗ No URL configured
|
|
127
|
+
|
|
128
|
+
8/10 — fix the 2 issues above before deploying
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Artifact Structure
|
|
132
|
+
|
|
133
|
+
Each build creates:
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
artifact/
|
|
137
|
+
{projectName}/
|
|
138
|
+
{YYYY-MM-DD}/
|
|
139
|
+
v{semver}/
|
|
140
|
+
artifact.zip
|
|
141
|
+
metadata.json
|
|
142
|
+
logs.txt
|
|
143
|
+
checksums.txt
|
|
144
|
+
deployment.json
|
|
145
|
+
release-notes.md
|
|
146
|
+
README.md
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Configuration
|
|
150
|
+
|
|
151
|
+
`deployhub.config.json` is generated by `init`. Credentials are **never** stored in this file — only in `.env` or GitHub Secrets.
|
|
152
|
+
|
|
153
|
+
## Pipeline Stages
|
|
154
|
+
|
|
155
|
+
1. **detect** — auto-detect project type
|
|
156
|
+
2. **install** — install dependencies
|
|
157
|
+
3. **test** — run test suite (skippable)
|
|
158
|
+
4. **build** — run build command
|
|
159
|
+
5. **docker** — build Docker image (skippable)
|
|
160
|
+
6. **artifact** — create artifact.zip + metadata
|
|
161
|
+
7. **storage** — upload to all configured providers (parallel)
|
|
162
|
+
8. **deploy** — deploy to configured targets
|
|
163
|
+
9. **verify** — health check after deployment
|
|
164
|
+
10. **notify** — send Slack/email/webhook notifications
|
|
165
|
+
|
|
166
|
+
## Author
|
|
167
|
+
|
|
168
|
+
**Akash Chowdhury**
|
|
169
|
+
📧 akashbumbac24@gmail.com
|
|
170
|
+
💼 [linkedin.com/in/akash-chowdhury-12141a222](https://www.linkedin.com/in/akash-chowdhury-12141a222/)
|
|
171
|
+
|
|
172
|
+
Built with ❤ — if DeployHub saves you time, feel free to connect on LinkedIn.
|
|
173
|
+
|
|
174
|
+
## License
|
|
175
|
+
|
|
176
|
+
MIT
|
package/install.ps1
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# DeployHub install script for Windows
|
|
2
|
+
# Author: Akash Chowdhury — canonical source: src/utils/author.js
|
|
3
|
+
# Repository: https://github.com/Akash-Chowdhury-24/DeployHub
|
|
4
|
+
|
|
5
|
+
$ErrorActionPreference = "Stop"
|
|
6
|
+
|
|
7
|
+
$GitHubRepo = "Akash-Chowdhury-24/DeployHub"
|
|
8
|
+
$BinaryName = "deployhub.exe"
|
|
9
|
+
|
|
10
|
+
function Get-LatestVersion {
|
|
11
|
+
$release = Invoke-RestMethod -Uri "https://api.github.com/repos/$GitHubRepo/releases/latest"
|
|
12
|
+
return $release.tag_name
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function Get-InstallDir {
|
|
16
|
+
$localBin = Join-Path $env:LOCALAPPDATA "Programs\DeployHub"
|
|
17
|
+
if (-not (Test-Path $localBin)) {
|
|
18
|
+
New-Item -ItemType Directory -Path $localBin -Force | Out-Null
|
|
19
|
+
}
|
|
20
|
+
return $localBin
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function Add-ToPath {
|
|
24
|
+
param([string]$Dir)
|
|
25
|
+
$userPath = [Environment]::GetEnvironmentVariable("Path", "User")
|
|
26
|
+
if ($userPath -notlike "*$Dir*") {
|
|
27
|
+
[Environment]::SetEnvironmentVariable("Path", "$userPath;$Dir", "User")
|
|
28
|
+
$env:Path = "$env:Path;$Dir"
|
|
29
|
+
Write-Host "Added $Dir to user PATH"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
$version = Get-LatestVersion
|
|
35
|
+
$assetName = "deployhub-win.exe"
|
|
36
|
+
$url = "https://github.com/$GitHubRepo/releases/download/$version/$assetName"
|
|
37
|
+
$installDir = Get-InstallDir
|
|
38
|
+
$dest = Join-Path $installDir $BinaryName
|
|
39
|
+
|
|
40
|
+
Write-Host "Downloading DeployHub $version for Windows..."
|
|
41
|
+
Invoke-WebRequest -Uri $url -OutFile $dest -UseBasicParsing
|
|
42
|
+
|
|
43
|
+
if (-not (Test-Path $dest) -or (Get-Item $dest).Length -eq 0) {
|
|
44
|
+
throw "Binary download failed"
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
Add-ToPath $installDir
|
|
48
|
+
Write-Host "DeployHub $version installed to $dest"
|
|
49
|
+
& $dest --version
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
Write-Host "Binary install failed ($($_.Exception.Message)). Falling back to npm..." -ForegroundColor Yellow
|
|
53
|
+
npm install -g deployhub@latest
|
|
54
|
+
Write-Host "DeployHub installed via npm."
|
|
55
|
+
}
|
package/install.sh
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# DeployHub install script
|
|
3
|
+
# Author: Akash Chowdhury — canonical source: src/utils/author.js
|
|
4
|
+
# Repository: https://github.com/Akash-Chowdhury-24/DeployHub
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
GITHUB_REPO="Akash-Chowdhury-24/DeployHub"
|
|
9
|
+
INSTALL_DIR="/usr/local/bin"
|
|
10
|
+
BINARY_NAME="deployhub"
|
|
11
|
+
|
|
12
|
+
detect_platform() {
|
|
13
|
+
OS="$(uname -s | tr '[:upper:]' '[:lower:]')"
|
|
14
|
+
ARCH="$(uname -m)"
|
|
15
|
+
|
|
16
|
+
case "$OS" in
|
|
17
|
+
linux)
|
|
18
|
+
case "$ARCH" in
|
|
19
|
+
x86_64|amd64) PLATFORM="linux" ;;
|
|
20
|
+
*) echo "Unsupported Linux architecture: $ARCH" >&2; exit 1 ;;
|
|
21
|
+
esac
|
|
22
|
+
;;
|
|
23
|
+
darwin)
|
|
24
|
+
case "$ARCH" in
|
|
25
|
+
x86_64) PLATFORM="macos" ;;
|
|
26
|
+
arm64|aarch64) PLATFORM="macos-arm64" ;;
|
|
27
|
+
*) echo "Unsupported macOS architecture: $ARCH" >&2; exit 1 ;;
|
|
28
|
+
esac
|
|
29
|
+
;;
|
|
30
|
+
*)
|
|
31
|
+
echo "Unsupported OS: $OS. Use install.ps1 on Windows." >&2
|
|
32
|
+
exit 1
|
|
33
|
+
;;
|
|
34
|
+
esac
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
fetch_latest_version() {
|
|
38
|
+
if command -v curl >/dev/null 2>&1; then
|
|
39
|
+
VERSION=$(curl -fsSL "https://api.github.com/repos/${GITHUB_REPO}/releases/latest" \
|
|
40
|
+
| sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' \
|
|
41
|
+
| head -n 1)
|
|
42
|
+
elif command -v wget >/dev/null 2>&1; then
|
|
43
|
+
VERSION=$(wget -qO- "https://api.github.com/repos/${GITHUB_REPO}/releases/latest" \
|
|
44
|
+
| sed -n 's/.*"tag_name"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' \
|
|
45
|
+
| head -n 1)
|
|
46
|
+
else
|
|
47
|
+
echo "curl or wget is required to download DeployHub." >&2
|
|
48
|
+
exit 1
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
if [ -z "$VERSION" ]; then
|
|
52
|
+
echo "Could not determine latest release version. Falling back to npm install." >&2
|
|
53
|
+
npm install -g deployhub@latest
|
|
54
|
+
echo "DeployHub installed via npm."
|
|
55
|
+
exit 0
|
|
56
|
+
fi
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
download_binary() {
|
|
60
|
+
ASSET="deployhub-${PLATFORM}"
|
|
61
|
+
URL="https://github.com/${GITHUB_REPO}/releases/download/${VERSION}/${ASSET}"
|
|
62
|
+
TMP="$(mktemp)"
|
|
63
|
+
|
|
64
|
+
echo "Downloading DeployHub ${VERSION} (${PLATFORM})..."
|
|
65
|
+
if command -v curl >/dev/null 2>&1; then
|
|
66
|
+
curl -fsSL "$URL" -o "$TMP"
|
|
67
|
+
else
|
|
68
|
+
wget -qO "$TMP" "$URL"
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
if [ ! -s "$TMP" ]; then
|
|
72
|
+
echo "Binary download failed. Falling back to npm install." >&2
|
|
73
|
+
rm -f "$TMP"
|
|
74
|
+
npm install -g deployhub@latest
|
|
75
|
+
echo "DeployHub installed via npm."
|
|
76
|
+
exit 0
|
|
77
|
+
fi
|
|
78
|
+
|
|
79
|
+
if [ "$(id -u)" -eq 0 ]; then
|
|
80
|
+
install -m 755 "$TMP" "${INSTALL_DIR}/${BINARY_NAME}"
|
|
81
|
+
else
|
|
82
|
+
if command -v sudo >/dev/null 2>&1; then
|
|
83
|
+
sudo install -m 755 "$TMP" "${INSTALL_DIR}/${BINARY_NAME}"
|
|
84
|
+
else
|
|
85
|
+
mkdir -p "${HOME}/.local/bin"
|
|
86
|
+
install -m 755 "$TMP" "${HOME}/.local/bin/${BINARY_NAME}"
|
|
87
|
+
echo "Installed to ${HOME}/.local/bin/${BINARY_NAME} — ensure it is on your PATH"
|
|
88
|
+
fi
|
|
89
|
+
fi
|
|
90
|
+
|
|
91
|
+
rm -f "$TMP"
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
detect_platform
|
|
95
|
+
fetch_latest_version
|
|
96
|
+
download_binary
|
|
97
|
+
|
|
98
|
+
echo "DeployHub ${VERSION} installed successfully."
|
|
99
|
+
deployhub --version 2>/dev/null || true
|
package/package.json
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@akash-chowdhury-24/deployhub",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Zero-configuration deployment and artifact manager",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./src/cli/index.js",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"homepage": "https://github.com/Akash-Chowdhury-24/DeployHub#readme",
|
|
9
|
+
"bugs": {
|
|
10
|
+
"url": "https://github.com/Akash-Chowdhury-24/DeployHub/issues"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"deploy",
|
|
14
|
+
"deployment",
|
|
15
|
+
"ci-cd",
|
|
16
|
+
"artifacts",
|
|
17
|
+
"cli",
|
|
18
|
+
"devops",
|
|
19
|
+
"automation"
|
|
20
|
+
],
|
|
21
|
+
"files": [
|
|
22
|
+
"src",
|
|
23
|
+
"install.sh",
|
|
24
|
+
"install.ps1",
|
|
25
|
+
"README.md",
|
|
26
|
+
"LICENSE"
|
|
27
|
+
],
|
|
28
|
+
"bin": {
|
|
29
|
+
"deployhub": "src/cli/index.js"
|
|
30
|
+
},
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "git+https://github.com/Akash-Chowdhury-24/DeployHub.git"
|
|
34
|
+
},
|
|
35
|
+
"scripts": {
|
|
36
|
+
"start": "node src/cli/index.js",
|
|
37
|
+
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
|
|
38
|
+
"prepublishOnly": "npm test",
|
|
39
|
+
"build:bundle": "node scripts/build-bundle.mjs",
|
|
40
|
+
"build:bin": "npm run build:bundle && pkg dist/deployhub.cjs --targets node20-linux-x64,node20-macos-x64,node20-macos-arm64,node20-win-x64 --output dist/deployhub --compress GZip"
|
|
41
|
+
},
|
|
42
|
+
"pkg": {
|
|
43
|
+
"scripts": "dist/deployhub.cjs",
|
|
44
|
+
"assets": [
|
|
45
|
+
"node_modules/ssh2/**/*"
|
|
46
|
+
],
|
|
47
|
+
"outputPath": "dist"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"commander": "^12.0.0",
|
|
51
|
+
"inquirer": "^9.0.0",
|
|
52
|
+
"execa": "^8.0.0",
|
|
53
|
+
"ora": "^8.0.0",
|
|
54
|
+
"chalk": "^5.0.0",
|
|
55
|
+
"archiver": "^6.0.0",
|
|
56
|
+
"fs-extra": "^11.0.0",
|
|
57
|
+
"js-yaml": "^4.0.0",
|
|
58
|
+
"axios": "^1.0.0",
|
|
59
|
+
"zod": "^3.23.0",
|
|
60
|
+
"@aws-sdk/client-s3": "^3.0.0",
|
|
61
|
+
"@aws-sdk/lib-storage": "^3.0.0",
|
|
62
|
+
"@azure/storage-blob": "^12.0.0",
|
|
63
|
+
"@google-cloud/storage": "^7.0.0",
|
|
64
|
+
"dropbox": "^10.0.0",
|
|
65
|
+
"googleapis": "^140.0.0",
|
|
66
|
+
"ssh2": "^1.0.0",
|
|
67
|
+
"node-ssh": "^13.0.0",
|
|
68
|
+
"semver": "^7.0.0",
|
|
69
|
+
"dotenv": "^16.0.0",
|
|
70
|
+
"basic-ftp": "^5.0.0",
|
|
71
|
+
"nodemailer": "^6.9.0"
|
|
72
|
+
},
|
|
73
|
+
"devDependencies": {
|
|
74
|
+
"jest": "^29.0.0",
|
|
75
|
+
"pkg": "^5.8.1",
|
|
76
|
+
"esbuild": "^0.21.0"
|
|
77
|
+
},
|
|
78
|
+
"engines": {
|
|
79
|
+
"node": ">=18.0.0"
|
|
80
|
+
},
|
|
81
|
+
"author": {
|
|
82
|
+
"name": "Akash Chowdhury",
|
|
83
|
+
"email": "akashbumbac24@gmail.com",
|
|
84
|
+
"url": "https://www.linkedin.com/in/akash-chowdhury-12141a222/"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { execa } from 'execa';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { createLogger } from '../logger/index.js';
|
|
5
|
+
|
|
6
|
+
function create(config, cwd) {
|
|
7
|
+
const log = createLogger('dotnet');
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
detect() {
|
|
11
|
+
const files = fs.readdirSync(cwd);
|
|
12
|
+
return files.some((f) => f.endsWith('.csproj'));
|
|
13
|
+
},
|
|
14
|
+
|
|
15
|
+
async install() {
|
|
16
|
+
log.info('Restoring .NET packages...');
|
|
17
|
+
await execa('dotnet', ['restore'], { cwd, stdio: 'inherit' });
|
|
18
|
+
},
|
|
19
|
+
|
|
20
|
+
async test() {
|
|
21
|
+
await execa('dotnet', ['test'], { cwd, stdio: 'inherit' });
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
async build() {
|
|
25
|
+
log.info(`Running: ${config.buildCommand}`);
|
|
26
|
+
const [cmd, ...args] = config.buildCommand.split(' ');
|
|
27
|
+
await execa(cmd, args, { cwd, stdio: 'inherit', shell: true });
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
async docker() {
|
|
31
|
+
if (await fs.pathExists(path.join(cwd, 'Dockerfile'))) {
|
|
32
|
+
await execa('docker', ['build', '-t', `${config.project}:latest`, '.'], {
|
|
33
|
+
cwd,
|
|
34
|
+
stdio: 'inherit',
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export default { create };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { execa } from 'execa';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { createLogger } from '../logger/index.js';
|
|
5
|
+
|
|
6
|
+
function create(config, cwd) {
|
|
7
|
+
const log = createLogger('go');
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
detect() {
|
|
11
|
+
return fs.existsSync(path.join(cwd, 'go.mod'));
|
|
12
|
+
},
|
|
13
|
+
|
|
14
|
+
async install() {
|
|
15
|
+
log.info('Downloading Go modules...');
|
|
16
|
+
await execa('go', ['mod', 'download'], { cwd, stdio: 'inherit' });
|
|
17
|
+
},
|
|
18
|
+
|
|
19
|
+
async test() {
|
|
20
|
+
await execa('go', ['test', './...'], { cwd, stdio: 'inherit' });
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
async build() {
|
|
24
|
+
log.info(`Running: ${config.buildCommand}`);
|
|
25
|
+
const [cmd, ...args] = config.buildCommand.split(' ');
|
|
26
|
+
await execa(cmd, args, { cwd, stdio: 'inherit', shell: true });
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
async docker() {
|
|
30
|
+
if (await fs.pathExists(path.join(cwd, 'Dockerfile'))) {
|
|
31
|
+
await execa('docker', ['build', '-t', `${config.project}:latest`, '.'], {
|
|
32
|
+
cwd,
|
|
33
|
+
stdio: 'inherit',
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export default { create };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import nodeAdapter from './node.adapter.js';
|
|
2
|
+
import pythonAdapter from './python.adapter.js';
|
|
3
|
+
import phpAdapter from './php.adapter.js';
|
|
4
|
+
import javaAdapter from './java.adapter.js';
|
|
5
|
+
import goAdapter from './go.adapter.js';
|
|
6
|
+
import dotnetAdapter from './dotnet.adapter.js';
|
|
7
|
+
import railsAdapter from './rails.adapter.js';
|
|
8
|
+
|
|
9
|
+
/** @type {Record<string, import('./node.adapter.js').default>} */
|
|
10
|
+
const ADAPTERS = {
|
|
11
|
+
react: nodeAdapter,
|
|
12
|
+
vue: nodeAdapter,
|
|
13
|
+
angular: nodeAdapter,
|
|
14
|
+
nextjs: nodeAdapter,
|
|
15
|
+
svelte: nodeAdapter,
|
|
16
|
+
astro: nodeAdapter,
|
|
17
|
+
vanilla: nodeAdapter,
|
|
18
|
+
node: nodeAdapter,
|
|
19
|
+
express: nodeAdapter,
|
|
20
|
+
nestjs: nodeAdapter,
|
|
21
|
+
fastify: nodeAdapter,
|
|
22
|
+
koa: nodeAdapter,
|
|
23
|
+
python: pythonAdapter,
|
|
24
|
+
fastapi: pythonAdapter,
|
|
25
|
+
django: pythonAdapter,
|
|
26
|
+
flask: pythonAdapter,
|
|
27
|
+
php: phpAdapter,
|
|
28
|
+
laravel: phpAdapter,
|
|
29
|
+
symfony: phpAdapter,
|
|
30
|
+
java: javaAdapter,
|
|
31
|
+
spring: javaAdapter,
|
|
32
|
+
go: goAdapter,
|
|
33
|
+
dotnet: dotnetAdapter,
|
|
34
|
+
rails: railsAdapter,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @param {string} framework
|
|
39
|
+
* @param {import('../core/config.js').DeployHubConfig} config
|
|
40
|
+
* @param {string} [cwd]
|
|
41
|
+
* @returns {import('./node.adapter.js').default}
|
|
42
|
+
*/
|
|
43
|
+
export function getAdapter(framework, config, cwd = process.cwd()) {
|
|
44
|
+
const AdapterClass = ADAPTERS[framework] || nodeAdapter;
|
|
45
|
+
return AdapterClass.create(config, cwd);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export default { getAdapter };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { execa } from 'execa';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { createLogger } from '../logger/index.js';
|
|
5
|
+
|
|
6
|
+
function create(config, cwd) {
|
|
7
|
+
const log = createLogger('java');
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
detect() {
|
|
11
|
+
return (
|
|
12
|
+
fs.existsSync(path.join(cwd, 'pom.xml')) ||
|
|
13
|
+
fs.existsSync(path.join(cwd, 'build.gradle'))
|
|
14
|
+
);
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
async install() {
|
|
18
|
+
log.info('Resolving Java dependencies...');
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
async test() {
|
|
22
|
+
if (fs.existsSync(path.join(cwd, 'pom.xml'))) {
|
|
23
|
+
await execa('mvn', ['test'], { cwd, stdio: 'inherit' });
|
|
24
|
+
} else {
|
|
25
|
+
await execa('./gradlew', ['test'], { cwd, stdio: 'inherit', shell: true });
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
async build() {
|
|
30
|
+
log.info(`Running: ${config.buildCommand}`);
|
|
31
|
+
const [cmd, ...args] = config.buildCommand.split(' ');
|
|
32
|
+
await execa(cmd, args, { cwd, stdio: 'inherit', shell: true });
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
async docker() {
|
|
36
|
+
if (await fs.pathExists(path.join(cwd, 'Dockerfile'))) {
|
|
37
|
+
await execa('docker', ['build', '-t', `${config.project}:latest`, '.'], {
|
|
38
|
+
cwd,
|
|
39
|
+
stdio: 'inherit',
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export default { create };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { execa } from 'execa';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { createLogger } from '../logger/index.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {Object} LanguageAdapter
|
|
8
|
+
* @property {function(): boolean} detect
|
|
9
|
+
* @property {function(): Promise<void>} install
|
|
10
|
+
* @property {function(): Promise<void>} test
|
|
11
|
+
* @property {function(): Promise<void>} build
|
|
12
|
+
* @property {function(): Promise<void>} docker
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @param {import('../core/config.js').DeployHubConfig} config
|
|
17
|
+
* @param {string} cwd
|
|
18
|
+
*/
|
|
19
|
+
function create(config, cwd) {
|
|
20
|
+
const log = createLogger('node');
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
detect() {
|
|
24
|
+
return fs.existsSync(path.join(cwd, 'package.json'));
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
async install() {
|
|
28
|
+
log.info('Installing dependencies...');
|
|
29
|
+
if (fs.existsSync(path.join(cwd, 'package-lock.json'))) {
|
|
30
|
+
await execa('npm', ['ci'], { cwd, stdio: 'inherit' });
|
|
31
|
+
} else {
|
|
32
|
+
await execa('npm', ['install'], { cwd, stdio: 'inherit' });
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
|
|
36
|
+
async test() {
|
|
37
|
+
const pkg = await fs.readJson(path.join(cwd, 'package.json'));
|
|
38
|
+
if (!pkg.scripts?.test) {
|
|
39
|
+
log.warn('No test script found, skipping');
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
log.info('Running tests...');
|
|
43
|
+
await execa('npm', ['test'], { cwd, stdio: 'inherit' });
|
|
44
|
+
},
|
|
45
|
+
|
|
46
|
+
async build() {
|
|
47
|
+
const buildCommand =
|
|
48
|
+
config.buildCommand ||
|
|
49
|
+
(config.projectType === 'both' ? config.frontend?.buildCommand : null) ||
|
|
50
|
+
(config.projectType === 'backend' ? config.backend?.buildCommand : null);
|
|
51
|
+
|
|
52
|
+
if (!buildCommand) {
|
|
53
|
+
log.info('No build command configured, skipping');
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
log.info(`Running build: ${buildCommand}`);
|
|
58
|
+
const [cmd, ...args] = buildCommand.split(' ');
|
|
59
|
+
await execa(cmd, args, { cwd, stdio: 'inherit', shell: true });
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
async docker() {
|
|
63
|
+
if (!(await fs.pathExists(path.join(cwd, 'Dockerfile')))) {
|
|
64
|
+
log.warn('No Dockerfile found, skipping docker build');
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
log.info('Building Docker image...');
|
|
68
|
+
const imageName = `${config.project}:latest`;
|
|
69
|
+
await execa('docker', ['build', '-t', imageName, '.'], {
|
|
70
|
+
cwd,
|
|
71
|
+
stdio: 'inherit',
|
|
72
|
+
});
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export default { create };
|