You’ve been handed a Node.js web application called LearnSphere, ready for deployment. The team wants to streamline releases by implementing a CI/CD pipeline using Azure DevOps. The goal: automate everything from code commit to build, package, deploy, and monitor on Azure App Service.
Demo Repo:
https://github.com/josephjem2/bootcamp-cicd-demo.git
- Fork and clone the dummy app repository
- Run the app locally and validate the
/healthendpoint - Deploy the app to Azure App Service (Free F1 plan)
- Create an Azure DevOps project and configure a service connection
- Set up a YAML pipeline to build, package, and publish the app
- Add a deployment stage to push the app to Azure App Service
- Validate the deployment by browsing the app and testing
/health - Troubleshoot common issues (artifacts, start script, hosted agent limits)
- Add monitoring with Application Insights
- Azure account (Free Trial)
- Azure DevOps organization (Sign up free)
- Node.js 20.x installed locally
- Git & PowerShell
git clone https://github.com/<your-username>/bootcamp-cicd-demo.git
cd bootcamp-cicd-demoReplace
<your-username>with your GitHub username.
npm install
npm start- Visit http://localhost:3000 → should display Hello Bootcamp!
- Visit http://localhost:3000/health → should return OK
⚠️ If you seenpm warn EBADENGINE, it’s a version mismatch. For demo, continue; for production, match Node.js version.
- In Azure Portal, search for App Service.
- Click Create → Web App.
- Fill out:
- Resource Group: e.g.,
bootcamp-rg - Name: globally unique, e.g.,
bootcamp-cicd-demo-app - Region: closest to you
- Runtime stack: Node.js 20 (Windows)
- Pricing plan: Free (F1)
- Resource Group: e.g.,
- Leave other settings as default → Review + Create → Create
- Once deployed, test the default URL:
https://<appname>.azurewebsites.net
- Go to Azure DevOps, create a new organization if needed.
- Create a new project (e.g.,
bootcamp-cicd-demo). - Navigate to Project Settings → Service connections → New service connection.
- Choose Azure Resource Manager → Service principal (automatic).
- Name it (e.g.,
AzureBootcampConnection), grant access to all pipelines.
- Go to Project Settings → Agent pools.
- Create an Agent Pool (e.g.,
BootcampPool). - Download and configure the agent on your machine (Windows recommended).
- Extract the ZIP, run
.\\config.cmdin PowerShell, provide:- Server URL:
https://dev.azure.com/<yourorg> - Authentication: PAT (Personal Access Token)
- Agent pool:
BootcampPool - Agent name: e.g.,
bootcamp-agent-1
- Server URL:
- Start the agent:
.\\run.cmd - (Optional) Install as a service:
.\\svc installthen.\\svc start - Verify in Azure DevOps: Agent should show as Online.
- In Azure DevOps, go to Pipelines → New Pipeline.
- Select GitHub → your forked repo.
- Choose Existing Azure Pipelines YAML file → select
azure-pipelines.yml. - Review and run the pipeline.
Sample azure-pipelines.yml:
trigger:
- main
pool:
vmImage: 'ubuntu-latest' # Or your self-hosted pool
steps:
- task: NodeTool@0
inputs:
versionSpec: '20.x'
displayName: 'Install Node.js'
- script: |
npm install
npm test
displayName: 'Install dependencies & run tests'
- task: CopyFiles@2
inputs:
SourceFolder: '$(Build.SourcesDirectory)'
Contents: |
app.js
package.json
package-lock.json
web.config
node_modules/**/*
TargetFolder: '$(Build.ArtifactStagingDirectory)/app'
displayName: 'Stage app files'
- task: ArchiveFiles@2
inputs:
rootFolderOrFile: '$(Build.ArtifactStagingDirectory)/app'
includeRootFolder: false
archiveType: 'zip'
archiveFile: '$(Build.ArtifactStagingDirectory)/app.zip'
replaceExistingArchive: true
- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: 'drop'Validation: Build succeeds,
app.zipappears in Artifacts.
Add to your pipeline YAML:
- task: AzureWebApp@1
inputs:
azureSubscription: '$(azureServiceConnection)'
appName: '$(appServiceName)'
package: '$(System.DefaultWorkingDirectory)/**/*.zip'
displayName: 'Deploy to Azure App Service'Validation: Deployment logs show success, App Service updated.
- Visit
https://<appname>.azurewebsites.net→ Hello Bootcamp! - Visit
https://<appname>.azurewebsites.net/health→ OK
- In Azure Portal → App Service → Application Insights → Enable → Apply.
- Open Live Metrics Stream in Application Insights.
- Generate traffic:
for i in {1..20}; do curl https://<appname>.azurewebsites.net/health; sleep 1; done
- Watch Live Metrics update (request rate, response times, success rate).
Simulate a failure: Stop App Service, run the loop again, observe failures in Live Metrics.
- Reproduce the issue
- Check the basics (app running, URL correct)
- Read error messages
- Check logs & metrics
- Isolate the problem (code, config, platform)
- Apply fix & retest
- Document the resolution
- App won’t load: Service stopped, wrong runtime, missing startup file (
web.configor startup command) - Pipeline fails: Permission denied, missing service connection, build step fails (check YAML, missing files)
- App deployed but not starting: Tail logs with
az webapp log tail --name <appname> --resource-group <rg>
- Live Metrics empty: Enable Application Insights, generate traffic, restart App Service, check connection string
- Git push rejected:
git pull --rebase origin main git push origin main
- Break & Fix: Remove
web.config, redeploy, troubleshoot - Pipeline Error: Misconfigure YAML, fix it
- Monitoring Drill: Stop app, observe failures in Live Metrics
- Git Conflict: Trigger push rejection, resolve with rebase
-
Stop or Delete App Service:
Azure Portal → App Service → Stop/DeleteValidation: App URL no longer responds
-
Remove Application Insights:
Delete the resourceValidation: No telemetry charges
-
Delete Resource Group (fastest):
az group delete --name <resource-group-name> --yes --no-wait
Validation: All resources in RG are gone
-
Clean Azure DevOps Artifacts:
Delete pipeline runs/artifacts if not neededValidation: No leftover artifacts consuming storage
- Troubleshooting is structured, not guesswork
- Logs & metrics are your best allies
- Every error is a learning opportunity
- Documenting fixes builds a knowledge base for the team