Build a CI/CD Pipeline with Azure DevOps

Build a YAML pipeline that auto-deploys a Node.js app to Azure App Service.

Introduction

30 Second Summary

Every time a developer changes their code, someone has to build it, test it, and push it live. Doing that by hand is slow, error-prone, and exhausting at scale.

In this project, you will build a CI/CD pipeline using Azure DevOps that automatically builds, tests, and deploys a web application every time you push a code change.

What You'll Build

You will create a YAML-based pipeline in Azure Pipelines that takes a Node.js web app from GitHub, builds and tests it, then deploys it to a live URL on Azure App Service.

By the end of this project, you'll have:

  • A GitHub repository with a Node.js web application connected to Azure DevOps.
  • A YAML pipeline that automatically builds, tests, and deploys your app on every code push.
  • A live web app running on Azure App Service at a public URL that updates itself when you change your code.
  • Secret Mission: add a second pipeline stage that deploys to a staging environment with a manual approval gate.

Are there any prerequisites?

None. This project walks you through setting up every tool you need, including Git, Node.js, GitHub, and Azure. All of the services used in this project are free.

Install Git and Node.js on Windows

Before you can build a CI/CD pipeline, you need a few core tools on your machine. Git is the version control system that tracks every change you make to your code and sends those changes to GitHub.

Node.js is the JavaScript runtime that powers the sample web app you will deploy. In this step, you will install Git, Node.js, and a code editor so your machine is ready for the rest of the project.

In this step, get ready to:
  • Install Git for Windows and verify it works from the command line.
  • Install Node.js 24 LTS and verify both node and npm commands work.
  • Install VS Code as your code editor.
Install Git for Windows
  • Download Git from the official Git for Windows page.
  • Run the downloaded installer.
  • The installer walks you through several screens of options. Accept the default settings on every screen by clicking Next until the installation completes.

What is Git?

Git is a version control system. It tracks every change you make to your code, so you can review history, undo mistakes, and collaborate with others.

In this project, Git sends your code changes to GitHub. From there, Azure DevOps picks up the changes and runs your pipeline automatically.

  • Press the Windows key to open your search bar.
  • Type Command Prompt and press Enter to open it.
  • Verify Git is installed by running this command:
git --version

You should see output like git version 2.47.1. The exact number may differ, but any 2.x.x version means Git is installed correctly.

Don't see a version number?

Make sure you opened a new Command Prompt window after the installer finished. PATH changes only take effect in new terminal windows.

If Git still is not recognized, rerun the installer and confirm the option to add Git to your PATH is checked. It should be selected by default.

Help me troubleshoot my Git installation on Windows.

Install Node.js
  • Download Node.js 24 LTS from the official Node.js website.
  • Run the Windows installer (the .msi file).
  • Accept the default settings throughout the installer.

What is Node.js?

Node.js is a JavaScript runtime that lets you run JavaScript outside of a web browser. The sample app you will deploy in this project is built on Node.js.

The installer also includes npm (Node Package Manager), which handles downloading and managing your project's dependencies.

  • Close your current Command Prompt window and open a new one so your terminal picks up the updated PATH.
  • Verify Node.js and npm are installed by running these commands:
node --version
npm --version

Each command prints a version number. The node output starts with v24 and npm prints a number like 10.x.x. As long as you see numbers and no errors, both tools are installed correctly.

Commands not recognized?

Make sure you opened a brand new Command Prompt window after the Node.js installer finished. Existing terminal windows will not have the updated PATH.

If the commands still do not work, rerun the Node.js installer and confirm the option to add to PATH is enabled.

Help me troubleshoot my Node.js installation on Windows.

Install VS Code

You need a code editor to view and edit your pipeline file later in the project. VS Code is a free, lightweight editor that works well for this.

  • Download VS Code from the official VS Code website.
  • Run the downloaded installer.
  • On the Select Additional Tasks screen, check the box for Add to PATH.
  • Click Next through the remaining screens and complete the installation.

Why Add to PATH matters

Enabling Add to PATH lets you open files and folders in VS Code straight from the command line using the code command. This comes in handy later when you work with your project files.

Your machine is now equipped with Git, Node.js, and a code editor. Next up, you will create your GitHub and Azure accounts to connect everything together.

Create Your GitHub and Azure Accounts

Your development tools are installed and ready to go. Now it's time to set up the cloud accounts that power your CI/CD pipeline.

A CI/CD pipeline needs three things: a place to store your code, a service to run your pipeline, and a platform to host your deployed app. You'll create accounts on GitHub, Azure, and Azure DevOps to cover all three.

In this step, get ready to:
  • Fork a sample Node.js app on GitHub.
  • Create a free Azure account with $200 in credits.
  • Set up an Azure DevOps organization and project.
Create a GitHub account and fork the sample app

GitHub is where your source code lives. Your pipeline watches this repository for changes and automatically triggers a new build whenever you push code.

  • Open your browser and go to github.com.
  • Sign in to your GitHub account.

Don't have a GitHub account?

Click Sign up on the GitHub homepage to create a free account. All you need is an email address.

Instead of building an app from scratch, you'll fork an existing sample app. Forking creates your own copy of a repository that you can modify freely.

  • Navigate to the sample repository at Azure-Samples/nodejs-docs-hello-world.
  • Click Fork near the top right of the page.
  • Make sure your GitHub account is selected as the Owner.
  • Click Create fork.

Your forked repository page loads. You'll see your username followed by /nodejs-docs-hello-world at the top, with "forked from Azure-Samples/nodejs-docs-hello-world" underneath.

Why fork instead of building from scratch?

This sample app is a minimal Node.js "Hello World" application maintained by Microsoft. Forking it saves time and keeps the project focused on learning pipeline mechanics instead of writing application code.

Create a free Azure account

Azure is Microsoft's cloud platform. This is where your app will be hosted and accessible to anyone on the internet.

  • Go to azure.microsoft.com/free.
  • Click Start free.
  • Sign in with a Microsoft account. If you don't have one, create a new Microsoft account when prompted.
  • Follow the prompts to complete your signup.

Will my credit card be charged?

Azure requires a credit card for identity verification only. You will not be charged. Everything in this project uses free-tier resources.

Once your signup is complete, the Azure portal opens at portal.azure.com. You should see a welcome page or dashboard confirming your $200 free credits are active.

Coming from AWS?

The Azure portal is similar to the AWS Management Console. Later in this project, you'll use Azure App Service, which plays a similar role to AWS Elastic Beanstalk.

Azure DevOps is the equivalent of combining AWS CodePipeline and CodeBuild into one service.

Create an Azure DevOps organization and project

Azure DevOps is where your CI/CD pipeline lives. It watches your GitHub repository, builds your code, runs tests, and deploys automatically.

  • Go to dev.azure.com.
  • Sign in with the same Microsoft account you used for your Azure signup.
  • Click Create new organization and follow the prompts.
  • Once your organization is created, click New project.
  • Enter my-first-pipeline as the project name.
  • Select Private for visibility.
  • Click Create.

Your project dashboard loads, showing the my-first-pipeline project.

Not seeing the option to create a project?

Make sure you signed into dev.azure.com with the same Microsoft account you used for your Azure signup. Using different accounts creates separate environments that can't connect to each other.

Help me troubleshoot my Azure DevOps setup.

There's one more critical setup task. New Azure DevOps organizations do not automatically receive free parallel jobs, which your pipeline needs in order to run.

Approval can take several business days

Microsoft reviews parallel job requests manually. Approval can take up to 2-3 business days.

You can continue with the rest of this project while you wait. Everything up to running the pipeline works without the grant. If your pipeline later fails with No hosted parallelism has been purchased or granted, the grant hasn't been approved yet.

What are parallel jobs?

A parallel job is a compute slot that runs your pipeline. The free tier gives you one Microsoft-hosted job with 1,800 minutes per month, which is more than enough for this project.

Your accounts are set up and your sample app is forked. Next, you'll deploy the app to Azure and see it running live on the internet.

Deploy the App to Azure App Service

Your accounts are set up and your tools are installed. Now it's time to get the sample app running on a live server that anyone can visit.

You'll deploy the Node.js app to Azure App Service, a cloud hosting platform for web apps. To set everything up, you'll work inside Azure Cloud Shell, a terminal built right into the Azure portal.

In this step, get ready to:
  • Open Azure Cloud Shell and clone your forked repository.
  • Deploy the app to Azure App Service on the free tier.
  • Verify the live site in your browser.
Open Azure Cloud Shell and clone the repo

Azure Cloud Shell comes with Git and the Azure CLI pre-installed. You don't need to install anything on your own machine for this step.

What is Azure Cloud Shell?

Azure Cloud Shell is a free, browser-based terminal built into the Azure portal. It gives you a pre-configured environment with common tools like Git, Node.js, and the Azure CLI already installed.

If you've used AWS CloudShell before, this is the Azure equivalent.

  • Go to the Azure portal. You should already be signed in from the previous step.
  • Click the Cloud Shell button on the top toolbar. It looks like a terminal icon (>_).
  • When prompted to choose a shell type, select Bash.

First time opening Cloud Shell?

If this is your first time using Cloud Shell, Azure creates a small storage account to persist your files between sessions. Click Create storage when prompted. This only happens once and takes a few seconds.

  • Clone your forked repository into Cloud Shell by running this command:
git clone https://github.com/[[GITHUB_USERNAME="your GitHub username"]]/nodejs-docs-hello-world

What does this command do?

`git clone` downloads a full copy of your forked GitHub repository into Azure Cloud Shell. This is the Node.js app you'll deploy to Azure App Service in the next substep.

  • Move into the project folder by running:
cd nodejs-docs-hello-world
  • Confirm the repository files are present by running:
ls

You should see files like index.js and package.json listed in the output.

Seeing 'repository not found'?

  • Make sure the GitHub username you entered in the clone command matches your actual GitHub username exactly.
  • Verify your fork exists by going to your GitHub profile and checking that the nodejs-docs-hello-world repository is listed.
  • Help me fix my git clone command in Azure Cloud Shell.
Create the App Service with the free tier

The az webapp up command handles the entire deployment in a single step. It creates all the Azure resources you need and deploys your code at the same time.

  • Create and deploy your App Service by running this command in Cloud Shell:
az webapp up --sku F1 --name [[APP_NAME="a unique name like yourname-nodeapp"]]

What does this command do?

  • `--sku F1` selects the free tier for Azure App Service. No charges apply.
  • `--name` sets your app's unique name, which becomes part of your public URL.
  • Behind the scenes, this single command creates three Azure resources: a resource group (a container for related resources), an App Service plan (the server infrastructure), and the web app itself.

This command takes 1-2 minutes to complete. When it finishes, you'll see JSON output in the terminal.

  • Find the URL field in the JSON output. It looks something like https://your-app-name.azurewebsites.net.
  • Copy this URL. You'll use it to verify your live site in the next substep.

Seeing an error?

  • If you see The webapp name is not available, your app name is already taken. Try a more unique name, like adding your initials and a number.
  • If you see an error about runtime detection, make sure you ran cd nodejs-docs-hello-world first. The command needs to run inside the project folder to detect the Node.js app.
  • Help me troubleshoot the az webapp up command in Azure Cloud Shell.
Verify the live site

Your app is now deployed. Time to confirm it's working.

  • Open a new browser tab.
  • Paste the URL you copied from the previous substep into the address bar and press Enter.

You should see the Hello World! page from the Node.js app. This confirms your application is live on Azure App Service and accessible to anyone on the internet.

Seeing an error page instead?

  • The app can take a minute or two to become available after deployment. Wait 30 seconds and refresh the page.
  • Make sure the URL matches the one from your az webapp up output. It should end in .azurewebsites.net.
  • My Azure App Service site is showing an error instead of Hello World.

Your app is live on Azure. Next up, you'll create the CI/CD pipeline in Azure DevOps that automatically rebuilds and redeploys this app every time you push a code change.

Create the CI/CD Pipeline in Azure DevOps

Your app is live on Azure App Service. Anyone can visit the URL and see your "Hello World!" page.

Right now, every code change requires you to manually redeploy. In this step, you'll create a CI/CD pipeline in Azure DevOps that automatically builds and deploys your app whenever you push code to GitHub.

In this step, get ready to:
  • Connect your GitHub repository to Azure Pipelines.
  • Configure a pipeline template and create a service connection to Azure.
  • Review the generated YAML pipeline file and trigger your first pipeline run.
Connect your GitHub repo to Azure Pipelines

Azure Pipelines needs access to your GitHub repository so it can detect code changes and pull your source code during builds.

  • In your Azure DevOps project, click Pipelines in the left sidebar.
  • Click New pipeline.
  • On the "Where is your code?" screen, select GitHub.

GitHub redirects you to authorize the Azure Pipelines app. This is a one-time setup that lets Azure DevOps access your repositories.

  • Click Approve & install on the GitHub authorization page.
  • Select your forked nodejs-docs-hello-world repository from the list.

Don't see your repository?

Make sure you're signed into the same GitHub account that owns the fork. If the repository list is empty, click the Authorize link to re-grant access to the Azure Pipelines app.

Help me connect my GitHub repository to Azure Pipelines.

Configure the pipeline template

Azure Pipelines analyzes your repository and suggests templates that match your app's technology stack. You'll select a template designed for Node.js apps deploying to Azure.

  • Select Node.js Express Web App to Linux on Azure from the suggested templates.
  • Select your Azure subscription from the dropdown.
  • Click Continue.

What is a service connection?

When you selected your Azure subscription, Azure DevOps created a service connection behind the scenes. This is a secure link between your Azure DevOps project and your Azure subscription that authorizes the pipeline to deploy resources on your behalf.

If you've used AWS, think of it like an IAM role that grants deployment permissions.

  • Select your App Service web app from the Web App name dropdown.
  • Click Validate and configure.

Azure Pipelines generates an azure-pipelines.yml file and displays it in the editor. This file defines your entire CI/CD pipeline.

Review the YAML and save

Before saving, take a moment to understand what Azure Pipelines generated for you.

What's in the generated YAML?

The YAML pipeline has a few key sections:

  • trigger: main tells the pipeline to run automatically on every push to the main branch.
  • The pool section specifies a Microsoft-hosted build agent. This is a virtual machine that runs your pipeline steps.
  • The build steps install Node.js, run npm install to grab dependencies, and run npm test.
  • The deploy steps package your app into a ZIP file and use the AzureWebApp task to deploy it to your App Service.

Why YAML instead of a visual editor?

Azure DevOps also offers a visual "Classic" pipeline editor, but YAML pipelines are the modern, recommended approach. YAML files live inside your repository alongside your code, so your pipeline definition is version-controlled and portable.

Most CI/CD tools (GitHub Actions, GitLab CI, CircleCI) also use declarative config files. Learning YAML pipelines here builds a transferable skill.

  • Click Save and run in the top right corner.
  • A commit dialog appears. Click Save and run again to confirm.

Why two clicks?

The first click opens a commit dialog where you can customize the commit message and branch. The second click confirms the commit. Azure DevOps commits the azure-pipelines.yml file directly to the main branch of your GitHub repository, which is what triggers the pipeline.

You'll be taken to the pipeline run summary page. If you see the pipeline running or queued, your CI/CD pipeline is set up correctly.

Pipeline stuck in the queue?

If your pipeline shows as queued but never starts running, your free parallel jobs grant hasn't been approved yet. Check your request status at https://aka.ms/azpipelines-parallelism-request. Approval can take several business days.

You can continue reviewing your pipeline configuration while waiting. Everything else is ready to go.

Help me troubleshoot my queued pipeline.

Your pipeline is live and connected to GitHub. Next up, you'll watch the pipeline execute in real time and trigger an automatic deployment by changing a single line of code.

Watch the Pipeline Run and Trigger a CI Build

Your pipeline is created and your first run has been triggered. That proves the YAML pipeline works when you kick it off manually from Azure DevOps.

The real test of CI/CD is whether it works automatically. In this step, you'll edit your app's code, push the change, and watch the pipeline trigger all on its own.

In this step, get ready to:
  • Monitor the pipeline run and verify each step passes.
  • Make a code change and push it to trigger an automatic rebuild.
  • Confirm the updated app deploys to your live site without any manual steps.
Monitor the pipeline execution

When you selected Save and run in the previous step, Azure Pipelines kicked off your first pipeline run. Let's check how it went.

  • In your Azure DevOps project, select Pipelines from the left navigation menu.
  • Select the most recent pipeline run at the top of the list.
  • On the run Summary page, select the job name to see the detailed execution log.

You should see a list of pipeline steps, each with a green checkmark indicating success.

What do all these pipeline steps do?

Each step in your pipeline handles one piece of the build and deploy process.

  • Use Node installs the specified Node.js version on the build agent.
  • npm install downloads the app's dependencies.
  • npm test runs any automated tests. If a test fails, the pipeline stops and does not deploy broken code.
  • Archive files packages the app into a ZIP file, ready for deployment.
  • Azure Web App Deploy pushes the packaged app to your Azure App Service instance.

Seeing a parallelism error?

If you see ##[error]No hosted parallelism has been purchased or granted., your free parallel job grant has not been approved yet. New Azure DevOps organizations must request this at https://aka.ms/azpipelines-parallelism-request. Approval can take several business days.

You can continue reviewing the pipeline configuration while you wait. Re-run the pipeline after approval by selecting Run pipeline in Azure Pipelines.

Help me troubleshoot my Azure Pipelines parallelism error

  • Once the Azure Web App Deploy step succeeds, look for the App Service Application URL link in the deploy step's log output.
  • Select that link to open your deployed app in a new browser tab.

You should see the "Hello World!" page, confirming the pipeline built and deployed your app successfully.

Make a code change and trigger CI

Your pipeline has a trigger: main line in the YAML file. This means every commit pushed to the main branch automatically starts a new pipeline run. Let's prove it works.

  • Open your forked GitHub repository in your browser at https://github.com/YOUR-GITHUB-USERNAME/nodejs-docs-hello-world.
  • Select the index.js file from the file list.
  • Select the pencil (edit) icon in the top right corner of the file view.

GitHub opens the file in its browser-based editor.

  • Find the line that contains res.send('Hello World!');.
  • Change Hello World! to Hello from my CI/CD pipeline!.
  • Select the Commit changes... button in the top right.
  • In the commit dialog, select Commit changes to confirm.

What just happened?

When you committed the change, GitHub pushed it to the main branch. Because your pipeline's trigger is set to main, Azure Pipelines detects the new commit and starts a fresh build automatically.

This is the "Continuous Integration" part of CI/CD. Every code change triggers a build and test cycle with zero manual effort.

Verify the automatic deployment

Your pipeline should already be running. Let's confirm the full CI/CD loop: code change, automatic build, and live deployment.

  • Go back to your Azure DevOps project at https://dev.azure.com.
  • Select Pipelines from the left navigation menu.
  • Look for a new pipeline run at the top of the list. The trigger column should show Individual CI, confirming it was triggered automatically by your code change.
  • Select the run and watch it progress through each step.

Don't see a new pipeline run?

Make sure you committed the change to the main branch, not a different branch. The pipeline only triggers on pushes to main.

Also check that the Azure Pipelines GitHub app is still authorized. You can verify this by going to your GitHub repository, selecting Settings, then Integrations, and confirming Azure Pipelines is listed.

Help me figure out why my pipeline didn't trigger automatically

  • Wait for the pipeline run to complete. All steps should show green checkmarks again.
  • Open your Azure App Service URL in a browser tab:
https://[[APP_NAME="your app name"]].azurewebsites.net
  • If you already have the tab open from earlier, do a hard refresh with Ctrl+Shift+R to clear cached content.

You should see your updated text: "Hello from my CI/CD pipeline!"

Why does this matter?

You just completed the full CI/CD loop. A single code change in GitHub triggered an automatic build, test, and deployment to a live website. No manual steps, no copying files, no restarting servers.

This is the foundation of how professional software teams ship code. Every change goes through the same automated pipeline, catching bugs early and deploying reliably.

Still seeing the old text?

Your browser may be showing a cached version of the page. Try a hard refresh with Ctrl+Shift+R or open the URL in a private/incognito window.

If the pipeline run failed, go back to Azure Pipelines and select the failed run to see which step has a red X. The error log usually points directly to the problem.

Help me debug why my updated app is not showing on Azure App Service

Secret mission

Add a Staging Environment with Manual Approval

Your pipeline deploys straight to production on every push. Real teams add a safety net: a staging environment with a manual approval gate that lets someone review changes before they go live.

Before you go

Clean Up Your Resources

Decide whether to keep your resources running, pause them to come back later, or delete them entirely.

Everything in this project runs on free tiers, so there are no ongoing costs.

Resources you used:

  • Azure App Service web app (F1 free tier).
  • App Service plan (free tier).
  • Azure resource group.
  • Azure DevOps organization and project (free tier).
  • Forked GitHub repository.
  • If you completed the Secret Mission: a second App Service web app and plan for staging.

Keep everything running

No action needed. Choose this if you are still actively building or want to keep experimenting with your pipeline.

  • All resources are on free tiers, so nothing will be charged.
  • Your pipeline will continue to build and deploy automatically on every push to the main branch.
  • Your App Service web app stays live at its public URL.

Pause - I'll come back to this later

Disable automatic builds so the pipeline does not run on every push. Your app stays online and your code stays intact.

  • In Azure DevOps, go to Pipelines in the left navigation menu.
  • Select your pipeline, then click the three-dot menu in the top right corner.
  • Select Settings.
  • Under Triggers, check Disable continuous integration trigger to stop automatic builds.
  • Your App Service web app remains live. You can re-enable the trigger anytime to resume CI/CD.

Delete - I don't want to use this again

Remove all project resources completely. This deletes your Azure resources, DevOps project, and forked repository.

  • Open Azure Cloud Shell from the Azure portal (click the terminal icon on the top toolbar).
  • Delete your App Service web app by running:
az webapp delete --name [[APP_NAME="your-app-name"]] --resource-group [[RESOURCE_GROUP="your-resource-group-name"]]
  • Delete your App Service plan by running:
az appservice plan delete --name [[PLAN_NAME="your-plan-name"]] --resource-group [[RESOURCE_GROUP="your-resource-group-name"]]
  • Delete the resource group by running:
az group delete --name [[RESOURCE_GROUP="your-resource-group-name"]]
  • If you completed the Secret Mission, repeat the web app and plan delete commands for your staging app.
  • To delete the Azure DevOps project, go to Project Settings, then Overview, and click Delete at the bottom of the page.
  • To delete the forked GitHub repository, go to the repo Settings tab, scroll to the bottom, and click Delete this repository.

Mission accomplished

That's a Wrap!

Nice work! You just built a fully automated CI/CD pipeline from scratch using Azure DevOps. Every time you push a code change, your pipeline automatically builds, tests, and deploys your app to a live URL.

You've learned how to:

  • Build a working YAML pipeline in Azure DevOps that triggers automatically on every code push.
  • Deploy a live Node.js web app to Azure App Service on the free tier.
  • Make a code change and watch it automatically build, test, and deploy to production.
  • Secret Mission: Add a multi-stage pipeline with a staging environment and a manual approval gate.

Ready to quiz yourself?