Build a CI/CD Pipeline with Azure DevOps

Automate building and testing a Node.js app with Azure DevOps pipelines.

Introduction

30 Second Summary

Every time a developer saves their code, someone needs to check it compiles, passes its tests, and is packaged up ready to ship. Doing this by hand is slow and error-prone. Automated pipelines handle all of it in seconds.

In this project, you will build a CI/CD pipeline in Azure DevOps that automatically builds, tests, and packages a Node.js application every time you push code to GitHub.

What You'll Build

A fully automated CI pipeline that triggers on every code push, installs dependencies, runs tests, and publishes a build artifact ready for deployment.

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

  • A GitHub repository with a simple Node.js application and automated tests.
  • A YAML pipeline in Azure DevOps that builds, tests, and packages your app on every push.
  • A published build artifact in Azure DevOps ready for deployment.
  • Secret Mission: Extend your pipeline into a multi-stage CI/CD structure with separate Build and Deploy stages.

Are there any prerequisites?

You need a basic understanding of Git (commits and pushing code). No prior CI/CD experience is required.

Set Up Your Accounts and Repository

Before you can build a pipeline, you need the tools and services that power it. Azure DevOps needs a code repository to watch, and your code needs a home to live in.

In this step you will create a GitHub repository, sign up for Azure DevOps, and set up a simple Node.js application that your pipeline will build and test later.

In this step, get ready to:
  • Create a GitHub repository and clone it to your computer.
  • Sign up for Azure DevOps and create a project.
  • Set up a Node.js application with tests and push it to GitHub.
Create a GitHub account and repository

Your pipeline needs source code to build. GitHub is where your code will live, and Azure DevOps will connect to it to detect new pushes.

  • Open github.com in your browser.
  • Sign in to your existing account, or click Sign up to create a free account.
  • In the upper-right corner of any page, click the + icon, then click New repository.
  • Enter azure-pipeline-demo as the repository name.
  • Set the visibility to Public.
  • Toggle Add a README file to On.
  • Click Create repository.

Your new repository is now live on GitHub with a README.md file.

Next, clone the repository to your local machine so you can add files to it.

  • Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
  • Type Terminal (macOS) or PowerShell (Windows) and press Enter to open it.
  • Move to your Desktop by running this command:
cd ~/Desktop
  • Clone your repository by running this command:
git clone [[REPO_URL="https://github.com/YOUR-USERNAME/azure-pipeline-demo.git"]]

Where do I find my repository URL?

On your repository page in GitHub, click the green Code button. Copy the HTTPS URL shown in the dropdown.

  • Move into the cloned folder by running:
cd azure-pipeline-demo
  • Confirm you are inside the repo by running:
ls

You should see README.md in the output.

Seeing 'git: command not found'?

Git is not installed on your machine. Download and install it from git-scm.com/downloads, then reopen your terminal and try the clone command again.

help me install Git so I can clone my GitHub repository

Sign up for Azure DevOps

Azure DevOps is the service that will run your pipeline. You need an organization and a project inside it to hold your pipeline configuration.

  • Open dev.azure.com in your browser.
  • Sign in with a Microsoft account. If you do not have one, click Create one! to make a free account.
  • When prompted, create a new organization. Accept the default name or choose your own.
  • Inside your organization, click New project.
  • Enter PipelineDemo as the project name.
  • Set visibility to Public, then click Create project.

What is an Azure DevOps organization?

An organization is the top-level container in Azure DevOps. Inside it, you create projects that hold your pipelines, repos, boards, and other resources.

The first 5 users are free, no credit card required.

Finally, request the free hosted parallelism grant so your pipeline can run.

Why do I need a parallelism grant?

New Azure DevOps organizations do not automatically receive hosted build minutes. The grant gives you 1,800 free minutes per month on Microsoft-hosted agents.

Approval takes 2-3 business days, but you can continue setting up your project right now. You will need the grant to actually run your pipeline in a later step.

Set up your Node.js app locally

Your pipeline will build and test a Node.js application. You need Node.js installed on your machine to initialize the project and run it locally.

  • Check if Node.js is already installed by running this command in your terminal:
node --version

✔️ I see a version number

Node.js is ready to go. Continue to the next instruction below.

ⓧ Command not found

Node.js is not installed yet.

  • Go to nodejs.org/en/download and download the LTS installer for your operating system.
  • Run the installer and accept the defaults.
  • Close and reopen your terminal.
  • Run node --version again to confirm installation.

Make sure your terminal is still inside the azure-pipeline-demo folder on your Desktop.

  • Initialize a Node.js project by running this command:
npm init -y

What does npm init -y do?

This creates a package.json file with default values. The -y flag accepts all defaults so you do not have to answer prompts.

You will replace its contents with a customized version in a moment.

Now open the project in a code editor to create your application files.

  • Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
  • Type VS Code and press Enter to open it.
  • In VS Code, click File in the top menu bar.
  • Click Open Folder.
  • Navigate to your Desktop, select the azure-pipeline-demo folder, and click Open.

Any code editor works

This project uses VS Code for screenshots, but you can use any text editor you are comfortable with.

  • Open package.json in the editor. Select all the content and replace it with the following:
{
  "name": "azure-pipeline-demo",
  "version": "1.0.0",
  "description": "A demo Node.js app for Azure DevOps CI/CD pipeline",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "build": "echo \"Build step complete\"",
    "test": "node index.test.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

What does this code do?

The scripts section defines commands your pipeline will use.

  • npm run build echoes a success message (a placeholder for a real build step).
  • npm test runs your test file to verify the app works.
  • npm start launches the application.
  • Save package.json.
  • Create a new file in the same folder called index.js and paste in the following code:
function greet(name) {
  return `Hello, ${name}! Welcome to Azure DevOps CI/CD.`;
}

function add(a, b) {
  return a + b;
}

module.exports = { greet, add };

console.log(greet("World"));

What does this code do?

This is your application. It defines two functions: greet returns a welcome message, and add sums two numbers.

The module.exports line makes these functions available to the test file. The last line prints a greeting when you run the file directly.

  • Save index.js.
  • Create another new file called index.test.js and paste in the following code:
const { greet, add } = require("./index");

let passed = 0;
let failed = 0;

function assert(condition, message) {
  if (condition) {
    console.log(`\u2713 PASS: ${message}`);
    passed++;
  } else {
    console.error(`\u2717 FAIL: ${message}`);
    failed++;
  }
}

// Test greet function
assert(greet("Alice") === "Hello, Alice! Welcome to Azure DevOps CI/CD.", "greet returns correct message");
assert(greet("") === "Hello, ! Welcome to Azure DevOps CI/CD.", "greet handles empty string");

// Test add function
assert(add(2, 3) === 5, "add returns correct sum");
assert(add(-1, 1) === 0, "add handles negative numbers");
assert(add(0, 0) === 0, "add handles zeros");

console.log(`\nResults: ${passed} passed, ${failed} failed`);

if (failed > 0) {
  process.exit(1);
}

What does this code do?

This is your test file. It imports the functions from index.js and checks that they return the correct results.

If any test fails, process.exit(1) tells the pipeline that something went wrong. Azure DevOps detects non-zero exit codes as failures.

  • Save index.test.js.
  • Verify your tests work by running this command in your terminal:
npm test

You should see output showing all 5 tests passing with a summary line at the end.

Tests failing or seeing an error?

Make sure your terminal is inside the azure-pipeline-demo folder. Check that both index.js and index.test.js are saved in the same folder as package.json.

help me debug why my npm test command is failing in my azure-pipeline-demo project

Now push all your files to GitHub so Azure DevOps can access them.

  • Stage, commit, and push your code by running these commands:
git add .
git commit -m "Initial app setup"
git push

What do these commands do?

  • git add . stages all new and changed files.
  • git commit -m "Initial app setup" saves a snapshot of your files with a descriptive message.
  • git push uploads your commit to the GitHub repository.
  • Go back to your azure-pipeline-demo repository on GitHub and refresh the page.

You should see index.js, index.test.js, and package.json listed alongside your README.md.

Push rejected or authentication error?

GitHub requires authentication for pushes. If prompted, sign in with your GitHub credentials or set up a personal access token.

help me authenticate with GitHub so I can push code from my terminal

✔️ Awesome, I've got everything!

Great. Double check that you have saved all three files.

ⓧ I'd like to double check the full code

Here is the complete code for each file. Make sure yours matches exactly.

{
  "name": "azure-pipeline-demo",
  "version": "1.0.0",
  "description": "A demo Node.js app for Azure DevOps CI/CD pipeline",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "build": "echo \"Build step complete\"",
    "test": "node index.test.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
function greet(name) {
  return `Hello, ${name}! Welcome to Azure DevOps CI/CD.`;
}

function add(a, b) {
  return a + b;
}

module.exports = { greet, add };

console.log(greet("World"));
const { greet, add } = require("./index");

let passed = 0;
let failed = 0;

function assert(condition, message) {
  if (condition) {
    console.log(`\u2713 PASS: ${message}`);
    passed++;
  } else {
    console.error(`\u2717 FAIL: ${message}`);
    failed++;
  }
}

// Test greet function
assert(greet("Alice") === "Hello, Alice! Welcome to Azure DevOps CI/CD.", "greet returns correct message");
assert(greet("") === "Hello, ! Welcome to Azure DevOps CI/CD.", "greet handles empty string");

// Test add function
assert(add(2, 3) === 5, "add returns correct sum");
assert(add(-1, 1) === 0, "add handles negative numbers");
assert(add(0, 0) === 0, "add handles zeros");

console.log(`\nResults: ${passed} passed, ${failed} failed`);

if (failed > 0) {
  process.exit(1);
}

Your accounts are ready and your code is live on GitHub. Next up, you will connect Azure DevOps to your repository and create your first pipeline.

Create Your First Pipeline in Azure DevOps

You have a Node.js app sitting in GitHub, but right now nothing happens when you push new code. Nobody checks whether the code builds correctly or whether the tests pass.

In this step, you will create a YAML pipeline in Azure DevOps that connects to your GitHub repository and automatically builds your app. This is the core of Continuous Integration.

In this step, get ready to:
  • Connect Azure DevOps to your GitHub repository.
  • Write your first pipeline YAML file.
  • Run the pipeline and watch it build your app.
Connect Azure DevOps to GitHub

Azure DevOps needs permission to access your GitHub repository before it can watch for changes and pull your code. The pipeline creation wizard handles this connection for you.

  • In your Azure DevOps project, select Pipelines from the left navigation menu.
  • Select Create Pipeline.
  • On the Where is your code? screen, select GitHub.
  • If prompted, sign in to GitHub with your credentials.
  • When asked to install the Azure Pipelines app, select Approve & install.
  • On the Select a repository screen, select your azure-pipeline-demo repository.

What is the Azure Pipelines GitHub app?

The Azure Pipelines GitHub app is a secure bridge between the two services. It grants Azure DevOps read access to your repository code and the ability to report build status back to GitHub.

You only need to authorize this once. All future pipelines in this project can reuse the same connection.

Don't see your repository in the list?

Make sure you authorized the Azure Pipelines app on the correct GitHub account. If you have multiple GitHub accounts, confirm you are signed in to the one that owns azure-pipeline-demo.

Help me find my repository in Azure DevOps

Choose a starter template and write your YAML

Azure DevOps offers pre-built templates to get you started quickly. You will start with the Starter pipeline template and replace its contents with your own custom YAML.

  • On the Configure your pipeline screen, select Starter pipeline.
  • Azure DevOps generates a basic azure-pipelines.yml file in the editor. Select all of its contents and delete them.
  • Replace the editor contents with the following YAML:
trigger:
  branches:
    include:
      - main

pool:
  vmImage: "ubuntu-latest"

steps:
  - task: UseNode@1
    inputs:
      version: "18.x"
    displayName: "Install Node.js"

  - script: |
      npm install
    displayName: "Install dependencies"

  - script: |
      npm run build
    displayName: "Build project"

What does this YAML do?

  • trigger tells the pipeline to run automatically whenever code is pushed to the main branch.
  • pool specifies that the pipeline runs on a Microsoft-hosted Ubuntu virtual machine. You do not need to manage any servers.
  • UseNode@1 installs Node.js 18.x on the build agent.
  • npm install downloads the project dependencies listed in package.json.
  • npm run build runs your build script, confirming the project compiles successfully.

Why YAML instead of a visual editor?

Microsoft recommends YAML pipelines for all new users. YAML pipelines live inside your repository alongside your code. This means your pipeline configuration is version-controlled, reviewable in pull requests, and portable between projects.

Classic pipelines (the visual editor approach) are considered legacy and lack these benefits.

Save and run the pipeline

When you save the pipeline, Azure DevOps commits your azure-pipelines.yml file directly into your GitHub repository. Then it immediately kicks off the first build.

  • Select Save and run in the top right corner.
  • A dialog appears asking you to commit azure-pipelines.yml to your repository. Keep the default commit message.
  • Select Save and run again to confirm.
  • Watch the build job execute. You should see each step (Install Node.js, Install dependencies, Build project) complete with a green checkmark.

What just happened?

Azure DevOps committed azure-pipelines.yml to the main branch of your GitHub repository. Because the file includes a trigger on main, the pipeline immediately ran.

From now on, every push to main will automatically trigger this pipeline.

✔️ I see green checkmarks on all steps

Your pipeline ran successfully. Azure DevOps installed Node.js, pulled your dependencies, and confirmed your project builds.

ⓧ I see a "No hosted parallelism has been purchased or granted" error

This means your free parallelism grant request has not been approved yet. Microsoft processes these requests within 2-3 business days.

Your pipeline YAML is saved and correct. Once the grant is approved, the pipeline will run automatically on your next push. You can continue to the next step in the meantime.

Help me resolve this parallelism error

ⓧ I see a different error

Check that you selected the correct repository (azure-pipeline-demo) and that your YAML has no indentation errors. YAML is whitespace-sensitive, so a single extra or missing space can break the file.

Compare your YAML against the code in the double-check tab below to make sure it matches exactly.

Help me troubleshoot my pipeline error

✔️ Awesome, I've got everything!

Great. Double check you have saved your file and that the pipeline has run at least once.

ⓧ I'd like to double check the full code

Here is the complete azure-pipelines.yml file at this point:

trigger:
  branches:
    include:
      - main

pool:
  vmImage: "ubuntu-latest"

steps:
  - task: UseNode@1
    inputs:
      version: "18.x"
    displayName: "Install Node.js"

  - script: |
      npm install
    displayName: "Install dependencies"

  - script: |
      npm run build
    displayName: "Build project"

Your pipeline is alive. Every push to main now triggers an automated build. Next up, you will add automated testing and publish a build artifact so your pipeline produces a deployable package.

Add Testing and Artifact Publishing

Your pipeline currently installs Node.js, installs dependencies, and builds the project. It doesn't verify that the code actually works or save the build output anywhere.

In this step, you'll add automated testing and artifact publishing to your pipeline. Testing catches bugs before they reach production. Artifact publishing packages your build output so it's ready for deployment.

In this step, get ready to:
  • Add a test step to your pipeline YAML.
  • Add artifact publishing tasks to save build output.
  • Trigger the updated pipeline and verify the artifact.
Update the pipeline to run tests

Your test file index.test.js is already in your repository from Step 1. You just need to tell the pipeline to run it.

  • In Azure DevOps, select Pipelines from the left sidebar.
  • Select your pipeline, then select Edit in the top right.
  • Find the step with displayName: "Build project" in your YAML.
  • Add the following code directly below that step:
  - script: |
      npm test
    displayName: "Run tests"

What does this step do?

npm test runs the command defined in your package.json scripts.test field, which executes node index.test.js.

If any test fails, process.exit(1) makes the script return a non-zero exit code. Azure Pipelines interprets non-zero exit codes as failures and stops the pipeline run.

You won't save yet. First, you'll add the artifact publishing tasks below.

Add artifact publishing

A pipeline artifact is a file or set of files produced by a build that you want to keep for later use, like deployment. You need two tasks: one to copy files to a staging area, and one to publish them.

  • In the pipeline editor, add the following code directly below the "Run tests" step you just added:
  - task: CopyFiles@2
    inputs:
      sourceFolder: "$(Build.SourcesDirectory)"
      contents: |
        index.js
        package.json
      targetFolder: "$(Build.ArtifactStagingDirectory)"
    displayName: "Copy project files"

  - task: PublishPipelineArtifact@1
    inputs:
      artifactName: "nodejs-app"
      targetPath: "$(Build.ArtifactStagingDirectory)"
    displayName: "Publish pipeline artifact"

What do these tasks do?

CopyFiles@2 copies index.js and package.json from your source code directory into a special staging folder that Azure Pipelines provides ($(Build.ArtifactStagingDirectory)).

PublishPipelineArtifact@1 takes everything in that staging folder and publishes it as a named artifact called nodejs-app. You can download or deploy this artifact later.

Seeing red squiggles in the editor?

YAML is whitespace-sensitive. Make sure each - task: and - script: line is indented with exactly 2 spaces from the steps: level. The inputs: and displayName: lines should be indented 4 spaces from the left margin.

help me fix YAML indentation errors in my Azure DevOps pipeline

✔️ Awesome, I've got everything!

Great. Double check that your indentation is consistent across all steps before saving.

ⓧ I'd like to double check the full code

Here is the complete azure-pipelines.yml file at this point:

trigger:
  branches:
    include:
      - main

pool:
  vmImage: "ubuntu-latest"

steps:
  - task: UseNode@1
    inputs:
      version: "18.x"
    displayName: "Install Node.js"

  - script: |
      npm install
    displayName: "Install dependencies"

  - script: |
      npm run build
    displayName: "Build project"

  - script: |
      npm test
    displayName: "Run tests"

  - task: CopyFiles@2
    inputs:
      sourceFolder: "$(Build.SourcesDirectory)"
      contents: |
        index.js
        package.json
      targetFolder: "$(Build.ArtifactStagingDirectory)"
    displayName: "Copy project files"

  - task: PublishPipelineArtifact@1
    inputs:
      artifactName: "nodejs-app"
      targetPath: "$(Build.ArtifactStagingDirectory)"
    displayName: "Publish pipeline artifact"
Trigger the pipeline with a code change
  • Select Save in the top right of the pipeline editor.
  • A commit dialog appears. Keep the default commit message and select Save again to commit directly to your branch.

Why does saving trigger the pipeline?

Saving in the pipeline editor commits the updated azure-pipelines.yml file to your GitHub repository. Your pipeline trigger is set to run on any commit to main, so the commit automatically starts a new pipeline run.

  • Watch the pipeline run. Select the running job to see each step execute in real time.
  • Once the run completes, return to the run summary page.
  • Look for the Published section at the bottom of the run summary. You should see your nodejs-app artifact listed there.

What should I see?

The pipeline run summary shows each step with a green checkmark. The "Run tests" step displays your test output (5 passed, 0 failed). The Published section at the bottom shows the nodejs-app artifact with a download link.

Pipeline failed at the test step?

Check that your index.test.js file was pushed to GitHub in Step 1. If it's missing, the npm test command has nothing to run.

Make sure package.json has "test": "node index.test.js" in the scripts section. If it says "echo \"Error: no test specified\" && exit 1" instead, the test command was not updated correctly.

Why is my Azure DevOps pipeline failing at the npm test step?

Your pipeline now builds, tests, and packages your app automatically. Next up, you'll customize the pipeline triggers so it only runs when it matters.

Customize Triggers and Verify CI

Your pipeline now builds, tests, and publishes artifacts automatically on every push. But not every push deserves a full build. Changes to documentation files like your README.md have nothing to do with code quality.

In this step, you'll add path filters to skip irrelevant builds. You'll also verify the full CI loop by pushing a code change and watching it trigger, then add a status badge so anyone visiting your repo knows the pipeline is healthy.

In this step, get ready to:
  • Add path filters to your pipeline trigger so documentation changes don't waste build minutes.
  • Push a code change and watch the pipeline trigger automatically.
  • Add a pipeline status badge to your GitHub repository.
Add branch filters to your trigger

Right now, your pipeline triggers on every push to main, regardless of what files changed. A paths filter tells the pipeline to ignore changes that only affect specific file types.

  • Open azure-pipelines.yml in your local azure-pipeline-demo repository folder.
  • Find the trigger section at the top of the file. It currently looks like this:
trigger:
  branches:
    include:
      - main
  • Replace the entire trigger section with the following updated version that adds a paths filter:
trigger:
  branches:
    include:
      - main
  paths:
    exclude:
      - "*.md"

What does this paths filter do?

The paths: exclude: block tells Azure Pipelines to skip a run when the ONLY files changed match the excluded patterns.

With "*.md" excluded, pushing changes to your README.md alone won't trigger a build. This saves your free-tier build minutes for real code changes.

  • Save azure-pipelines.yml.

✔️ Awesome, I've got everything!

Great. Double check you've saved your file before moving on.

ⓧ I'd like to double check the full code

trigger:
  branches:
    include:
      - main
  paths:
    exclude:
      - "*.md"

pool:
  vmImage: "ubuntu-latest"

steps:
  - task: UseNode@1
    inputs:
      version: "18.x"
    displayName: "Install Node.js"

  - script: |
      npm install
    displayName: "Install dependencies"

  - script: |
      npm run build
    displayName: "Build project"

  - script: |
      npm test
    displayName: "Run tests"

  - task: CopyFiles@2
    inputs:
      sourceFolder: "$(Build.SourcesDirectory)"
      contents: |
        index.js
        package.json
      targetFolder: "$(Build.ArtifactStagingDirectory)"
    displayName: "Copy project files"

  - task: PublishPipelineArtifact@1
    inputs:
      artifactName: "nodejs-app"
      targetPath: "$(Build.ArtifactStagingDirectory)"
    displayName: "Publish pipeline artifact"
Make a code change and watch CI run

The best way to prove your CI pipeline works is to push a real change and watch it trigger automatically.

  • Open index.js in your local azure-pipeline-demo folder.
  • Make a small change to the file. For example, on the last line, change "World" to a different name like "Pipeline".
  • Save index.js.
  • Commit and push all your changes (both azure-pipelines.yml and index.js) by running these commands:
git add .
git commit -m "Add path filter and update greeting"
git push
  • Switch back to Azure DevOps in your browser.
  • Select Pipelines from the left menu.
  • Watch for a new pipeline run to appear. It triggers automatically because you pushed a non-Markdown file change to main.
  • Click into the run and wait for all steps to complete with green checkmarks.

What should I see?

Your pipeline run should show all steps passing: Install Node.js, Install dependencies, Build project, Run tests, Copy project files, and Publish pipeline artifact. The run was triggered automatically by your git push without you clicking anything in Azure DevOps.

Pipeline didn't trigger?

Make sure you pushed to the main branch. If you're on a different branch, the trigger won't fire.

Check that your YAML indentation is correct. The paths block must be at the same indentation level as branches under trigger.

If you still see a parallelism error, your free tier request is still pending. You can wait for approval or continue to the next substep.

Help me troubleshoot why my pipeline didn't trigger after pushing to main.

Add a pipeline status badge

A status badge is a small image that shows whether your latest build passed or failed. Adding it to your README.md lets anyone visiting your repository see your pipeline health at a glance.

  • In Azure DevOps, select Pipelines from the left menu.
  • Select your pipeline from the list.
  • Click the three-dot menu (More Actions) in the top right corner of your pipeline page.
  • Select Status badge.
  • In the dialog that appears, make sure the Branch is set to main.
  • Click Copy to clipboard next to the Sample markdown section. This copies the Markdown snippet for your badge.

What does the badge Markdown look like?

The copied snippet is a Markdown image link that points to your pipeline's status API. It includes your organization name, project name, and pipeline ID. When rendered, it shows a green "passing" or red "failing" badge that updates automatically.

  • Open README.md in your local azure-pipeline-demo folder.
  • Replace all existing content with a heading and your copied badge. Your file should look similar to this:
# azure-pipeline-demo

[![Build Status](https://dev.azure.com/[[AZDO_ORG="your-organization-name"]]/PipelineDemo/_apis/build/status/[[PIPELINE_NAME="your-pipeline-name"]]?branchName=main)](https://dev.azure.com/[[AZDO_ORG="your-organization-name"]]/PipelineDemo/_build/latest?definitionId=[[PIPELINE_ID="your-pipeline-id"]]&branchName=main)

Use the copied snippet directly

You don't need to type the badge URL manually. Paste the exact Markdown you copied from Azure DevOps. It already contains your organization name, project, and pipeline ID filled in.

  • Save README.md.
  • Commit and push the badge update by running these commands:
git add .
git commit -m "Add pipeline status badge"
git push
  • Open your azure-pipeline-demo repository on github.com.
  • Scroll down to the README section on the repository's main page. You should see a green "Build passing" (or similar) badge displayed below the heading.

Why didn't this push trigger a pipeline run?

You only changed README.md, which matches the *.md exclusion pattern you just added. Your path filter is already working. The pipeline correctly skipped this documentation-only change.

Badge not showing on GitHub?

Make sure you pushed README.md to the main branch. GitHub only renders the README from the default branch on the repo's main page.

If you see a broken image icon, double check that the Markdown you pasted is the exact snippet from Azure DevOps with no extra spaces or line breaks.

Help me figure out why my pipeline status badge isn't showing on GitHub.

Secret mission

Add a Multi-Stage Deploy Pipeline

Your pipeline builds and tests your code. But in the real world, that's only half the story. Extend your CI pipeline into a full CI/CD pipeline with a separate Deploy stage that runs after your build succeeds.

Clean Up Your Resources

Clean Up Your Resources

This project uses Azure DevOps (free tier) and GitHub (free), so there are no ongoing costs. Decide whether to keep your resources running, pause them to come back later, or delete them entirely.

Resources you used:

  • Azure DevOps project (PipelineDemo) with CI/CD pipeline and dev environment.
  • GitHub repository (azure-pipeline-demo).
  • Local project files (azure-pipeline-demo folder on your Desktop).
  • Pipeline runs consume free minutes (1,800 minutes/month included in the free tier).

Keep everything running

No action needed. Choose this if you are still actively building on your pipeline or plan to revisit it soon.

  • Your Azure DevOps project and pipeline remain active for free.
  • The pipeline will run on each push to main, consuming your free 1,800 minutes/month.
  • Your GitHub repository and local files stay as they are.

Pause - I'll come back to this later

Disable the pipeline trigger so it stops running on every push. Your project and all history remain intact.

  • Open your azure-pipelines.yml file in your GitHub repository (or locally).
  • Change the trigger: section at the top of the file to:
trigger: none
  • Commit and push the change to main.
  • The pipeline will no longer trigger on new pushes.
  • To re-enable it later, restore the original trigger: block with your branch and path filters.

Delete - I don't want to use this again

Remove all project resources and start fresh. Follow each section below to fully clean up.

Delete the pipeline
  • In Azure DevOps, navigate to Pipelines from the left menu.
  • Select your pipeline to open its summary page.
  • Select the ... menu at the top-right of the page, then select Delete.
  • Type the name of the pipeline to confirm, then select Delete.
Delete the Azure DevOps project
  • Select Organization settings (gear icon in the bottom-left corner).
  • Select Projects in the left sidebar.
  • Find PipelineDemo and select it, then select Delete.
  • Enter the project name to confirm, then select Delete.
Delete the GitHub repository
  • On GitHub, navigate to your azure-pipeline-demo repository.
  • Click Settings (tab at the top of the repo page).
  • Scroll down to the Danger Zone section.
  • Click Delete this repository and follow the confirmation prompts to verify.
Delete local project files
  • Remove the local folder by running this command in your terminal:

macOS

rm -rf ~/Desktop/azure-pipeline-demo

Windows

Remove-Item -Recurse -Force "$env:USERPROFILE\Desktop\azure-pipeline-demo"

Nice Work!

Nice Work!

You just built a fully automated CI pipeline from scratch using Azure DevOps! Every time you push code to GitHub, your pipeline kicks in to build, test, and package your application without any manual intervention.

You've learned how to:

  • Set up Azure DevOps and connected it to a GitHub repository for automated pipeline triggers.
  • Written a YAML pipeline from scratch that builds, tests, and publishes pipeline artifacts on every push.
  • Configured branch filters and path exclusions to control when your pipeline runs, and added a status badge to your repository.
  • Extended the pipeline into a multi-stage CI/CD structure with separate Build and Deploy stages.

Ready to quiz yourself?