myaidev-method 0.2.4 โ 0.2.6
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/USER_GUIDE.md +389 -8
- package/bin/cli.js +165 -30
- package/package.json +1 -1
- package/src/lib/ascii-banner.js +100 -0
- package/src/templates/claude/commands/myai-deploy-dev.md +500 -0
- package/src/templates/claude/commands/myai-deploy-prod.md +837 -0
- package/src/templates/claude/commands/myai-deploy-staging.md +331 -0
- package/src/templates/claude/commands/myai-git-hotfix.md +957 -0
- package/src/templates/claude/commands/myai-git-pr.md +200 -0
- package/src/templates/claude/commands/myai-git-release.md +806 -0
- package/src/templates/claude/commands/myai-git-sync.md +796 -0
- package/src/templates/codex/commands/myai-astro-publish.md +51 -0
- package/src/templates/codex/commands/myai-configure.md +185 -0
- package/src/templates/codex/commands/myai-content-writer.md +73 -0
- package/src/templates/codex/commands/myai-coolify-deploy.md +159 -0
- package/src/templates/codex/commands/myai-deploy-dev.md +379 -0
- package/src/templates/codex/commands/myai-deploy-prod.md +431 -0
- package/src/templates/codex/commands/myai-deploy-staging.md +275 -0
- package/src/templates/codex/commands/myai-dev-architect.md +69 -0
- package/src/templates/codex/commands/myai-dev-code.md +82 -0
- package/src/templates/codex/commands/myai-dev-docs.md +83 -0
- package/src/templates/codex/commands/myai-dev-review.md +85 -0
- package/src/templates/codex/commands/myai-dev-test.md +84 -0
- package/src/templates/codex/commands/myai-docusaurus-publish.md +42 -0
- package/src/templates/codex/commands/myai-git-hotfix.md +512 -0
- package/src/templates/codex/commands/myai-git-pr.md +196 -0
- package/src/templates/codex/commands/myai-git-release.md +516 -0
- package/src/templates/codex/commands/myai-git-sync.md +517 -0
- package/src/templates/codex/commands/myai-mintlify-publish.md +42 -0
- package/src/templates/codex/commands/myai-payloadcms-publish.md +42 -0
- package/src/templates/codex/commands/myai-sparc-workflow.md +185 -0
- package/src/templates/codex/commands/myai-wordpress-admin.md +143 -0
- package/src/templates/codex/commands/myai-wordpress-publish.md +66 -0
- package/src/templates/gemini/commands/myai-astro-publish.toml +76 -0
- package/src/templates/gemini/commands/myai-configure.toml +188 -0
- package/src/templates/gemini/commands/myai-content-writer.toml +76 -0
- package/src/templates/gemini/commands/myai-coolify-deploy.toml +138 -0
- package/src/templates/gemini/commands/myai-deploy-dev.toml +379 -0
- package/src/templates/gemini/commands/myai-deploy-prod.toml +438 -0
- package/src/templates/gemini/commands/myai-deploy-staging.toml +275 -0
- package/src/templates/gemini/commands/myai-dev-architect.toml +64 -0
- package/src/templates/gemini/commands/myai-dev-code.toml +75 -0
- package/src/templates/gemini/commands/myai-dev-docs.toml +76 -0
- package/src/templates/gemini/commands/myai-dev-review.toml +78 -0
- package/src/templates/gemini/commands/myai-dev-test.toml +77 -0
- package/src/templates/gemini/commands/myai-docusaurus-publish.toml +63 -0
- package/src/templates/gemini/commands/myai-git-hotfix.toml +953 -0
- package/src/templates/gemini/commands/myai-git-pr.toml +196 -0
- package/src/templates/gemini/commands/myai-git-release.toml +802 -0
- package/src/templates/gemini/commands/myai-git-sync.toml +792 -0
- package/src/templates/gemini/commands/myai-mintlify-publish.toml +67 -0
- package/src/templates/gemini/commands/myai-payloadcms-publish.toml +59 -0
- package/src/templates/gemini/commands/myai-sparc-workflow.toml +47 -0
- package/src/templates/gemini/commands/myai-wordpress-admin.toml +143 -0
- package/src/templates/gemini/commands/myai-wordpress-publish.toml +77 -0
|
@@ -0,0 +1,837 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: myai-deploy-prod
|
|
3
|
+
description: Deploy to production environment with strict checks and approval
|
|
4
|
+
tools: [bash, read, write]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
You are a deployment automation assistant specializing in production environment deployments with strict safety protocols.
|
|
8
|
+
|
|
9
|
+
Task: Deploy to production environment - $ARGUMENTS
|
|
10
|
+
|
|
11
|
+
## Production Deployment Workflow
|
|
12
|
+
|
|
13
|
+
### 1. Pre-Deployment Checks (CRITICAL)
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
echo "๐ Starting production deployment pre-flight checks..."
|
|
17
|
+
|
|
18
|
+
# CRITICAL: Ensure on correct branch
|
|
19
|
+
current_branch=$(git branch --show-current)
|
|
20
|
+
if [[ "$current_branch" != "main" && "$current_branch" != "master" && "$current_branch" != "production" ]]; then
|
|
21
|
+
echo "โ BLOCKED: Not on production branch (main/master/production)"
|
|
22
|
+
echo "Current branch: $current_branch"
|
|
23
|
+
exit 1
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
# Check for uncommitted changes
|
|
27
|
+
if ! git diff-index --quiet HEAD --; then
|
|
28
|
+
echo "โ BLOCKED: Uncommitted changes detected"
|
|
29
|
+
git status
|
|
30
|
+
exit 1
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
# Ensure branch is up to date
|
|
34
|
+
git fetch origin
|
|
35
|
+
LOCAL=$(git rev-parse @)
|
|
36
|
+
REMOTE=$(git rev-parse @{u})
|
|
37
|
+
if [ $LOCAL != $REMOTE ]; then
|
|
38
|
+
echo "โ BLOCKED: Local branch not in sync with remote"
|
|
39
|
+
echo "Run: git pull origin $current_branch"
|
|
40
|
+
exit 1
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
# Check if staging is ahead of production
|
|
44
|
+
if [ -n "$(git rev-list $current_branch..origin/staging 2>/dev/null)" ]; then
|
|
45
|
+
echo "โ ๏ธ WARNING: Staging branch has commits not in production"
|
|
46
|
+
echo "Consider deploying from staging first"
|
|
47
|
+
read -p "Continue anyway? (yes/no): " confirm
|
|
48
|
+
if [ "$confirm" != "yes" ]; then
|
|
49
|
+
exit 1
|
|
50
|
+
fi
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
echo "โ
Pre-flight checks passed"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 2. Environment Validation (CRITICAL)
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
echo "๐ Validating production environment..."
|
|
60
|
+
|
|
61
|
+
# Required variables for Coolify
|
|
62
|
+
coolify_vars=("COOLIFY_URL" "COOLIFY_API_TOKEN" "COOLIFY_PROD_APP_ID")
|
|
63
|
+
|
|
64
|
+
# Required variables for Docker
|
|
65
|
+
docker_vars=("DOCKER_REGISTRY" "PROD_IMAGE_TAG")
|
|
66
|
+
|
|
67
|
+
# Application variables
|
|
68
|
+
app_vars=("PROD_URL" "NODE_ENV")
|
|
69
|
+
|
|
70
|
+
# Check configuration
|
|
71
|
+
missing_vars=()
|
|
72
|
+
for var in "${coolify_vars[@]}" "${app_vars[@]}"; do
|
|
73
|
+
if [ -z "${!var}" ]; then
|
|
74
|
+
missing_vars+=("$var")
|
|
75
|
+
fi
|
|
76
|
+
done
|
|
77
|
+
|
|
78
|
+
# If Coolify missing, check Docker
|
|
79
|
+
if [ ${#missing_vars[@]} -gt 0 ]; then
|
|
80
|
+
echo "Checking Docker configuration..."
|
|
81
|
+
for var in "${docker_vars[@]}"; do
|
|
82
|
+
if [ -z "${!var}" ]; then
|
|
83
|
+
echo "โ Missing required variable: $var"
|
|
84
|
+
exit 1
|
|
85
|
+
fi
|
|
86
|
+
done
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# Verify NODE_ENV is set to production
|
|
90
|
+
if [ "$NODE_ENV" != "production" ]; then
|
|
91
|
+
echo "โ BLOCKED: NODE_ENV must be 'production', not '$NODE_ENV'"
|
|
92
|
+
exit 1
|
|
93
|
+
fi
|
|
94
|
+
|
|
95
|
+
echo "โ
Environment validation passed"
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 3. Comprehensive Testing (CRITICAL)
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
echo "๐งช Running comprehensive test suite..."
|
|
102
|
+
|
|
103
|
+
# Unit tests
|
|
104
|
+
echo "Running unit tests..."
|
|
105
|
+
npm run test:unit || { echo "โ Unit tests FAILED"; exit 1; }
|
|
106
|
+
|
|
107
|
+
# Integration tests
|
|
108
|
+
echo "Running integration tests..."
|
|
109
|
+
npm run test:integration || { echo "โ Integration tests FAILED"; exit 1; }
|
|
110
|
+
|
|
111
|
+
# End-to-end tests
|
|
112
|
+
echo "Running E2E tests..."
|
|
113
|
+
npm run test:e2e || { echo "โ E2E tests FAILED"; exit 1; }
|
|
114
|
+
|
|
115
|
+
# Security audit
|
|
116
|
+
echo "Running security audit..."
|
|
117
|
+
npm audit --production --audit-level=moderate || {
|
|
118
|
+
echo "โ Security vulnerabilities detected"
|
|
119
|
+
npm audit
|
|
120
|
+
exit 1
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
# Linting
|
|
124
|
+
echo "Running linter..."
|
|
125
|
+
npm run lint || { echo "โ Linting FAILED"; exit 1; }
|
|
126
|
+
|
|
127
|
+
# Type checking (if TypeScript)
|
|
128
|
+
if [ -f "tsconfig.json" ]; then
|
|
129
|
+
echo "Running type check..."
|
|
130
|
+
npm run type-check || { echo "โ Type check FAILED"; exit 1; }
|
|
131
|
+
fi
|
|
132
|
+
|
|
133
|
+
# Build
|
|
134
|
+
echo "Building production bundle..."
|
|
135
|
+
NODE_ENV=production npm run build || { echo "โ Build FAILED"; exit 1; }
|
|
136
|
+
|
|
137
|
+
# Bundle size check
|
|
138
|
+
if command -v bundlewatch &> /dev/null; then
|
|
139
|
+
echo "Checking bundle size..."
|
|
140
|
+
bundlewatch || echo "โ ๏ธ Bundle size warning"
|
|
141
|
+
fi
|
|
142
|
+
|
|
143
|
+
echo "โ
All tests passed"
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### 4. Deployment Approval (REQUIRED)
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
request_deployment_approval() {
|
|
150
|
+
echo ""
|
|
151
|
+
echo "โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"
|
|
152
|
+
echo "โ ๐จ PRODUCTION DEPLOYMENT APPROVAL ๐จ โ"
|
|
153
|
+
echo "โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ"
|
|
154
|
+
echo ""
|
|
155
|
+
echo "Environment: PRODUCTION"
|
|
156
|
+
echo "Branch: $(git branch --show-current)"
|
|
157
|
+
echo "Commit: $(git rev-parse --short HEAD)"
|
|
158
|
+
echo "Message: $(git log -1 --pretty=%B)"
|
|
159
|
+
echo "Author: $(git log -1 --pretty=%an)"
|
|
160
|
+
echo "Date: $(git log -1 --pretty=%ad)"
|
|
161
|
+
echo ""
|
|
162
|
+
echo "Deployment Target: $PROD_URL"
|
|
163
|
+
echo ""
|
|
164
|
+
|
|
165
|
+
# Show what will be deployed
|
|
166
|
+
echo "Changes since last deployment:"
|
|
167
|
+
git log --oneline -5
|
|
168
|
+
echo ""
|
|
169
|
+
|
|
170
|
+
# Require explicit confirmation
|
|
171
|
+
read -p "Type 'DEPLOY TO PRODUCTION' to confirm: " approval
|
|
172
|
+
|
|
173
|
+
if [ "$approval" != "DEPLOY TO PRODUCTION" ]; then
|
|
174
|
+
echo "โ Deployment cancelled"
|
|
175
|
+
exit 1
|
|
176
|
+
fi
|
|
177
|
+
|
|
178
|
+
echo "โ
Deployment approved"
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
# Request approval
|
|
182
|
+
request_deployment_approval
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### 5. Create Backup and Rollback Point
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
echo "๐พ Creating rollback point..."
|
|
189
|
+
|
|
190
|
+
# Tag current production state
|
|
191
|
+
current_prod_commit=$(git rev-parse HEAD)
|
|
192
|
+
timestamp=$(date +%Y%m%d_%H%M%S)
|
|
193
|
+
rollback_tag="prod-backup-$timestamp"
|
|
194
|
+
|
|
195
|
+
git tag -a "$rollback_tag" -m "Production backup before deployment at $timestamp"
|
|
196
|
+
git push origin "$rollback_tag"
|
|
197
|
+
|
|
198
|
+
# Save current deployment info
|
|
199
|
+
cat > .deployment-backup.json << EOF
|
|
200
|
+
{
|
|
201
|
+
"timestamp": "$timestamp",
|
|
202
|
+
"commit": "$current_prod_commit",
|
|
203
|
+
"tag": "$rollback_tag",
|
|
204
|
+
"environment": "production"
|
|
205
|
+
}
|
|
206
|
+
EOF
|
|
207
|
+
|
|
208
|
+
echo "โ
Rollback point created: $rollback_tag"
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### 6. Deployment Strategy Selection
|
|
212
|
+
|
|
213
|
+
#### Option A: Blue-Green Deployment (Recommended)
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
blue_green_deploy() {
|
|
217
|
+
echo "๐ต๐ข Executing blue-green deployment..."
|
|
218
|
+
|
|
219
|
+
# Deploy to green environment (inactive)
|
|
220
|
+
echo "Deploying to GREEN environment..."
|
|
221
|
+
|
|
222
|
+
if [ -n "$COOLIFY_URL" ]; then
|
|
223
|
+
# Deploy via Coolify to green slot
|
|
224
|
+
curl -X POST "$COOLIFY_URL/api/v1/deploy" \
|
|
225
|
+
-H "Authorization: Bearer $COOLIFY_API_TOKEN" \
|
|
226
|
+
-H "Content-Type: application/json" \
|
|
227
|
+
-d "{
|
|
228
|
+
\"application_id\": \"$COOLIFY_PROD_GREEN_APP_ID\",
|
|
229
|
+
\"commit\": \"$(git rev-parse HEAD)\"
|
|
230
|
+
}"
|
|
231
|
+
else
|
|
232
|
+
# Deploy via Docker to green
|
|
233
|
+
ssh prod-server << 'EOF'
|
|
234
|
+
docker pull $DOCKER_REGISTRY/app:prod-green
|
|
235
|
+
docker stop app-prod-green 2>/dev/null || true
|
|
236
|
+
docker rm app-prod-green 2>/dev/null || true
|
|
237
|
+
docker run -d \
|
|
238
|
+
--name app-prod-green \
|
|
239
|
+
--network prod-network \
|
|
240
|
+
-p 3001:3000 \
|
|
241
|
+
--env-file /etc/app/prod.env \
|
|
242
|
+
$DOCKER_REGISTRY/app:prod-green
|
|
243
|
+
EOF
|
|
244
|
+
fi
|
|
245
|
+
|
|
246
|
+
# Health check on green
|
|
247
|
+
echo "๐ Health checking GREEN environment..."
|
|
248
|
+
max_retries=60
|
|
249
|
+
retry_count=0
|
|
250
|
+
|
|
251
|
+
while [ $retry_count -lt $max_retries ]; do
|
|
252
|
+
if curl -f -s "${PROD_GREEN_URL}/health" > /dev/null; then
|
|
253
|
+
echo "โ
GREEN environment healthy"
|
|
254
|
+
break
|
|
255
|
+
fi
|
|
256
|
+
sleep 5
|
|
257
|
+
((retry_count++))
|
|
258
|
+
done
|
|
259
|
+
|
|
260
|
+
if [ $retry_count -eq $max_retries ]; then
|
|
261
|
+
echo "โ GREEN environment failed health check"
|
|
262
|
+
exit 1
|
|
263
|
+
fi
|
|
264
|
+
|
|
265
|
+
# Run smoke tests on green
|
|
266
|
+
echo "๐งช Running smoke tests on GREEN..."
|
|
267
|
+
SMOKE_TEST_URL=$PROD_GREEN_URL npm run test:smoke || {
|
|
268
|
+
echo "โ Smoke tests FAILED on GREEN"
|
|
269
|
+
exit 1
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
# Switch traffic to green (blue becomes inactive)
|
|
273
|
+
echo "๐ Switching traffic to GREEN..."
|
|
274
|
+
|
|
275
|
+
# Update load balancer or reverse proxy
|
|
276
|
+
if [ -n "$LOAD_BALANCER_URL" ]; then
|
|
277
|
+
curl -X POST "$LOAD_BALANCER_URL/switch" \
|
|
278
|
+
-H "Content-Type: application/json" \
|
|
279
|
+
-d '{"active":"green"}'
|
|
280
|
+
else
|
|
281
|
+
# Update nginx configuration
|
|
282
|
+
ssh prod-server << 'EOF'
|
|
283
|
+
# Swap upstream servers in nginx config
|
|
284
|
+
sed -i 's/app-prod-blue:3000/app-prod-green:3000/g' /etc/nginx/sites-enabled/production
|
|
285
|
+
nginx -t && nginx -s reload
|
|
286
|
+
EOF
|
|
287
|
+
fi
|
|
288
|
+
|
|
289
|
+
echo "โ
Traffic switched to GREEN"
|
|
290
|
+
echo "๐ก BLUE environment kept running for quick rollback"
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
# Execute blue-green deployment
|
|
294
|
+
# blue_green_deploy
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
#### Option B: Canary Deployment
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
canary_deploy() {
|
|
301
|
+
echo "๐ค Executing canary deployment..."
|
|
302
|
+
|
|
303
|
+
# Deploy canary instance
|
|
304
|
+
echo "Deploying CANARY (10% traffic)..."
|
|
305
|
+
|
|
306
|
+
ssh prod-server << 'EOF'
|
|
307
|
+
docker pull $DOCKER_REGISTRY/app:prod-canary
|
|
308
|
+
docker run -d \
|
|
309
|
+
--name app-prod-canary \
|
|
310
|
+
--network prod-network \
|
|
311
|
+
--label "traefik.weight=10" \
|
|
312
|
+
--env-file /etc/app/prod.env \
|
|
313
|
+
$DOCKER_REGISTRY/app:prod-canary
|
|
314
|
+
EOF
|
|
315
|
+
|
|
316
|
+
# Monitor canary metrics
|
|
317
|
+
echo "๐ Monitoring canary metrics for 10 minutes..."
|
|
318
|
+
|
|
319
|
+
# Check error rates
|
|
320
|
+
check_canary_health() {
|
|
321
|
+
error_rate=$(curl -s "$MONITORING_URL/canary/errors" | jq '.rate')
|
|
322
|
+
latency=$(curl -s "$MONITORING_URL/canary/latency" | jq '.p99')
|
|
323
|
+
|
|
324
|
+
if (( $(echo "$error_rate > 0.05" | bc -l) )); then
|
|
325
|
+
echo "โ Error rate too high: $error_rate"
|
|
326
|
+
return 1
|
|
327
|
+
fi
|
|
328
|
+
|
|
329
|
+
if (( $(echo "$latency > 1000" | bc -l) )); then
|
|
330
|
+
echo "โ Latency too high: ${latency}ms"
|
|
331
|
+
return 1
|
|
332
|
+
fi
|
|
333
|
+
|
|
334
|
+
return 0
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
# Monitor for 10 minutes
|
|
338
|
+
for i in {1..20}; do
|
|
339
|
+
sleep 30
|
|
340
|
+
if ! check_canary_health; then
|
|
341
|
+
echo "โ Canary failed health checks - rolling back"
|
|
342
|
+
ssh prod-server "docker stop app-prod-canary; docker rm app-prod-canary"
|
|
343
|
+
exit 1
|
|
344
|
+
fi
|
|
345
|
+
echo "โ
Canary check $i/20 passed"
|
|
346
|
+
done
|
|
347
|
+
|
|
348
|
+
# Gradually increase traffic: 10% โ 25% โ 50% โ 100%
|
|
349
|
+
for weight in 25 50 100; do
|
|
350
|
+
echo "๐ Increasing canary traffic to $weight%..."
|
|
351
|
+
ssh prod-server << EOF
|
|
352
|
+
docker update --label "traefik.weight=$weight" app-prod-canary
|
|
353
|
+
EOF
|
|
354
|
+
sleep 300 # Wait 5 minutes between increases
|
|
355
|
+
|
|
356
|
+
if ! check_canary_health; then
|
|
357
|
+
echo "โ Canary failed at $weight% traffic"
|
|
358
|
+
exit 1
|
|
359
|
+
fi
|
|
360
|
+
done
|
|
361
|
+
|
|
362
|
+
# Replace all production instances
|
|
363
|
+
echo "๐ Replacing all production instances..."
|
|
364
|
+
ssh prod-server << 'EOF'
|
|
365
|
+
# Stop old production instances
|
|
366
|
+
docker ps -q --filter "name=app-prod-main" | xargs docker stop
|
|
367
|
+
|
|
368
|
+
# Tag canary as main production
|
|
369
|
+
docker tag app-prod-canary app-prod-main
|
|
370
|
+
|
|
371
|
+
# Scale up new instances
|
|
372
|
+
for i in {1..3}; do
|
|
373
|
+
docker run -d \
|
|
374
|
+
--name app-prod-main-$i \
|
|
375
|
+
--network prod-network \
|
|
376
|
+
--env-file /etc/app/prod.env \
|
|
377
|
+
app-prod-main
|
|
378
|
+
done
|
|
379
|
+
EOF
|
|
380
|
+
|
|
381
|
+
echo "โ
Canary deployment complete"
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
# Execute canary deployment
|
|
385
|
+
# canary_deploy
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
#### Option C: Rolling Deployment
|
|
389
|
+
|
|
390
|
+
```bash
|
|
391
|
+
rolling_deploy() {
|
|
392
|
+
echo "๐ Executing rolling deployment..."
|
|
393
|
+
|
|
394
|
+
# Get list of production instances
|
|
395
|
+
instances=($(ssh prod-server "docker ps -q --filter name=app-prod-"))
|
|
396
|
+
total_instances=${#instances[@]}
|
|
397
|
+
|
|
398
|
+
echo "๐ Found $total_instances production instances"
|
|
399
|
+
|
|
400
|
+
# Update instances one at a time
|
|
401
|
+
for i in "${!instances[@]}"; do
|
|
402
|
+
instance_num=$((i+1))
|
|
403
|
+
instance_id="${instances[$i]}"
|
|
404
|
+
|
|
405
|
+
echo "[$instance_num/$total_instances] Updating instance $instance_id..."
|
|
406
|
+
|
|
407
|
+
# Deploy new version
|
|
408
|
+
ssh prod-server << EOF
|
|
409
|
+
# Pull new image
|
|
410
|
+
docker pull $DOCKER_REGISTRY/app:prod
|
|
411
|
+
|
|
412
|
+
# Stop old instance
|
|
413
|
+
docker stop $instance_id
|
|
414
|
+
docker rm $instance_id
|
|
415
|
+
|
|
416
|
+
# Start new instance
|
|
417
|
+
docker run -d \
|
|
418
|
+
--name app-prod-$instance_num \
|
|
419
|
+
--network prod-network \
|
|
420
|
+
-p 300$instance_num:3000 \
|
|
421
|
+
--env-file /etc/app/prod.env \
|
|
422
|
+
$DOCKER_REGISTRY/app:prod
|
|
423
|
+
EOF
|
|
424
|
+
|
|
425
|
+
# Wait for instance to be healthy
|
|
426
|
+
echo "๐ Health checking new instance..."
|
|
427
|
+
sleep 10
|
|
428
|
+
|
|
429
|
+
if ! curl -f -s "http://prod-server:300$instance_num/health" > /dev/null; then
|
|
430
|
+
echo "โ Instance $instance_num failed health check"
|
|
431
|
+
echo "๐ Rolling back..."
|
|
432
|
+
# Rollback logic here
|
|
433
|
+
exit 1
|
|
434
|
+
fi
|
|
435
|
+
|
|
436
|
+
echo "โ
Instance $instance_num updated successfully"
|
|
437
|
+
|
|
438
|
+
# Wait before updating next instance
|
|
439
|
+
if [ $instance_num -lt $total_instances ]; then
|
|
440
|
+
echo "โณ Waiting 30s before next instance..."
|
|
441
|
+
sleep 30
|
|
442
|
+
fi
|
|
443
|
+
done
|
|
444
|
+
|
|
445
|
+
echo "โ
Rolling deployment complete"
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
# Execute rolling deployment
|
|
449
|
+
# rolling_deploy
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
### 7. Post-Deployment Verification (CRITICAL)
|
|
453
|
+
|
|
454
|
+
```bash
|
|
455
|
+
echo "๐ Running post-deployment verification..."
|
|
456
|
+
|
|
457
|
+
# Wait for deployment to stabilize
|
|
458
|
+
echo "โณ Waiting for deployment to stabilize (60s)..."
|
|
459
|
+
sleep 60
|
|
460
|
+
|
|
461
|
+
# Comprehensive health checks
|
|
462
|
+
echo "๐ฅ Running health checks..."
|
|
463
|
+
|
|
464
|
+
# 1. Application health endpoint
|
|
465
|
+
if ! curl -f -s "$PROD_URL/health" > /dev/null; then
|
|
466
|
+
echo "โ CRITICAL: Health endpoint unreachable"
|
|
467
|
+
exit 1
|
|
468
|
+
fi
|
|
469
|
+
|
|
470
|
+
# 2. API endpoints check
|
|
471
|
+
critical_endpoints=(
|
|
472
|
+
"/api/status"
|
|
473
|
+
"/api/version"
|
|
474
|
+
"/api/metrics"
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
for endpoint in "${critical_endpoints[@]}"; do
|
|
478
|
+
response=$(curl -s -o /dev/null -w "%{http_code}" "$PROD_URL$endpoint")
|
|
479
|
+
if [ "$response" != "200" ]; then
|
|
480
|
+
echo "โ CRITICAL: Endpoint $endpoint returned $response"
|
|
481
|
+
exit 1
|
|
482
|
+
fi
|
|
483
|
+
echo "โ
$endpoint: OK"
|
|
484
|
+
done
|
|
485
|
+
|
|
486
|
+
# 3. Database connectivity
|
|
487
|
+
if curl -f -s "$PROD_URL/api/health/db" | grep -q "connected"; then
|
|
488
|
+
echo "โ
Database: Connected"
|
|
489
|
+
else
|
|
490
|
+
echo "โ CRITICAL: Database connection failed"
|
|
491
|
+
exit 1
|
|
492
|
+
fi
|
|
493
|
+
|
|
494
|
+
# 4. External service connectivity
|
|
495
|
+
echo "Checking external services..."
|
|
496
|
+
npm run health:check:services || {
|
|
497
|
+
echo "โ ๏ธ WARNING: Some external services unreachable"
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
# 5. Smoke tests
|
|
501
|
+
echo "๐งช Running production smoke tests..."
|
|
502
|
+
npm run test:smoke:prod || {
|
|
503
|
+
echo "โ CRITICAL: Smoke tests failed"
|
|
504
|
+
exit 1
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
# 6. Performance baseline check
|
|
508
|
+
echo "๐ Checking performance metrics..."
|
|
509
|
+
response_time=$(curl -o /dev/null -s -w '%{time_total}' "$PROD_URL")
|
|
510
|
+
if (( $(echo "$response_time > 2.0" | bc -l) )); then
|
|
511
|
+
echo "โ ๏ธ WARNING: Response time ${response_time}s exceeds 2s baseline"
|
|
512
|
+
fi
|
|
513
|
+
|
|
514
|
+
# 7. Error rate monitoring
|
|
515
|
+
echo "๐ Monitoring error rates (5 minutes)..."
|
|
516
|
+
sleep 300
|
|
517
|
+
|
|
518
|
+
error_rate=$(curl -s "$MONITORING_URL/api/errors/rate" | jq '.last_5min')
|
|
519
|
+
if (( $(echo "$error_rate > 0.01" | bc -l) )); then
|
|
520
|
+
echo "โ ๏ธ WARNING: Error rate elevated: $error_rate"
|
|
521
|
+
read -p "Continue or rollback? (continue/rollback): " decision
|
|
522
|
+
if [ "$decision" == "rollback" ]; then
|
|
523
|
+
./rollback_production.sh
|
|
524
|
+
exit 1
|
|
525
|
+
fi
|
|
526
|
+
fi
|
|
527
|
+
|
|
528
|
+
echo "โ
All post-deployment checks passed"
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
### 8. Rollback Procedures
|
|
532
|
+
|
|
533
|
+
```bash
|
|
534
|
+
# EMERGENCY ROLLBACK - Quick revert to previous version
|
|
535
|
+
emergency_rollback() {
|
|
536
|
+
echo "๐จ EMERGENCY ROLLBACK INITIATED"
|
|
537
|
+
|
|
538
|
+
# Load backup info
|
|
539
|
+
if [ -f ".deployment-backup.json" ]; then
|
|
540
|
+
backup_tag=$(jq -r '.tag' .deployment-backup.json)
|
|
541
|
+
backup_commit=$(jq -r '.commit' .deployment-backup.json)
|
|
542
|
+
|
|
543
|
+
echo "Rolling back to: $backup_tag ($backup_commit)"
|
|
544
|
+
else
|
|
545
|
+
# Use previous tag
|
|
546
|
+
backup_tag=$(git tag --sort=-creatordate | grep "prod-backup" | head -1)
|
|
547
|
+
fi
|
|
548
|
+
|
|
549
|
+
# For blue-green: Just switch back
|
|
550
|
+
if [ "$DEPLOYMENT_STRATEGY" == "blue-green" ]; then
|
|
551
|
+
echo "๐ต Switching traffic back to BLUE..."
|
|
552
|
+
ssh prod-server << 'EOF'
|
|
553
|
+
sed -i 's/app-prod-green:3000/app-prod-blue:3000/g' /etc/nginx/sites-enabled/production
|
|
554
|
+
nginx -s reload
|
|
555
|
+
EOF
|
|
556
|
+
echo "โ
Rolled back to BLUE environment"
|
|
557
|
+
return
|
|
558
|
+
fi
|
|
559
|
+
|
|
560
|
+
# For other strategies: Redeploy previous version
|
|
561
|
+
echo "๐ Redeploying previous version..."
|
|
562
|
+
|
|
563
|
+
git checkout "$backup_tag"
|
|
564
|
+
|
|
565
|
+
if [ -n "$COOLIFY_URL" ]; then
|
|
566
|
+
curl -X POST "$COOLIFY_URL/api/v1/deploy" \
|
|
567
|
+
-H "Authorization: Bearer $COOLIFY_API_TOKEN" \
|
|
568
|
+
-H "Content-Type: application/json" \
|
|
569
|
+
-d "{
|
|
570
|
+
\"application_id\": \"$COOLIFY_PROD_APP_ID\",
|
|
571
|
+
\"commit\": \"$backup_commit\",
|
|
572
|
+
\"force\": true
|
|
573
|
+
}"
|
|
574
|
+
else
|
|
575
|
+
ssh prod-server << EOF
|
|
576
|
+
docker pull $DOCKER_REGISTRY/app:$backup_tag
|
|
577
|
+
docker service update --image $DOCKER_REGISTRY/app:$backup_tag app-prod
|
|
578
|
+
EOF
|
|
579
|
+
fi
|
|
580
|
+
|
|
581
|
+
echo "โ
Rollback complete"
|
|
582
|
+
send_notification "๐จ EMERGENCY ROLLBACK completed to $backup_tag"
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
# GRACEFUL ROLLBACK - With validation
|
|
586
|
+
graceful_rollback() {
|
|
587
|
+
echo "๐ Initiating graceful rollback..."
|
|
588
|
+
|
|
589
|
+
# Get rollback target
|
|
590
|
+
backup_tag=$(jq -r '.tag' .deployment-backup.json)
|
|
591
|
+
|
|
592
|
+
# Validate rollback target
|
|
593
|
+
if ! git tag | grep -q "$backup_tag"; then
|
|
594
|
+
echo "โ Rollback tag not found"
|
|
595
|
+
exit 1
|
|
596
|
+
fi
|
|
597
|
+
|
|
598
|
+
# Request confirmation
|
|
599
|
+
read -p "Rollback to $backup_tag? (yes/no): " confirm
|
|
600
|
+
if [ "$confirm" != "yes" ]; then
|
|
601
|
+
echo "Rollback cancelled"
|
|
602
|
+
exit 0
|
|
603
|
+
fi
|
|
604
|
+
|
|
605
|
+
# Execute rollback
|
|
606
|
+
emergency_rollback
|
|
607
|
+
|
|
608
|
+
# Verify rollback
|
|
609
|
+
sleep 30
|
|
610
|
+
if curl -f -s "$PROD_URL/health" > /dev/null; then
|
|
611
|
+
echo "โ
Rollback verified"
|
|
612
|
+
else
|
|
613
|
+
echo "โ Rollback verification failed"
|
|
614
|
+
fi
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
# Export rollback functions
|
|
618
|
+
export -f emergency_rollback
|
|
619
|
+
export -f graceful_rollback
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
### 9. Production Monitoring Setup
|
|
623
|
+
|
|
624
|
+
```bash
|
|
625
|
+
setup_production_monitoring() {
|
|
626
|
+
echo "๐ Setting up production monitoring..."
|
|
627
|
+
|
|
628
|
+
# Set up health check monitoring
|
|
629
|
+
cat > monitor-production.sh << 'EOF'
|
|
630
|
+
#!/bin/bash
|
|
631
|
+
|
|
632
|
+
while true; do
|
|
633
|
+
timestamp=$(date '+%Y-%m-%d %H:%M:%S')
|
|
634
|
+
|
|
635
|
+
# Health check
|
|
636
|
+
if curl -f -s "$PROD_URL/health" > /dev/null; then
|
|
637
|
+
status="โ
UP"
|
|
638
|
+
else
|
|
639
|
+
status="โ DOWN"
|
|
640
|
+
# Send alert
|
|
641
|
+
curl -X POST "$ALERT_WEBHOOK" \
|
|
642
|
+
-d '{"text":"๐จ Production health check FAILED"}'
|
|
643
|
+
fi
|
|
644
|
+
|
|
645
|
+
# Log status
|
|
646
|
+
echo "[$timestamp] $status" >> /var/log/prod-health.log
|
|
647
|
+
|
|
648
|
+
# Check every 30 seconds
|
|
649
|
+
sleep 30
|
|
650
|
+
done
|
|
651
|
+
EOF
|
|
652
|
+
|
|
653
|
+
chmod +x monitor-production.sh
|
|
654
|
+
|
|
655
|
+
# Start monitoring in background
|
|
656
|
+
nohup ./monitor-production.sh &
|
|
657
|
+
|
|
658
|
+
echo "โ
Monitoring started"
|
|
659
|
+
}
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
### 10. Deployment Notification
|
|
663
|
+
|
|
664
|
+
```bash
|
|
665
|
+
send_production_notification() {
|
|
666
|
+
local status=$1
|
|
667
|
+
local commit_sha=$(git rev-parse HEAD)
|
|
668
|
+
local commit_msg=$(git log -1 --pretty=%B)
|
|
669
|
+
local deployed_by=$(git config user.name)
|
|
670
|
+
local deployment_time=$(date -u +%Y-%m-%dT%H:%M:%SZ)
|
|
671
|
+
|
|
672
|
+
# Slack notification
|
|
673
|
+
if [ -n "$SLACK_WEBHOOK_URL" ]; then
|
|
674
|
+
curl -X POST "$SLACK_WEBHOOK_URL" \
|
|
675
|
+
-H 'Content-Type: application/json' \
|
|
676
|
+
-d "{
|
|
677
|
+
\"text\": \"๐ PRODUCTION Deployment $status\",
|
|
678
|
+
\"blocks\": [
|
|
679
|
+
{
|
|
680
|
+
\"type\": \"header\",
|
|
681
|
+
\"text\": {
|
|
682
|
+
\"type\": \"plain_text\",
|
|
683
|
+
\"text\": \"๐ PRODUCTION DEPLOYMENT $status\"
|
|
684
|
+
}
|
|
685
|
+
},
|
|
686
|
+
{
|
|
687
|
+
\"type\": \"section\",
|
|
688
|
+
\"fields\": [
|
|
689
|
+
{\"type\": \"mrkdwn\", \"text\": \"*Environment:*\nProduction\"},
|
|
690
|
+
{\"type\": \"mrkdwn\", \"text\": \"*Status:*\n$status\"},
|
|
691
|
+
{\"type\": \"mrkdwn\", \"text\": \"*Commit:*\n\`$commit_sha\`\"},
|
|
692
|
+
{\"type\": \"mrkdwn\", \"text\": \"*Deployed by:*\n$deployed_by\"},
|
|
693
|
+
{\"type\": \"mrkdwn\", \"text\": \"*Time:*\n$deployment_time\"},
|
|
694
|
+
{\"type\": \"mrkdwn\", \"text\": \"*URL:*\n$PROD_URL\"}
|
|
695
|
+
]
|
|
696
|
+
},
|
|
697
|
+
{
|
|
698
|
+
\"type\": \"section\",
|
|
699
|
+
\"text\": {
|
|
700
|
+
\"type\": \"mrkdwn\",
|
|
701
|
+
\"text\": \"*Message:*\n$commit_msg\"
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
]
|
|
705
|
+
}"
|
|
706
|
+
fi
|
|
707
|
+
|
|
708
|
+
# Discord notification
|
|
709
|
+
if [ -n "$DISCORD_WEBHOOK_URL" ]; then
|
|
710
|
+
curl -X POST "$DISCORD_WEBHOOK_URL" \
|
|
711
|
+
-H 'Content-Type: application/json' \
|
|
712
|
+
-d "{
|
|
713
|
+
\"content\": \"@here ๐ **PRODUCTION Deployment $status**\",
|
|
714
|
+
\"embeds\": [{
|
|
715
|
+
\"title\": \"Production Deployment\",
|
|
716
|
+
\"color\": 15844367,
|
|
717
|
+
\"fields\": [
|
|
718
|
+
{\"name\": \"Status\", \"value\": \"$status\", \"inline\": true},
|
|
719
|
+
{\"name\": \"Environment\", \"value\": \"Production\", \"inline\": true},
|
|
720
|
+
{\"name\": \"Commit\", \"value\": \"$commit_sha\"},
|
|
721
|
+
{\"name\": \"Message\", \"value\": \"$commit_msg\"},
|
|
722
|
+
{\"name\": \"Deployed by\", \"value\": \"$deployed_by\", \"inline\": true},
|
|
723
|
+
{\"name\": \"URL\", \"value\": \"$PROD_URL\", \"inline\": true}
|
|
724
|
+
],
|
|
725
|
+
\"timestamp\": \"$deployment_time\"
|
|
726
|
+
}]
|
|
727
|
+
}"
|
|
728
|
+
fi
|
|
729
|
+
|
|
730
|
+
# Email notification for production
|
|
731
|
+
if [ -n "$SENDGRID_API_KEY" ]; then
|
|
732
|
+
curl -X POST "https://api.sendgrid.com/v3/mail/send" \
|
|
733
|
+
-H "Authorization: Bearer $SENDGRID_API_KEY" \
|
|
734
|
+
-H "Content-Type: application/json" \
|
|
735
|
+
-d "{
|
|
736
|
+
\"personalizations\": [{\"to\": [{\"email\": \"$TEAM_EMAIL\"}]}],
|
|
737
|
+
\"from\": {\"email\": \"deploy@yourcompany.com\"},
|
|
738
|
+
\"subject\": \"๐ Production Deployment $status\",
|
|
739
|
+
\"content\": [{
|
|
740
|
+
\"type\": \"text/html\",
|
|
741
|
+
\"value\": \"<h2>Production Deployment $status</h2><p><strong>Commit:</strong> $commit_sha<br><strong>Message:</strong> $commit_msg<br><strong>Deployed by:</strong> $deployed_by<br><strong>URL:</strong> $PROD_URL</p>\"
|
|
742
|
+
}]
|
|
743
|
+
}"
|
|
744
|
+
fi
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
# Send notification
|
|
748
|
+
send_production_notification "Success"
|
|
749
|
+
```
|
|
750
|
+
|
|
751
|
+
## Complete Production Deployment Script
|
|
752
|
+
|
|
753
|
+
```bash
|
|
754
|
+
#!/bin/bash
|
|
755
|
+
set -e
|
|
756
|
+
|
|
757
|
+
echo "๐ PRODUCTION DEPLOYMENT INITIATED"
|
|
758
|
+
echo "===================================="
|
|
759
|
+
|
|
760
|
+
# 1. CRITICAL: Pre-flight checks
|
|
761
|
+
echo "๐ Running pre-flight checks..."
|
|
762
|
+
[[ "$(git branch --show-current)" =~ ^(main|master|production)$ ]] || { echo "โ Wrong branch"; exit 1; }
|
|
763
|
+
git diff-index --quiet HEAD -- || { echo "โ Uncommitted changes"; exit 1; }
|
|
764
|
+
|
|
765
|
+
# 2. CRITICAL: Run all tests
|
|
766
|
+
echo "๐งช Running test suite..."
|
|
767
|
+
npm test || { echo "โ Tests failed"; exit 1; }
|
|
768
|
+
npm audit --production --audit-level=moderate || { echo "โ Security issues"; exit 1; }
|
|
769
|
+
|
|
770
|
+
# 3. Build
|
|
771
|
+
echo "๐๏ธ Building production bundle..."
|
|
772
|
+
NODE_ENV=production npm run build || { echo "โ Build failed"; exit 1; }
|
|
773
|
+
|
|
774
|
+
# 4. REQUIRED: Get approval
|
|
775
|
+
read -p "Type 'DEPLOY TO PRODUCTION': " approval
|
|
776
|
+
[ "$approval" == "DEPLOY TO PRODUCTION" ] || { echo "โ Cancelled"; exit 1; }
|
|
777
|
+
|
|
778
|
+
# 5. Create rollback point
|
|
779
|
+
echo "๐พ Creating rollback point..."
|
|
780
|
+
timestamp=$(date +%Y%m%d_%H%M%S)
|
|
781
|
+
git tag "prod-backup-$timestamp"
|
|
782
|
+
git push origin "prod-backup-$timestamp"
|
|
783
|
+
|
|
784
|
+
# 6. Deploy (blue-green recommended)
|
|
785
|
+
echo "๐ Deploying..."
|
|
786
|
+
blue_green_deploy
|
|
787
|
+
|
|
788
|
+
# 7. CRITICAL: Verify deployment
|
|
789
|
+
echo "๐ Verifying deployment..."
|
|
790
|
+
sleep 60
|
|
791
|
+
curl -f "$PROD_URL/health" || { echo "โ Health check failed"; emergency_rollback; exit 1; }
|
|
792
|
+
npm run test:smoke:prod || { echo "โ Smoke tests failed"; emergency_rollback; exit 1; }
|
|
793
|
+
|
|
794
|
+
# 8. Monitor
|
|
795
|
+
echo "๐ Monitoring (5 minutes)..."
|
|
796
|
+
sleep 300
|
|
797
|
+
|
|
798
|
+
# 9. Notify
|
|
799
|
+
send_production_notification "Success"
|
|
800
|
+
|
|
801
|
+
echo "โ
PRODUCTION DEPLOYMENT COMPLETE"
|
|
802
|
+
echo "๐ Live at: $PROD_URL"
|
|
803
|
+
```
|
|
804
|
+
|
|
805
|
+
## Environment Configuration
|
|
806
|
+
|
|
807
|
+
```bash
|
|
808
|
+
# Coolify
|
|
809
|
+
COOLIFY_URL=https://coolify.your-server.com
|
|
810
|
+
COOLIFY_API_TOKEN=your_api_token
|
|
811
|
+
COOLIFY_PROD_APP_ID=your_prod_app_id
|
|
812
|
+
COOLIFY_PROD_GREEN_APP_ID=your_green_app_id
|
|
813
|
+
|
|
814
|
+
# Docker
|
|
815
|
+
DOCKER_REGISTRY=registry.your-domain.com
|
|
816
|
+
PROD_IMAGE_TAG=prod
|
|
817
|
+
|
|
818
|
+
# Application
|
|
819
|
+
PROD_URL=https://your-app.com
|
|
820
|
+
PROD_GREEN_URL=https://green.your-app.com
|
|
821
|
+
NODE_ENV=production
|
|
822
|
+
|
|
823
|
+
# Deployment Strategy
|
|
824
|
+
DEPLOYMENT_STRATEGY=blue-green # or: canary, rolling
|
|
825
|
+
|
|
826
|
+
# Monitoring
|
|
827
|
+
MONITORING_URL=https://monitoring.your-domain.com
|
|
828
|
+
ALERT_WEBHOOK=https://alerts.your-domain.com/webhook
|
|
829
|
+
|
|
830
|
+
# Notifications
|
|
831
|
+
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/YOUR/WEBHOOK
|
|
832
|
+
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/YOUR/WEBHOOK
|
|
833
|
+
SENDGRID_API_KEY=your_sendgrid_key
|
|
834
|
+
TEAM_EMAIL=team@yourcompany.com
|
|
835
|
+
```
|
|
836
|
+
|
|
837
|
+
Execute production deployment with maximum safety and approval gates.
|