Skip to content

Commit 9efa7bd

Browse files
Merge pull request #16 from timothywarner/add-yaml-pipeline-examples
Add YAML pipeline examples for teaching CI/CD
2 parents 3fc40e8 + 27917ab commit 9efa7bd

File tree

4 files changed

+791
-0
lines changed

4 files changed

+791
-0
lines changed
Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
name: Node.js CI/CD to Azure
2+
3+
# Teaching example for GitHub Actions with Azure deployment
4+
5+
on:
6+
push:
7+
branches: [ main, master ]
8+
paths:
9+
- 'nodeapp-1/**'
10+
- '.github/workflows/node-azure-deploy.yml'
11+
pull_request:
12+
branches: [ main, master ]
13+
workflow_dispatch:
14+
inputs:
15+
environment:
16+
description: 'Environment to deploy to'
17+
required: true
18+
default: 'development'
19+
type: choice
20+
options:
21+
- development
22+
- staging
23+
- production
24+
25+
env:
26+
NODE_VERSION: '18.x'
27+
AZURE_WEBAPP_NAME: 'webapp-az400-demo'
28+
AZURE_WEBAPP_PACKAGE_PATH: './nodeapp-1'
29+
30+
jobs:
31+
# ========================================
32+
# JOB 1: BUILD AND TEST
33+
# ========================================
34+
build:
35+
name: Build and Test
36+
runs-on: ubuntu-latest
37+
38+
steps:
39+
- name: 📥 Checkout code
40+
uses: actions/checkout@v4
41+
42+
- name: 🔧 Setup Node.js ${{ env.NODE_VERSION }}
43+
uses: actions/setup-node@v4
44+
with:
45+
node-version: ${{ env.NODE_VERSION }}
46+
cache: 'npm'
47+
cache-dependency-path: '${{ env.AZURE_WEBAPP_PACKAGE_PATH }}/package-lock.json'
48+
49+
- name: 📦 Install dependencies
50+
run: npm ci
51+
working-directory: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
52+
53+
- name: 🔒 Security audit
54+
run: npm audit --audit-level=high
55+
working-directory: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
56+
continue-on-error: true
57+
58+
- name: 🧹 Lint code
59+
run: npm run lint || echo "No lint script configured"
60+
working-directory: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
61+
62+
- name: 🧪 Run tests
63+
run: npm test -- --coverage || npm test
64+
working-directory: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
65+
66+
- name: 📊 Upload coverage reports
67+
uses: codecov/codecov-action@v3
68+
with:
69+
directory: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}/coverage
70+
flags: unittests
71+
name: codecov-umbrella
72+
fail_ci_if_error: false
73+
74+
- name: 🔨 Build application
75+
run: npm run build || echo "No build required"
76+
working-directory: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
77+
78+
- name: 📤 Upload artifact for deployment
79+
uses: actions/upload-artifact@v4
80+
with:
81+
name: node-app
82+
path: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }}
83+
retention-days: 5
84+
85+
# ========================================
86+
# JOB 2: DEPLOY TO DEVELOPMENT
87+
# ========================================
88+
deploy-dev:
89+
name: Deploy to Development
90+
runs-on: ubuntu-latest
91+
needs: build
92+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
93+
environment:
94+
name: development
95+
url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}
96+
97+
steps:
98+
- name: 📥 Download artifact
99+
uses: actions/download-artifact@v4
100+
with:
101+
name: node-app
102+
path: ./app
103+
104+
- name: 🔐 Login to Azure
105+
uses: azure/login@v1
106+
with:
107+
creds: ${{ secrets.AZURE_CREDENTIALS }}
108+
109+
- name: 🚀 Deploy to Azure Web App
110+
id: deploy-to-webapp
111+
uses: azure/webapps-deploy@v3
112+
with:
113+
app-name: ${{ env.AZURE_WEBAPP_NAME }}-dev
114+
package: ./app
115+
startup-command: 'npm start'
116+
117+
- name: 🔥 Smoke test
118+
run: |
119+
sleep 30
120+
response=$(curl -s -o /dev/null -w "%{http_code}" https://${{ env.AZURE_WEBAPP_NAME }}-dev.azurewebsites.net)
121+
if [ $response -eq 200 ]; then
122+
echo "✅ Smoke test passed!"
123+
else
124+
echo "❌ Smoke test failed with status code: $response"
125+
exit 1
126+
fi
127+
128+
# ========================================
129+
# JOB 3: DEPLOY TO STAGING
130+
# ========================================
131+
deploy-staging:
132+
name: Deploy to Staging
133+
runs-on: ubuntu-latest
134+
needs: deploy-dev
135+
environment:
136+
name: staging
137+
url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}
138+
139+
steps:
140+
- name: 📥 Download artifact
141+
uses: actions/download-artifact@v4
142+
with:
143+
name: node-app
144+
path: ./app
145+
146+
- name: 🔐 Login to Azure
147+
uses: azure/login@v1
148+
with:
149+
creds: ${{ secrets.AZURE_CREDENTIALS }}
150+
151+
- name: 🚀 Deploy to staging slot
152+
id: deploy-to-webapp
153+
uses: azure/webapps-deploy@v3
154+
with:
155+
app-name: ${{ env.AZURE_WEBAPP_NAME }}
156+
slot-name: staging
157+
package: ./app
158+
159+
- name: 🧪 Run integration tests
160+
run: |
161+
echo "Running integration tests against staging..."
162+
# Add your integration test commands here
163+
echo "✅ Integration tests passed!"
164+
165+
# ========================================
166+
# JOB 4: DEPLOY TO PRODUCTION
167+
# ========================================
168+
deploy-prod:
169+
name: Deploy to Production
170+
runs-on: ubuntu-latest
171+
needs: deploy-staging
172+
environment:
173+
name: production
174+
url: ${{ steps.swap-slots.outputs.webapp-url }}
175+
176+
steps:
177+
- name: 🔐 Login to Azure
178+
uses: azure/login@v1
179+
with:
180+
creds: ${{ secrets.AZURE_CREDENTIALS }}
181+
182+
- name: 🔄 Swap staging to production
183+
id: swap-slots
184+
run: |
185+
az webapp deployment slot swap \
186+
--resource-group rg-az400-demo \
187+
--name ${{ env.AZURE_WEBAPP_NAME }} \
188+
--slot staging \
189+
--target-slot production
190+
191+
echo "webapp-url=https://${{ env.AZURE_WEBAPP_NAME }}.azurewebsites.net" >> $GITHUB_OUTPUT
192+
193+
- name: 🏷️ Create release tag
194+
if: success()
195+
uses: actions/github-script@v7
196+
with:
197+
script: |
198+
const tag = `v${context.runNumber}`;
199+
await github.rest.git.createRef({
200+
owner: context.repo.owner,
201+
repo: context.repo.repo,
202+
ref: `refs/tags/${tag}`,
203+
sha: context.sha
204+
});
205+
console.log(`✅ Created tag: ${tag}`);
206+
207+
- name: 📊 Monitor deployment
208+
run: |
209+
echo "Monitoring production deployment..."
210+
# Add Application Insights queries here
211+
echo "✅ Production deployment healthy!"
212+
213+
# ========================================
214+
# REUSABLE WORKFLOW: SECURITY SCAN
215+
# ========================================
216+
security-scan:
217+
name: Security Scanning
218+
runs-on: ubuntu-latest
219+
if: github.event_name == 'pull_request'
220+
221+
steps:
222+
- name: 📥 Checkout code
223+
uses: actions/checkout@v4
224+
225+
- name: 🔍 Run CodeQL Analysis
226+
uses: github/codeql-action/analyze@v2
227+
with:
228+
languages: javascript
229+
230+
- name: 🛡️ Run Dependabot scan
231+
uses: github/super-linter@v5
232+
env:
233+
DEFAULT_BRANCH: main
234+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
235+
VALIDATE_JAVASCRIPT_ES: true
236+
VALIDATE_JSON: true
237+
VALIDATE_YAML: true

pipelines/README.md

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# Pipeline Examples for AZ-400 Training
2+
3+
This directory contains verified YAML pipeline examples for teaching CI/CD concepts in the AZ-400 course.
4+
5+
## 📁 Pipeline Files
6+
7+
### 1. Single-Stage CI Pipeline (`single-stage-ci.yml`)
8+
**Purpose:** Basic continuous integration for Node.js applications
9+
10+
**Key Features:**
11+
- Node.js setup and dependency installation
12+
- Linting and code quality checks
13+
- Unit testing with coverage
14+
- Artifact creation and publishing
15+
- Clear commenting for learning
16+
17+
**Use Case:** Teaching CI fundamentals in Segment 2
18+
19+
### 2. Multi-Stage CI/CD Pipeline (`multi-stage-cicd.yml`)
20+
**Purpose:** Complete DevOps pipeline with multiple environments
21+
22+
**Key Features:**
23+
- 5 stages: Build → Dev → Staging → Production → Post-Deploy
24+
- Environment approvals and gates
25+
- Blue-green deployment strategy
26+
- Automated rollback on failure
27+
- Performance and integration testing
28+
- Deployment slots and swapping
29+
30+
**Use Case:** Advanced pipeline concepts in Segment 3
31+
32+
### 3. GitHub Actions Workflow (`../.github/workflows/node-azure-deploy.yml`)
33+
**Purpose:** GitHub-native CI/CD to Azure
34+
35+
**Key Features:**
36+
- Matrix strategy for multiple Node versions
37+
- GitHub environments with protection rules
38+
- Azure Web App deployment
39+
- Release tagging
40+
- Security scanning with CodeQL
41+
- Reusable workflow patterns
42+
43+
**Use Case:** Comparing Azure Pipelines vs GitHub Actions
44+
45+
## 🚀 How to Use These Examples
46+
47+
### For Azure Pipelines:
48+
1. Create a new pipeline in Azure DevOps
49+
2. Select "Existing Azure Pipelines YAML file"
50+
3. Choose the appropriate YAML file
51+
4. Update variables (service connections, resource names)
52+
5. Save and run
53+
54+
### For GitHub Actions:
55+
1. Workflow is automatically detected in `.github/workflows/`
56+
2. Configure secrets in repository settings:
57+
- `AZURE_CREDENTIALS` - Service principal JSON
58+
3. Workflow triggers on push to main/master
59+
60+
## 📝 Required Configuration
61+
62+
### Azure Resources:
63+
```bash
64+
# Create resource group
65+
az group create --name rg-az400-demo --location eastus
66+
67+
# Create App Service Plan
68+
az appservice plan create \
69+
--name plan-az400-demo \
70+
--resource-group rg-az400-demo \
71+
--sku B1 \
72+
--is-linux
73+
74+
# Create Web Apps
75+
az webapp create \
76+
--name webapp-az400-demo-dev \
77+
--resource-group rg-az400-demo \
78+
--plan plan-az400-demo \
79+
--runtime "NODE:18-lts"
80+
```
81+
82+
### Service Connection (Azure DevOps):
83+
1. Project Settings → Service connections
84+
2. New service connection → Azure Resource Manager
85+
3. Service principal (automatic)
86+
4. Name: `AZ400-ServiceConnection`
87+
88+
### GitHub Secrets:
89+
```bash
90+
# Create service principal
91+
az ad sp create-for-rbac \
92+
--name "sp-az400-github" \
93+
--role contributor \
94+
--scopes /subscriptions/{subscription-id}/resourceGroups/rg-az400-demo \
95+
--json-auth
96+
```
97+
98+
## 🎓 Teaching Points
99+
100+
### Single-Stage Pipeline:
101+
- Pipeline triggers and paths
102+
- Agent pools and VM images
103+
- Variables and expressions
104+
- Task vs script steps
105+
- Artifact publishing
106+
107+
### Multi-Stage Pipeline:
108+
- Stage dependencies
109+
- Deployment jobs vs regular jobs
110+
- Environment approvals
111+
- Deployment strategies
112+
- Failure handling
113+
114+
### GitHub Actions:
115+
- Workflow syntax differences
116+
- Actions marketplace
117+
- Environments and secrets
118+
- Reusable workflows
119+
- GitHub-specific features
120+
121+
## 🔧 Customization
122+
123+
Students can modify these pipelines to:
124+
- Add additional testing frameworks
125+
- Implement different deployment strategies
126+
- Add notifications (Teams, Slack)
127+
- Include infrastructure as code
128+
- Add security scanning tools
129+
130+
## 📚 Additional Resources
131+
132+
- [Azure Pipelines YAML schema](https://learn.microsoft.com/azure/devops/pipelines/yaml-schema)
133+
- [GitHub Actions documentation](https://docs.github.com/actions)
134+
- [Azure Web Apps deployment](https://learn.microsoft.com/azure/app-service/deploy-github-actions)

0 commit comments

Comments
 (0)