Set Up Azure DevOps Pipelines

Learn how to set up Azure DevOps pipelines step by step with this hands-on Azure tutorial for developers. Master the core concepts, walk through a practical exercise, and troubleshoot common issues.

Focus: set up azure devops pipelines

Sponsored

You've built the app, containerized it, and pushed it to a registry — but every time you deploy manually, something breaks. The pain is real: a forgotten environment variable, a wrong image tag, a build that works on your machine but fails in production. That's the gap Azure DevOps Pipelines fills: an automated, repeatable, and auditable path from code commit to cloud deploy. In this lesson, you'll learn how to set up Azure DevOps pipelines from scratch — define a YAML-based continuous integration (CI) and continuous delivery (CD) workflow, run it on Microsoft-hosted agents, and connect it to your Azure resources — so you can ship with confidence and stop babysitting deployments.

The Problem This Lesson Solves

Manual deployment is a ticking time bomb. When you deploy by hand, you accept several risks:

  • Human error: You forget to run migrations or set APP_ENV=production.
  • Inconsistency: The build you tested locally isn't the artifact you deploy.
  • No audit trail: If something breaks, you can't answer "what changed?"
  • Slow feedback: Bugs surface hours after commit, not minutes.

Azure DevOps Pipelines solves these by encoding your entire release process into a checked-in file — azure-pipelines.yml. Every push to your branch triggers a build, runs tests, packages the artifact, and deploys to Azure — automatically, every time, the same way.

The pain is especially acute in a team: without a pipeline, "it works on my machine" becomes a recurring nightmare. You need a single source of truth for how your app is built, tested, and shipped. That's precisely what this lesson gives you.

Core Concept / Mental Model

Think of Azure DevOps Pipelines as a conveyor belt in a factory. Raw materials (your code) enter on one end, and finished goods (deployed app) exit on the other. The belt is your pipeline, and each station is a stage. Within a stage, you have jobs (work units), and each job runs a series of steps (tasks) in order.

Here’s the vocabulary you need:

  • Pipeline: The entire YAML definition.
  • Trigger: What starts the pipeline — typically a branch push or a PR.
  • Agent: The machine where steps run. Azure DevOps provides Microsoft-hosted agents (pre-configured with common tools) or you can use self-hosted agents (your own VMs).
  • Stage: A major phase — e.g., Build, Test, Deploy.
  • Job: A set of steps that run on the same agent.
  • Step: A single action — run a script, publish an artifact, deploy to Azure.
  • Artifact: The packaged output of your build that gets handed to the release stage.

A simple mental model: Trigger → Agent → Stages → Jobs → Steps → Artifacts → Deploy. When you commit code, the pipeline picks up the change, runs your build and tests, produces a deployable artifact, and pushes it to your environment.

How It Works Step by Step

Setting up Azure DevOps Pipelines follows a predictable sequence. Here’s the cause-and-effect chain:

  1. Create an Azure DevOps organization and project — your pipeline lives inside a project that contains repos, pipelines, and release targets. Cause: you need a logical container for your automation.
  2. Connect your code repository — Azure DevOps can pull from its own azure-pipelines repo, GitHub, or Bitbucket. Cause: the pipeline needs a source of code to build.
  3. Define your pipeline with azure-pipelines.yml — this file declares triggers, agents, stages, and tasks. Cause: the pipeline is code, versioned alongside your app.
  4. Run the pipeline — Azure DevOps spins up an agent, runs your steps, and shows logs in real time. Cause: execution is observables, so you can debug issues.
  5. Publish artifacts — the build stage produces a zip or a container image that the release stage consumes. Cause: artifacts make deployments reproducible.
  6. Deploy to Azure — you add a deployment job that uses the Azure CLI, ARM templates, or Azure App Service task to push your artifact to a resource like an App Service or AKS. Cause: the app actually reaches your infrastructure.
  7. Monitor and iterate — logs, tests, and release gates give you feedback, and you tweak the YAML for future commits. Cause: continuous improvement.

Every step depends on the previous one — if your YAML has a syntax error, the pipeline fails at step 4, not at deployment.

Hands-On Walkthrough

Now, let’s set up Azurę DevOps pipelines for a small Python web app. We’ll assume you have an Azure DevOps organization (create one for free at dev.azure.com) and have a repo with a basic app.py and requirements.txt.

1. Create Your azure-pipelines.yml

Start with a minimal CI pipeline that runs tests and publishes an artifact:

# azure-pipelines.yml
trigger:
- main

pool:
  vmImage: 'ubuntu-latest'

steps:
- script: |
    python -m pip install --upgrade pip
    pip install -r requirements.txt
  displayName: 'Install dependencies'

- script: |
    python -m pytest
  displayName: 'Run tests'

- task: PublishBuildArtifacts@1
  inputs:
    PathtoPublish: '$(Build.SourcesDirectory)'
    ArtifactName: 'drop'

Replace pytest with your test runner if different. Push this file to your repo’s main branch.

2. Create the Pipeline in Azure DevOps

  • In your Azure DevOps project, go to Pipelines → New Pipeline.
  • Choose your repository (Azure Repos, GitHub, etc.).
  • Select Existing Azure Pipelines YAML file and point to azure-pipelines.yml.
  • Click Run — this creates a pipeline that triggers on every push to main.

3. Add a Deployment Stage

To actually deploy, extend the YAML. Here’s a multi-stage pipeline that builds and deploys to an Azure App Service:

# azure-pipelines.yml
trigger:
- main

variables:
  azureServiceConnectionId: 'your-service-connection'  # Create this in Project Settings
  appName: 'my-python-app'

stages:
- stage: Build
  jobs:
  - job: BuildJob
    pool:
      vmImage: 'ubuntu-latest'
    steps:
    - script: |
        python -m pip install --upgrade pip
        pip install -r requirements.txt
      displayName: 'Install dependencies'
    - script: |
        python -m pytest
      displayName: 'Run tests'
    - task: ArchiveFiles@2
      inputs:
        rootFolderOrFile: '$(Build.SourcesDirectory)'
        includeRootFolder: false
        archiveType: 'zip'
        archiveFile: '$(Build.ArtifactStagingDirectory)/$(appName).zip'
    - task: PublishBuildArtifacts@1
      inputs:
        PathtoPublish: '$(Build.ArtifactStagingDirectory)'
        ArtifactName: 'drop'

- stage: Deploy
  dependsOn: Build
  jobs:
  - deployment: DeployJob
    pool:
      vmImage: 'ubuntu-latest'
    environment: 'production'
    strategy:
      runOnce:
        deploy:
          steps:
          - task: AzureWebApp@1
            inputs:
              azureSubscription: '$(azureServiceConnectionId)'
              appName: '$(appName)'
              package: '$(Pipeline.Workspace)/drop/*.zip'

You’ll need a Service Connection to authenticate: go to Project Settings → Service connections → New service connection → Azure Resource Manager and select your subscription.

4. Run and Observe

Commit a change to main. The pipeline will start automatically. In the Azure DevOps UI, you can watch each stage’s logs, see test results, and inspect the published artifact. When the deployment finishes, your app is live on Azure.

Pro tip: Use ci triggers for PRs. Add pr: - main to run the pipeline on pull requests — it catches issues before merging.

Compare Options / When to Choose What

When you set up Azure DevOps pipelines, you have choices for how to define and run them. Here’s a quick comparison:

Aspect YAML Pipelines (recommended) Classic Release Pipelines
Definition Infrastructure as code, versioned in repo GUI-based, stored in Azure DevOps
Reusability Templates and variables via YAML Limited to tasks and environments
Audit trail Full Git history of pipeline changes Only metadata, no code review
Best for New projects, teams that love Git Legacy setups, quick ad-hoc releases
Skill to learn YAML, basic Drag-and-drop

For almost all modern scenarios, YAML pipelines beat classic releases because they bring the same benefits as infrastructure-as-code: versioning, reviewability, and testability. Use classic release pipelines only if you have a legacy system that’s already built on it and you don’t want to migrate.

Another comparison: Microsoft-hosted agents vs self-hosted.

  • Microsoft-hosted agents: quick to start, pre-installed tools, no maintenance — but limited to available VM images.
  • Self-hosted agents: full control over OS, cached dependencies, faster builds — but you manage the VM and its updates.

Choose Microsoft-hosted for simplicity; choose self-hosted if you need proprietary libraries or want to reuse a warm build cache.

Troubleshooting & Edge Cases

Here are the most common failures when you set up Azure DevOps pipelines, and how to fix them.

Error: "No hosted parallelism has been purchased or granted"

Cause: Free-tier accounts may need to request parallelism. Fix: Go to Azure DevOps portal → Organization settings → Billing → Parallel jobs → clear the request or purchase a paid plan. It’s a known stumbling block.

Error: "The service connection does not exist or has not been authorized"

Cause: You referenced a service connection name that isn’t valid. Fix: In Project Settings, confirm the exact name, and check you have permissions to use it. Use a variable for the connection ID.

Tests pass locally but fail in pipeline

Cause: Different Python version or missing environment variables. Fix: Pin your Python version in the pipeline (e.g., python: 3.11), and define variables for secrets as pipeline variables or a variable group.

Deployment says "app is up" but health check fails

Cause: Your app needs a startup command, or PORT isn’t set. For Azure App Service, set Configuration → General settings → Startup Command to python -m app or similar. For containers, define EXPOSE and PORT correctly.

Artifacts not found in deploy stage

Cause: The publish step didn’t place artifacts where you think. Fix: Use $(Build.ArtifactStagingDirectory) consistently and download in the deploy stage with DownloadBuildArtifacts@1 if needed.

What You Learned & What's Next

In this lesson, you learned how to set up Azure DevOps pipelines from scratch. You now understand the core components — triggers, agents, stages, jobs, steps, and artifacts — and you completed a hands-on exercise where you defined a YAML pipeline that runs tests, publishes artifacts, and deploys to Azure. You compared YAML vs classic releases and troubleshooted common errors like service connection issues and parallelism limits. These skills let you automate delivery for any Azure-backed app.

Your learning doesn’t stop here. The next step in this Azure track is Deploying containers to Azure Kubernetes Service (AKS) — where you’ll take the pipeline you just built and extend it to push container images and roll out releases with zero downtime. You’ll apply the same pipeline principles but with docker build and kubectl steps. You’re building toward a full DevOps chain, and pipelines are the glue.

Practice recap

Take the YAML pipeline you created and add a pr trigger so it also runs on pull requests. Then, create a variable group named dev-variables with a dummy environment variable, and reference it in a new step that prints the value. Commit to main and watch the pipeline run — verify that the PR trigger works by opening a test pull request. This will solidify your understanding of triggers and variables before moving on to container deployments.

Common mistakes

  • Forgetting to pin the Python version — the pipeline uses whatever is on the hosted agent (e.g., 3.12) while you test on 3.11, leading to subtle behavior differences. Fix: set - task: UsePythonVersion@0 with versionSpec: '3.11'.
  • Hard-coding secrets in YAML — anyone with access to the repo sees plaintext passwords. Use Azure DevOps variable groups or Key Vault references instead.
  • Not triggering on pull requests — you catch bugs only after merge. Add a pr: trigger so the pipeline runs on every PR and blocks bad merges.
  • Publishing the entire source as an artifact instead of a build output — this bloats the deployment and may expose files you don’t want. Use ArchiveFiles on a targeted folder like dist/.
  • Missing a service connection name with spaces — Azure DevOps treats it as case-sensitive, and a typo causes immediate failure. Store the connection ID in a variable.

Variations

  1. Use classic release pipelines with a GUI editor if your team prefers a visual interface, but it lacks code reviewability.
  2. Use self-hosted agents on an Azure VM to speed up builds with cached dependencies and control over the environment.
  3. Use templates and extends syntax in YAML to reuse pipeline snippets across multiple projects — great for consistency.

Real-world use cases

  • Automate CI/CD for a Python web app on Azure App Service, so every commit to main deploys a tested version to production.
  • Build and push a container image to Azure Container Registry (ACR) in a pipeline, then use a separate release job to roll out to AKS.
  • Run a scheduled pipeline for nightly database backups using a PowerShell step that invokes Azure CLI commands, ensuring backups are audited.

Key takeaways

  • Azure DevOps Pipelines turn your release process into versionable code (azure-pipelines.yml), delivering consistency and auditability.
  • A pipeline is structured as stages → jobs → steps, running on agents; artifacts are the handoff from build to deployment.
  • YAML pipelines are superior to classic releases for modern teams — they’re reviewable, testable, and reusable via templates.
  • Microsoft-hosted agents are the fastest way to start; self-hosted agents give control and caching but add operational overhead.
  • Configure triggers on both pushes and PRs to catch issues early, and always pin dependency and runtime versions for reproducibility.
  • Service connections and variable groups are essential for secure, maintainable authentication and secrets management.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.