1
+ name : Elevate CI/CD Pipeline
2
+
3
+ on :
4
+ push :
5
+ branches : [main, develop]
6
+ pull_request :
7
+ branches : [main]
8
+
9
+ # Add write permissions for the GITHUB_TOKEN
10
+ permissions :
11
+ contents : read
12
+ actions : write
13
+ pull-requests : write
14
+ checks : write
15
+
16
+ env :
17
+ NODE_VERSION : ' 24'
18
+ CACHE_KEY : npm-cache-v1
19
+
20
+ jobs :
21
+ # Quality checks and build
22
+ quality-checks :
23
+ runs-on : ubuntu-latest
24
+ outputs :
25
+ cache-hit : ${{ steps.cache.outputs.cache-hit }}
26
+
27
+ steps :
28
+ - name : Checkout code
29
+ uses : actions/checkout@v4
30
+
31
+ - name : Setup Node.js
32
+ uses : actions/setup-node@v4
33
+ with :
34
+ node-version : ${{ env.NODE_VERSION }}
35
+ cache : ' npm'
36
+
37
+ - name : Cache dependencies
38
+ id : cache
39
+ uses : actions/cache@v4
40
+ with :
41
+ path : node_modules
42
+ key : ${{ runner.os }}-${{ env.CACHE_KEY }}-${{ hashFiles('**/package-lock.json') }}
43
+
44
+ - name : Install dependencies
45
+ if : steps.cache.outputs.cache-hit != 'true'
46
+ run : npm ci
47
+
48
+ - name : Type check
49
+ run : |
50
+ if [ -f "tsconfig.json" ]; then
51
+ npx tsc --noEmit
52
+ else
53
+ echo "No TypeScript config found, skipping type check"
54
+ fi
55
+
56
+ - name : Run tests
57
+ run : |
58
+ if npm run test --if-present; then
59
+ echo "Tests completed successfully"
60
+ else
61
+ echo "No tests found or tests skipped"
62
+ fi
63
+
64
+ - name : Build project
65
+ run : npm run build
66
+
67
+ - name : Upload build artifacts
68
+ uses : actions/upload-artifact@v4
69
+ with :
70
+ name : build-files-${{ github.run_id }}
71
+ path : dist/
72
+ retention-days : 1
73
+
74
+ # Security and performance audits
75
+ security-audit :
76
+ runs-on : ubuntu-latest
77
+ needs : quality-checks
78
+
79
+ steps :
80
+ - name : Checkout code
81
+ uses : actions/checkout@v4
82
+
83
+ - name : Setup Node.js
84
+ uses : actions/setup-node@v4
85
+ with :
86
+ node-version : ${{ env.NODE_VERSION }}
87
+ cache : ' npm'
88
+
89
+ - name : Install dependencies
90
+ run : npm ci
91
+
92
+ - name : Security audit
93
+ run : |
94
+ echo "Running npm audit..."
95
+ npm audit --audit-level moderate || true
96
+
97
+ - name : Check for high/critical vulnerabilities
98
+ run : |
99
+ # Check if jq is available, if not install it
100
+ if ! command -v jq &> /dev/null; then
101
+ sudo apt-get update && sudo apt-get install -y jq
102
+ fi
103
+
104
+ HIGH_VULNS=$(npm audit --audit-level high --json 2>/dev/null | jq '.metadata.vulnerabilities.high // 0' || echo "0")
105
+ CRITICAL_VULNS=$(npm audit --audit-level critical --json 2>/dev/null | jq '.metadata.vulnerabilities.critical // 0' || echo "0")
106
+
107
+ echo "High vulnerabilities: $HIGH_VULNS"
108
+ echo "Critical vulnerabilities: $CRITICAL_VULNS"
109
+
110
+ if [ "$HIGH_VULNS" -gt 0 ] || [ "$CRITICAL_VULNS" -gt 0 ]; then
111
+ echo "High or critical vulnerabilities found!"
112
+ npm audit --audit-level high
113
+ exit 1
114
+ else
115
+ echo "No high or critical vulnerabilities found"
116
+ fi
117
+
118
+ # Vercel deployment
119
+ deploy-vercel :
120
+ runs-on : ubuntu-latest
121
+ needs : [quality-checks, security-audit]
122
+ if : always() && needs.quality-checks.result == 'success' && (needs.security-audit.result == 'success' || needs.security-audit.result == 'skipped')
123
+ outputs :
124
+ preview-url : ${{ steps.vercel-preview.outputs.preview-url }}
125
+ production-url : ${{ steps.vercel-production.outputs.preview-url }}
126
+
127
+ steps :
128
+ - name : Checkout code
129
+ uses : actions/checkout@v4
130
+
131
+ - name : Deploy to Vercel (Preview)
132
+ id : vercel-preview
133
+ if : github.event_name == 'pull_request'
134
+ uses : amondnet/vercel-action@v25
135
+ with :
136
+ vercel-token : ${{ secrets.VERCEL_TOKEN }}
137
+ vercel-org-id : ${{ secrets.VERCEL_ORG_ID }}
138
+ vercel-project-id : ${{ secrets.VERCEL_PROJECT_ID }}
139
+ working-directory : ./
140
+ scope : ${{ secrets.VERCEL_ORG_ID }}
141
+ alias-domains : |
142
+ pr-${{ github.event.number }}-elevatehabits.vercel.app
143
+
144
+ - name : Deploy to Vercel (Production)
145
+ id : vercel-production
146
+ if : github.ref == 'refs/heads/main' && github.event_name == 'push'
147
+ uses : amondnet/vercel-action@v25
148
+ with :
149
+ vercel-token : ${{ secrets.VERCEL_TOKEN }}
150
+ vercel-org-id : ${{ secrets.VERCEL_ORG_ID }}
151
+ vercel-project-id : ${{ secrets.VERCEL_PROJECT_ID }}
152
+ vercel-args : ' --prod'
153
+ working-directory : ./
154
+ scope : ${{ secrets.VERCEL_ORG_ID }}
155
+
156
+ - name : Comment PR with preview URL
157
+ if : github.event_name == 'pull_request' && steps.vercel-preview.outputs.preview-url
158
+ uses : actions/github-script@v7
159
+ with :
160
+ script : |
161
+ const deploymentUrl = '${{ steps.vercel-preview.outputs.preview-url }}';
162
+ const comment = `## 🚀 Preview Deployment
163
+
164
+ Your changes have been deployed to Vercel:
165
+
166
+ **Preview URL:** ${deploymentUrl}
167
+
168
+ ---
169
+ *Deployed from commit: ${{ github.sha }}*`;
170
+
171
+ github.rest.issues.createComment({
172
+ issue_number: context.issue.number,
173
+ owner: context.repo.owner,
174
+ repo: context.repo.repo,
175
+ body: comment
176
+ });
177
+
178
+ # Post-deployment checks
179
+ post-deploy-checks :
180
+ runs-on : ubuntu-latest
181
+ needs : [deploy-vercel]
182
+ if : always() && needs.deploy-vercel.result == 'success'
183
+
184
+ steps :
185
+ - name : Health check Vercel deployment
186
+ run : |
187
+ echo "Performing post-deployment health checks..."
188
+
189
+ # Health check for preview deployment
190
+ if [ "${{ github.event_name }}" == "pull_request" ] && [ -n "${{ needs.deploy-vercel.outputs.preview-url }}" ]; then
191
+ echo "Checking preview deployment..."
192
+ PREVIEW_URL="${{ needs.deploy-vercel.outputs.preview-url }}"
193
+ if curl -f "$PREVIEW_URL" > /dev/null 2>&1; then
194
+ echo "✅ Preview deployment is healthy: $PREVIEW_URL"
195
+ else
196
+ echo "⚠️ Preview deployment health check failed: $PREVIEW_URL"
197
+ fi
198
+ fi
199
+
200
+ # Health check for production deployment
201
+ if [ "${{ github.ref }}" == "refs/heads/main" ] && [ "${{ github.event_name }}" == "push" ] && [ -n "${{ needs.deploy-vercel.outputs.production-url }}" ]; then
202
+ echo "Checking production deployment..."
203
+ PROD_URL="${{ needs.deploy-vercel.outputs.production-url }}"
204
+ if curl -f "$PROD_URL" > /dev/null 2>&1; then
205
+ echo "✅ Production deployment is healthy: $PROD_URL"
206
+ else
207
+ echo "⚠️ Production deployment health check failed: $PROD_URL"
208
+ fi
209
+ fi
210
+
211
+ echo "Health checks completed"
212
+
213
+ - name : Notify deployment status
214
+ if : github.event_name == 'push' && github.ref == 'refs/heads/main'
215
+ run : |
216
+ echo "🚀 Production deployment completed successfully!"
217
+ echo "Vercel Status: ${{ needs.deploy-vercel.result }}"
218
+ echo "Deployment URL: ${{ needs.deploy-vercel.outputs.production-url }}"
219
+
220
+ - name : Create deployment summary
221
+ run : |
222
+ echo "## 🚀 Deployment Summary" >> $GITHUB_STEP_SUMMARY
223
+ echo "" >> $GITHUB_STEP_SUMMARY
224
+ echo "**Repository:** ${{ github.repository }}" >> $GITHUB_STEP_SUMMARY
225
+ echo "**Commit:** ${{ github.sha }}" >> $GITHUB_STEP_SUMMARY
226
+ echo "**Branch:** ${{ github.ref_name }}" >> $GITHUB_STEP_SUMMARY
227
+ echo "**Trigger:** ${{ github.event_name }}" >> $GITHUB_STEP_SUMMARY
228
+ echo "" >> $GITHUB_STEP_SUMMARY
229
+
230
+ if [ "${{ github.event_name }}" == "pull_request" ]; then
231
+ echo "### Preview Deployment" >> $GITHUB_STEP_SUMMARY
232
+ echo "- **Platform:** Vercel" >> $GITHUB_STEP_SUMMARY
233
+ echo "- **Status:** ${{ needs.deploy-vercel.result }}" >> $GITHUB_STEP_SUMMARY
234
+ if [ -n "${{ needs.deploy-vercel.outputs.preview-url }}" ]; then
235
+ echo "- **URL:** [${{ needs.deploy-vercel.outputs.preview-url }}](${{ needs.deploy-vercel.outputs.preview-url }})" >> $GITHUB_STEP_SUMMARY
236
+ fi
237
+ else
238
+ echo "### Production Deployment" >> $GITHUB_STEP_SUMMARY
239
+ echo "- **Platform:** Vercel" >> $GITHUB_STEP_SUMMARY
240
+ echo "- **Status:** ${{ needs.deploy-vercel.result }}" >> $GITHUB_STEP_SUMMARY
241
+ if [ -n "${{ needs.deploy-vercel.outputs.production-url }}" ]; then
242
+ echo "- **URL:** [${{ needs.deploy-vercel.outputs.production-url }}](${{ needs.deploy-vercel.outputs.production-url }})" >> $GITHUB_STEP_SUMMARY
243
+ fi
244
+ fi
245
+
246
+ echo "" >> $GITHUB_STEP_SUMMARY
247
+ echo "---" >> $GITHUB_STEP_SUMMARY
248
+ echo "*Workflow completed at $(date)*" >> $GITHUB_STEP_SUMMARY
249
+
250
+ # Cleanup job
251
+ cleanup :
252
+ runs-on : ubuntu-latest
253
+ needs : [deploy-vercel, post-deploy-checks]
254
+ if : always()
255
+
256
+ steps :
257
+ - name : Cleanup notification
258
+ run : |
259
+ echo "🧹 Cleanup job completed"
260
+ echo "Build artifacts will be automatically cleaned up after retention period"
261
+ echo "Manual cleanup can be done through GitHub UI if needed"
262
+
263
+ - name : Workflow completion
264
+ run : |
265
+ echo "✅ Elevate CI/CD Pipeline completed"
266
+ echo "Overall Status:"
267
+ echo "- Quality Checks: Completed"
268
+ echo "- Security Audit: Completed"
269
+ echo "- Vercel Deployment: ${{ needs.deploy-vercel.result }}"
270
+ echo "- Post-deploy Checks: ${{ needs.post-deploy-checks.result }}"
0 commit comments