Skip to content

Commit c413075

Browse files
committed
Add multi-stage CI/CD pipeline example
1 parent 07d8b0f commit c413075

File tree

1 file changed

+316
-0
lines changed

1 file changed

+316
-0
lines changed

pipelines/multi-stage-cicd.yml

Lines changed: 316 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,316 @@
1+
# Multi-Stage CI/CD Pipeline for Node.js to Azure
2+
# Teaching example for full DevOps pipeline with environments
3+
4+
trigger:
5+
branches:
6+
include:
7+
- master
8+
- main
9+
paths:
10+
include:
11+
- nodeapp-1/*
12+
13+
pr:
14+
branches:
15+
include:
16+
- master
17+
- main
18+
19+
pool:
20+
vmImage: 'ubuntu-latest'
21+
22+
variables:
23+
nodeVersion: '18.x'
24+
azureSubscription: 'AZ400-ServiceConnection' # Update with your service connection
25+
resourceGroupName: 'rg-az400-demo'
26+
webAppName: 'webapp-az400-$(Build.BuildId)'
27+
environmentNameDev: 'Development'
28+
environmentNameStaging: 'Staging'
29+
environmentNameProd: 'Production'
30+
31+
stages:
32+
# ========================================
33+
# STAGE 1: BUILD
34+
# ========================================
35+
- stage: Build
36+
displayName: 'Build and Test'
37+
jobs:
38+
- job: BuildJob
39+
displayName: 'Build Node.js Application'
40+
steps:
41+
# Setup Node.js
42+
- task: NodeTool@0
43+
displayName: 'Install Node.js $(nodeVersion)'
44+
inputs:
45+
versionSpec: $(nodeVersion)
46+
47+
# Install dependencies
48+
- script: |
49+
echo "📦 Installing dependencies..."
50+
npm ci
51+
displayName: 'Install dependencies'
52+
workingDirectory: nodeapp-1
53+
54+
# Run security audit
55+
- script: |
56+
echo "🔒 Running security audit..."
57+
npm audit --audit-level=high || true
58+
displayName: 'Security audit'
59+
workingDirectory: nodeapp-1
60+
61+
# Run linting
62+
- script: |
63+
echo "🔍 Running linter..."
64+
npm run lint || echo "No lint script configured"
65+
displayName: 'Lint code'
66+
workingDirectory: nodeapp-1
67+
continueOnError: true
68+
69+
# Run unit tests
70+
- script: |
71+
echo "🧪 Running unit tests..."
72+
npm test -- --coverage || npm test
73+
displayName: 'Run unit tests'
74+
workingDirectory: nodeapp-1
75+
76+
# Publish test results
77+
- task: PublishTestResults@2
78+
displayName: 'Publish test results'
79+
inputs:
80+
testResultsFormat: 'JUnit'
81+
testResultsFiles: '**/test-*.xml'
82+
searchFolder: nodeapp-1
83+
failTaskOnFailedTests: true
84+
condition: succeededOrFailed()
85+
86+
# Publish code coverage
87+
- task: PublishCodeCoverageResults@1
88+
displayName: 'Publish code coverage'
89+
inputs:
90+
codeCoverageTool: 'Cobertura'
91+
summaryFileLocation: 'nodeapp-1/coverage/**/cobertura-coverage.xml'
92+
condition: succeededOrFailed()
93+
94+
# Build application
95+
- script: |
96+
echo "🔨 Building application..."
97+
npm run build || echo "No build required"
98+
displayName: 'Build application'
99+
workingDirectory: nodeapp-1
100+
101+
# Create deployment package
102+
- task: ArchiveFiles@2
103+
displayName: 'Create deployment package'
104+
inputs:
105+
rootFolderOrFile: 'nodeapp-1'
106+
includeRootFolder: false
107+
archiveType: 'zip'
108+
archiveFile: '$(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip'
109+
110+
# Publish artifact
111+
- publish: $(Build.ArtifactStagingDirectory)
112+
artifact: drop
113+
displayName: 'Publish artifact'
114+
115+
# ========================================
116+
# STAGE 2: DEPLOY TO DEVELOPMENT
117+
# ========================================
118+
- stage: DeployDev
119+
displayName: 'Deploy to Development'
120+
dependsOn: Build
121+
condition: succeeded()
122+
jobs:
123+
- deployment: DeployToDev
124+
displayName: 'Deploy to Dev Environment'
125+
environment: $(environmentNameDev)
126+
strategy:
127+
runOnce:
128+
deploy:
129+
steps:
130+
# Download artifact
131+
- download: current
132+
artifact: drop
133+
displayName: 'Download artifact'
134+
135+
# Deploy to Azure Web App
136+
- task: AzureWebApp@1
137+
displayName: 'Deploy to Dev Web App'
138+
inputs:
139+
azureSubscription: $(azureSubscription)
140+
appType: 'webAppLinux'
141+
appName: '$(webAppName)-dev'
142+
package: '$(Pipeline.Workspace)/drop/*.zip'
143+
runtimeStack: 'NODE|18-lts'
144+
startUpCommand: 'npm start'
145+
146+
# Smoke test
147+
- script: |
148+
echo "🔥 Running smoke tests..."
149+
sleep 30
150+
curl -f https://$(webAppName)-dev.azurewebsites.net || exit 1
151+
echo "✅ Smoke tests passed!"
152+
displayName: 'Smoke test'
153+
154+
# ========================================
155+
# STAGE 3: DEPLOY TO STAGING
156+
# ========================================
157+
- stage: DeployStaging
158+
displayName: 'Deploy to Staging'
159+
dependsOn: DeployDev
160+
condition: succeeded()
161+
jobs:
162+
- deployment: DeployToStaging
163+
displayName: 'Deploy to Staging Environment'
164+
environment:
165+
name: $(environmentNameStaging)
166+
resourceType: VirtualMachine
167+
strategy:
168+
runOnce:
169+
deploy:
170+
steps:
171+
# Download artifact
172+
- download: current
173+
artifact: drop
174+
displayName: 'Download artifact'
175+
176+
# Deploy to staging slot
177+
- task: AzureWebApp@1
178+
displayName: 'Deploy to Staging Slot'
179+
inputs:
180+
azureSubscription: $(azureSubscription)
181+
appType: 'webAppLinux'
182+
appName: '$(webAppName)-staging'
183+
deployToSlotOrASE: true
184+
slotName: 'staging'
185+
package: '$(Pipeline.Workspace)/drop/*.zip'
186+
runtimeStack: 'NODE|18-lts'
187+
188+
# Run integration tests
189+
- script: |
190+
echo "🧪 Running integration tests..."
191+
npm run test:integration || echo "No integration tests configured"
192+
displayName: 'Integration tests'
193+
workingDirectory: nodeapp-1
194+
continueOnError: true
195+
196+
# Performance test
197+
- script: |
198+
echo "⚡ Running performance tests..."
199+
# Add your performance testing tool here
200+
echo "Performance baseline: Response time < 200ms"
201+
displayName: 'Performance tests'
202+
203+
# ========================================
204+
# STAGE 4: DEPLOY TO PRODUCTION
205+
# ========================================
206+
- stage: DeployProd
207+
displayName: 'Deploy to Production'
208+
dependsOn: DeployStaging
209+
condition: succeeded()
210+
jobs:
211+
- deployment: DeployToProd
212+
displayName: 'Deploy to Production Environment'
213+
environment:
214+
name: $(environmentNameProd)
215+
resourceType: VirtualMachine
216+
strategy:
217+
runOnce:
218+
preDeploy:
219+
steps:
220+
- script: |
221+
echo "📋 Pre-deployment checklist:"
222+
echo "✓ All tests passed"
223+
echo "✓ Security scan completed"
224+
echo "✓ Performance benchmarks met"
225+
displayName: 'Pre-deployment validation'
226+
227+
deploy:
228+
steps:
229+
# Download artifact
230+
- download: current
231+
artifact: drop
232+
displayName: 'Download artifact'
233+
234+
# Blue-Green deployment
235+
- task: AzureWebApp@1
236+
displayName: 'Deploy to Production (Blue-Green)'
237+
inputs:
238+
azureSubscription: $(azureSubscription)
239+
appType: 'webAppLinux'
240+
appName: $(webAppName)
241+
deployToSlotOrASE: true
242+
slotName: 'staging'
243+
package: '$(Pipeline.Workspace)/drop/*.zip'
244+
runtimeStack: 'NODE|18-lts'
245+
246+
# Swap slots
247+
- task: AzureAppServiceManage@0
248+
displayName: 'Swap staging to production'
249+
inputs:
250+
azureSubscription: $(azureSubscription)
251+
WebAppName: $(webAppName)
252+
ResourceGroupName: $(resourceGroupName)
253+
SourceSlot: 'staging'
254+
SwapWithProduction: true
255+
256+
postRouteTraffic:
257+
steps:
258+
# Monitor deployment
259+
- script: |
260+
echo "📊 Monitoring deployment health..."
261+
# Add Application Insights queries here
262+
echo "✅ Deployment healthy"
263+
displayName: 'Monitor deployment'
264+
265+
on:
266+
failure:
267+
steps:
268+
# Rollback on failure
269+
- task: AzureAppServiceManage@0
270+
displayName: 'Rollback: Swap slots back'
271+
inputs:
272+
azureSubscription: $(azureSubscription)
273+
WebAppName: $(webAppName)
274+
ResourceGroupName: $(resourceGroupName)
275+
SourceSlot: 'production'
276+
TargetSlot: 'staging'
277+
SwapWithProduction: false
278+
279+
success:
280+
steps:
281+
- script: |
282+
echo "🎉 Production deployment successful!"
283+
echo "URL: https://$(webAppName).azurewebsites.net"
284+
echo "Build: $(Build.BuildId)"
285+
echo "Commit: $(Build.SourceVersion)"
286+
displayName: 'Deployment summary'
287+
288+
# ========================================
289+
# STAGE 5: POST-DEPLOYMENT
290+
# ========================================
291+
- stage: PostDeployment
292+
displayName: 'Post-Deployment Tasks'
293+
dependsOn: DeployProd
294+
condition: succeeded()
295+
jobs:
296+
- job: PostDeploymentTasks
297+
displayName: 'Run post-deployment tasks'
298+
steps:
299+
# Tag the release
300+
- script: |
301+
echo "🏷️ Tagging release..."
302+
git tag -a "v$(Build.BuildId)" -m "Release $(Build.BuildId)"
303+
displayName: 'Tag release'
304+
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
305+
306+
# Update documentation
307+
- script: |
308+
echo "📚 Updating deployment documentation..."
309+
echo "Deployment completed at: $(date)" >> deployment-log.md
310+
displayName: 'Update documentation'
311+
312+
# Send notifications
313+
- script: |
314+
echo "📧 Sending deployment notifications..."
315+
# Add your notification logic here (Teams, Slack, email)
316+
displayName: 'Send notifications'

0 commit comments

Comments
 (0)