Top Azure DevOps Interview Questions and Answers for 2026(30+ questions)

Top Azure DevOps Interview Questions and Answers for 2026(30+ questions)

As organizations continue to embrace DevOps practices to accelerate software delivery and improve collaboration, Azure DevOps has emerged as a leading platform supporting these goals. Whether you are a developer, tester, project manager, or DevOps engineer, understanding Azure DevOps is essential for many technical roles today. This article covers the most important Azure DevOps interview questions and answers for 2026, helping you prepare effectively for your next job interview.

Table of Contents

Understanding Azure DevOps: An Overview

Azure DevOps is a comprehensive suite of development tools provided by Microsoft that supports the entire software development lifecycle. It enables teams to plan, develop, test, deliver, and maintain software efficiently. The platform offers integrated services for source control, continuous integration and continuous deployment (CI/CD), agile project management, artifact management, and testing.

One of the key strengths of Azure DevOps is its flexibility and extensibility. It integrates seamlessly with Git, the popular open-source distributed version control system, and also supports Team Foundation Version Control (TFVC), a centralized version control system. Additionally, Azure DevOps has a vast marketplace of extensions, allowing teams to customize their workflows and tools to suit specific DevOps lifecycle requirements. This adaptability is particularly beneficial in today’s fast-paced development environment, where teams must respond quickly to changing requirements and technologies.

Moreover, Azure DevOps fosters a culture of collaboration and transparency within teams. With features like pull requests, code reviews, and built-in dashboards, team members can easily share insights and feedback, leading to better code quality and more efficient problem-solving. The platform also supports integration with popular communication tools like Microsoft Teams and Slack, further enhancing collaboration across teams, regardless of their geographical locations.

Why Azure DevOps is Popular in 2026

In the evolving DevOps landscape, Azure DevOps stands out due to its end-to-end capabilities and ease of integration with other tools. Organizations benefit from its cloud-based infrastructure, which supports collaboration across distributed teams and automates many manual processes. The platform’s support for agile methodologies and its rich set of features make it a preferred choice for enterprises aiming to improve software quality and speed up delivery cycles. Additionally, the robust analytics and reporting capabilities of Azure DevOps allow teams to gain insights into their development processes, helping them make data-driven decisions that enhance productivity and efficiency.

As businesses increasingly adopt cloud-native architectures and microservices, Azure DevOps provides the necessary tools to facilitate these modern development practices. Its support for containerization technologies such as Docker and orchestration platforms like Kubernetes enables teams to build, deploy, and manage applications in a scalable and efficient manner. This adaptability to new technologies is crucial for organizations looking to stay competitive in an ever-evolving market landscape.

Core Services Offered by Azure DevOps

Azure DevOps provides several core services that cover different aspects of the software development lifecycle:

  • Azure Repos: Provides Git repositories or TFVC for source control and versioning.
  • Azure Pipelines: Enables CI/CD pipelines to automate building, testing, and deploying applications.
  • Azure Boards: Supports agile project management with work items, backlogs, sprints, and dashboards.
  • Azure Artifacts: Manages packages and dependencies used in development.
  • Azure Test Plans: Offers tools for manual and automated testing to ensure software quality.

Each of these services is designed to work seamlessly together, providing a cohesive experience for development teams. For instance, Azure Pipelines can be directly linked to Azure Repos, allowing for automatic triggering of builds and deployments whenever changes are pushed to the repository. This integration not only streamlines the development process but also minimizes the risk of errors that can occur when managing multiple tools separately. Furthermore, Azure Boards enhances visibility into project progress, enabling teams to track their work effectively and adapt to changes in real time.

Common Azure DevOps Interview Questions and Detailed Answers

Now that we’ve covered the fundamental components of Azure DevOps and why it’s essential in 2026, let’s dive into the specific questions you’re likely to encounter in interviews. The following questions range from foundational concepts to practical applications, helping you demonstrate both theoretical knowledge and hands-on experience.

1. What is Azure DevOps and what are its main components?

Azure DevOps is a cloud-based platform by Microsoft that provides a suite of services to support the entire software development lifecycle. Its main components include Azure Repos for source control, Azure Pipelines for CI/CD, Azure Boards for project tracking, Azure Artifacts for package management, and Azure Test Plans for testing.

Section Image

This integrated approach allows teams to collaborate efficiently, automate workflows, and deliver high-quality software faster.

2. How does Azure DevOps support version control?

Azure DevOps supports two types of version control systems: Git and Team Foundation Version Control (TFVC). Git is a distributed version control system widely used in the industry, allowing multiple developers to work on code simultaneously with local repositories. TFVC is a centralized version control system where developers check in code to a central server.

Using Azure Repos, teams can manage and track code changes effectively, enabling collaboration and maintaining a history of modifications for auditing and rollback purposes.

3. Can you explain the concept of CI/CD in Azure DevOps?

Continuous Integration (CI) and Continuous Deployment (CD) are key DevOps practices that Azure DevOps facilitates through Azure Pipelines. CI involves automatically building and testing code changes as they are committed to the repository, ensuring that new code integrates well with the existing codebase.

CD extends this by automating the deployment of validated code to production or staging environments. Azure Pipelines supports multiple languages and platforms, enabling teams to create robust workflows that reduce manual errors and accelerate delivery.

4. What are Azure Boards and how do they help in project management?

Azure Boards is a service within Azure DevOps that supports agile project management. It provides tools like work items, backlogs, sprint planning boards, and dashboards to track tasks, bugs, features, and user stories.

By using Azure Boards, teams can visualize their progress, prioritize work, and maintain transparency, which is crucial for iterative development and continuous improvement.

5. How does Azure DevOps integrate with Git and other tools?

Azure DevOps has native integration with Git, allowing users to create repositories, manage branches, and perform pull requests directly within the platform. Its extensible architecture supports integration with a wide range of third-party tools and services through a large marketplace of extensions.

This flexibility enables teams to customize their DevOps lifecycle, incorporating tools for code quality, security scanning, containerization, and more.

Advanced Azure DevOps Interview Questions

These foundational questions establish your understanding of Azure DevOps basics. However, interviewers often probe deeper to assess your practical experience and problem-solving abilities. The following advanced questions will help you demonstrate expertise in complex scenarios and architectural decisions.

6. What is the difference between Git and TFVC in Azure DevOps?

Git is a distributed version control system where each developer has a full copy of the repository, enabling offline work and multiple workflows like branching and merging. TFVC is centralized, with a single server repository where developers check in changes.

Git is generally preferred for its flexibility and support for modern development workflows, while TFVC may be used in scenarios requiring centralized control.

Feature Git (Distributed) TFVC (Centralized)
Repository Model Each developer has full repository copy Single server-side repository
Offline Work Full functionality offline Limited offline capabilities
Branching Lightweight, encourages feature branches Heavier, path-based branching
Merging Advanced merge algorithms More complex merge process
Performance Fast local operations Network-dependent operations
Workflow Flexibility Multiple workflows (Gitflow, trunk-based) Linear workflow
File Locking Not natively supported Built-in file locking
History Complete local history Server-based history
Learning Curve Steeper initial learning Easier for beginners
Large Files Requires Git LFS Handles large files natively
Best For Modern distributed teams, microservices Legacy systems, strict centralized control

7. How do you implement branching strategies in Azure DevOps?

Branching strategies in Azure DevOps depend on the team’s workflow and project requirements. Common strategies include:

  • Feature branching: Developers create branches for new features and merge them back after completion.
  • Gitflow: Uses dedicated branches for features, releases, and hotfixes to manage releases systematically.
  • Mainline development: Focuses on a single main branch with short-lived feature branches.

Azure Repos supports all these strategies, and pull requests facilitate code reviews before merging.

8. What are Azure Artifacts and how do they benefit DevOps teams?

Azure Artifacts is a service that manages packages and dependencies used in software development. It supports multiple package types such as NuGet, npm, Maven, and Python.

By centralizing package management, Azure Artifacts helps teams share libraries securely, control versions, and reduce build times by caching dependencies.

9. How do you ensure quality and testing in Azure DevOps?

Azure DevOps provides Azure Test Plans, which includes tools for manual testing, exploratory testing, and automated test execution. Test cases can be linked to requirements and bugs, ensuring traceability.

Additionally, Azure Pipelines can integrate automated testing frameworks into CI/CD workflows, enabling continuous quality checks and faster feedback loops.

10. How do you manage secrets and sensitive data in Azure Pipelines?

Azure DevOps provides multiple approaches for managing secrets:

Variable Groups with Secret Variables: Store sensitive data as secret variables in Variable Groups, which are encrypted at rest and masked in logs. These can be linked to Azure Key Vault for centralized secret management.

Azure Key Vault Integration: The recommended approach is integrating Azure Pipelines with Azure Key Vault. Create a service connection to Key Vault, then reference secrets directly in your pipeline:

- task: AzureKeyVault@2
inputs:
azureSubscription: 'MyServiceConnection'
KeyVaultName: 'mykeyvault'
SecretsFilter: '*'
RunAsPreJob: true

Best Practices: Never hardcode secrets in YAML files or source code, use secret variables for pipeline-specific secrets, rotate secrets regularly, and limit access using Azure RBAC.

11. What are Service Connections and how do you secure them?

Service Connections are secure endpoints that allow Azure Pipelines to connect to external services like Azure subscriptions, Docker registries, Kubernetes clusters, or other cloud providers.

Security Best Practices:

  • Use Workload Identity Federation instead of secrets where possible
  • Apply least-privilege principles with specific resource group or resource-level permissions
  • Enable “Approve for pipeline use” to prevent unauthorized pipeline access
  • Regularly audit service connection usage and permissions
  • Use separate service connections for different environments (dev, staging, production)

Service connections should be managed at the project level and protected using pipeline permissions and checks.

Security & Secrets Management

10. How do you manage secrets and sensitive data in Azure Pipelines?

Azure DevOps provides multiple approaches for managing secrets:

Variable Groups with Secret Variables: Store sensitive data as secret variables in Variable Groups, which are encrypted at rest and masked in logs. These can be linked to Azure Key Vault for centralized secret management.

Azure Key Vault Integration: The recommended approach is integrating Azure Pipelines with Azure Key Vault. Create a service connection to Key Vault, then reference secrets directly in your pipeline:

- task: AzureKeyVault@2
  inputs:
    azureSubscription: 'MyServiceConnection'
    KeyVaultName: 'mykeyvault'
    SecretsFilter: '*'
    RunAsPreJob: true

Best Practices: Never hardcode secrets in YAML files or source code, use secret variables for pipeline-specific secrets, rotate secrets regularly, and limit access using Azure RBAC.


11. What are Service Connections and how do you secure them?

Service Connections are secure endpoints that allow Azure Pipelines to connect to external services like Azure subscriptions, Docker registries, Kubernetes clusters, or other cloud providers.

Security Best Practices:

  • Use Workload Identity Federation instead of secrets where possible
  • Apply least-privilege principles with specific resource group or resource-level permissions
  • Enable “Approve for pipeline use” to prevent unauthorized pipeline access
  • Regularly audit service connection usage and permissions
  • Use separate service connections for different environments (dev, staging, production)

Service connections should be managed at the project level and protected using pipeline permissions and checks.


Containers & Kubernetes

12. How do you build and deploy Docker containers using Azure Pipelines?

Azure Pipelines provides native support for containerized applications through built-in tasks:

Building Docker Images:

- task: Docker@2
  displayName: 'Build Docker Image'
  inputs:
    command: build
    repository: 'myapp'
    dockerfile: '$(Build.SourcesDirectory)/Dockerfile'
    tags: |
      $(Build.BuildId)
      latest

Pushing to Container Registry:

- task: Docker@2
  displayName: 'Push to ACR'
  inputs:
    command: push
    repository: 'myapp'
    containerRegistry: 'myACRServiceConnection'
    tags: |
      $(Build.BuildId)
      latest

The pipeline can integrate with Azure Container Registry (ACR), Docker Hub, or other registries through service connections. Multi-stage builds optimize image size and security.


13. Explain how to deploy applications to Azure Kubernetes Service (AKS) using Azure DevOps.

Deploying to AKS involves several steps in Azure Pipelines:

1. Build and Push Container: Build Docker image and push to container registry 2. Update Kubernetes Manifests: Update deployment YAML with new image tag 3. Deploy to AKS: Use Kubernetes tasks to apply manifests

- task: Kubernetes@1
  displayName: 'Deploy to AKS'
  inputs:
    connectionType: 'Azure Resource Manager'
    azureSubscriptionEndpoint: 'MyAzureConnection'
    azureResourceGroup: 'myResourceGroup'
    kubernetesCluster: 'myAKSCluster'
    command: 'apply'
    arguments: '-f $(Build.SourcesDirectory)/k8s/'

Advanced Approach: Use Helm charts for templated deployments:

- task: HelmDeploy@0
  inputs:
    connectionType: 'Azure Resource Manager'
    azureSubscription: 'MyAzureConnection'
    azureResourceGroup: 'myResourceGroup'
    kubernetesCluster: 'myAKSCluster'
    command: 'upgrade'
    chartType: 'FilePath'
    chartPath: '$(Build.SourcesDirectory)/helm/myapp'
    releaseName: 'myapp'
    overrideValues: 'image.tag=$(Build.BuildId)'

For production, implement deployment strategies like blue-green or canary deployments using AKS features or service meshes.


YAML Pipelines & Multi-Stage

14. What is the difference between stages, jobs, and steps in Azure Pipelines?

Azure Pipelines has a hierarchical structure:

Stages: Logical boundaries in your pipeline representing phases like Build, Test, Deploy-Dev, Deploy-Prod. Stages run sequentially by default but can run in parallel. Each stage can have dependencies and conditions.

Jobs: Units of work that run on an agent. Multiple jobs within a stage run in parallel by default. Jobs can run on different agent pools or platforms (Windows, Linux, macOS).

Steps: Individual tasks within a job that run sequentially. These are the actual commands or tasks that perform work (build, test, deploy).

Example Structure:

stages:
- stage: Build
  jobs:
  - job: BuildJob
    steps:
    - script: echo "Building application"
    - task: DotNetCoreCLI@2

- stage: Deploy
  dependsOn: Build
  jobs:
  - job: DeployJob
    steps:
    - task: AzureWebApp@1

This hierarchy enables complex workflows with proper separation of concerns and parallel execution where appropriate.


15. How do you implement manual approvals and gates in Azure Pipelines?

Azure Pipelines supports approvals and checks at the environment level for deployment control:

Environments: Create environments in Azure DevOps (e.g., Production, Staging) Approvals: Configure approvals on environments requiring human validation before deployment Checks: Automated validations like Azure Function checks, REST API calls, or Azure Monitor queries

Pipeline Configuration:

stages:
- stage: DeployProduction
  jobs:
  - deployment: DeployWeb
    environment: 'Production'  # This environment has approvals configured
    strategy:
      runOnce:
        deploy:
          steps:
          - task: AzureWebApp@1

In the UI: Navigate to Environments → Select Environment → Approvals and checks → Add approval with specific users or groups.

Benefits: Ensures compliance, prevents accidental production deployments, and creates an audit trail of who approved what deployment.


16. Explain YAML pipeline templates and how they promote reusability.

YAML templates allow you to define reusable pipeline logic that can be shared across multiple pipelines:

Template Types:

  • Stage templates: Reusable stages
  • Job templates: Reusable jobs
  • Step templates: Reusable steps
  • Variable templates: Shared variables

Example Step Template (templates/build-steps.yml):

parameters:
- name: buildConfiguration
  type: string
  default: 'Release'

steps:
- task: DotNetCoreCLI@2
  inputs:
    command: 'restore'
- task: DotNetCoreCLI@2
  inputs:
    command: 'build'
    arguments: '--configuration ${{ parameters.buildConfiguration }}'

Using the Template:

stages:
- stage: Build
  jobs:
  - job: BuildJob
    steps:
    - template: templates/build-steps.yml
      parameters:
        buildConfiguration: 'Release'

Benefits: Reduces code duplication, ensures consistency across pipelines, simplifies maintenance, and enables organization-wide standards.


Infrastructure as Code

17. How does Azure DevOps support Infrastructure as Code (IaC)?

Azure DevOps integrates with multiple IaC tools for infrastructure automation:

ARM Templates: Native Azure support using Azure Resource Group Deployment tasks:

- task: AzureResourceManagerTemplateDeployment@3
  inputs:
    deploymentScope: 'Resource Group'
    azureResourceManagerConnection: 'MyServiceConnection'
    resourceGroupName: 'myResourceGroup'
    location: 'East US'
    templateLocation: 'Linked artifact'
    cstrTemplateFilePath: '$(Build.SourcesDirectory)/infrastructure/template.json'
    cstrParametersFilePath: '$(Build.SourcesDirectory)/infrastructure/parameters.json'

Terraform: Using the Terraform task from marketplace:

- task: TerraformTaskV3@3
  inputs:
    provider: 'azurerm'
    command: 'init'
    backendServiceArm: 'MyServiceConnection'
    
- task: TerraformTaskV3@3
  inputs:
    provider: 'azurerm'
    command: 'apply'
    environmentServiceNameAzureRM: 'MyServiceConnection'

Bicep: Microsoft’s DSL for Azure resources, compiled to ARM templates Pulumi: Code-based infrastructure using familiar programming languages

IaC in pipelines enables version control, peer review, automated testing, and consistent deployments across environments.


Monitoring & Troubleshooting

18. How do you troubleshoot failed pipeline runs in Azure DevOps?

Systematic troubleshooting approach:

1. Check Pipeline Logs: Review detailed logs for each step, looking for error messages and exit codes 2. Enable System Diagnostics: Add variable system.debug = true for verbose logging 3. Review Pipeline Variables: Verify all required variables are defined and accessible 4. Check Service Connections: Ensure service connections have valid credentials and permissions 5. Agent Availability: Verify agents are online and have capacity 6. Dependency Issues: Check if dependencies (packages, tools) are accessible

Common Issues:

  • Authentication failures: Expired service principals or permissions issues
  • Agent timeout: Increase job timeout or optimize build steps
  • Variable resolution: Secret variables not available in certain contexts
  • Artifact publishing: Path issues or storage capacity

Debugging Techniques:

- script: |
    echo "Debug: Build.SourcesDirectory = $(Build.SourcesDirectory)"
    echo "Debug: Build.ArtifactStagingDirectory = $(Build.ArtifactStagingDirectory)"
    ls -la $(Build.SourcesDirectory)
  displayName: 'Debug filesystem'

19. What are pipeline analytics and how do they help improve DevOps processes?

Azure DevOps provides built-in analytics to measure and improve pipeline performance:

Key Metrics:

  • Pass rate: Percentage of successful runs
  • Duration: Average and trend of pipeline execution time
  • Test pass rate: Quality metrics from automated tests
  • Deployment frequency: How often code reaches production
  • Lead time: Time from commit to production

Analytics Reports Available:

  • Pipeline duration report (identifies bottlenecks)
  • Pipeline pass rate report (quality trends)
  • Test analytics (flaky tests, failure patterns)
  • Deployment analytics (success rates by environment)

Using Insights: Navigate to Pipelines → Analytics to view reports and identify:

  • Slow stages that need optimization
  • Frequently failing tests requiring attention
  • Agents with performance issues
  • Deployment success patterns

These metrics support continuous improvement and data-driven decisions about DevOps process optimization.


Advanced Git & Branching

20. How do you handle merge conflicts in Azure Repos?

Merge conflicts occur when concurrent changes affect the same code lines:

Prevention Strategies:

  • Keep branches short-lived (merge frequently)
  • Pull latest changes before starting new work
  • Use clear branching strategies with defined ownership
  • Implement code ownership (CODEOWNERS file)

Resolution Process:

  1. Pull latest changes: git pull origin main
  2. Identify conflicts: Git marks conflicts in files with <<<<<<<, =======, >>>>>>>
  3. Resolve conflicts: Edit files to choose correct version or merge both changes
  4. Test thoroughly: Run builds and tests after resolution
  5. Commit resolution: git add . then git commit

In Azure DevOps PR:

  • Conflicts shown in PR interface
  • Can resolve simple conflicts directly in browser
  • Complex conflicts require local resolution

Best Practices: Communicate with team members when resolving conflicts, understand both sets of changes, and never just accept “ours” or “theirs” without review.


21. Explain Branch Policies in Azure Repos and their importance.

Branch policies enforce quality standards and govern how code enters protected branches:

Common Policy Types:

Require Pull Requests: Direct pushes to main/master are blocked; all changes must go through PR review

Minimum Number of Reviewers: Enforce peer review (e.g., require 2 approvers)

Check for Linked Work Items: Ensure traceability by requiring work item association

Build Validation: Require successful build before PR completion

# Build validation policy triggers this pipeline
trigger: none # Explicit PR trigger only

pr:
  branches:
    include:
    - main

Status Checks: Require external service checks to pass (security scans, code quality)

Comment Resolution: All PR comments must be resolved before merge

Configuration: Repository Settings → Policies → Branch Policies → Select branch

Benefits:

  • Prevents broken code from reaching main branch
  • Ensures code review and knowledge sharing
  • Maintains audit trail
  • Enforces compliance requirements
  • Improves code quality through automated checks

Performance & Optimization

22. How do you optimize Azure Pipeline execution time?

Multiple strategies can reduce pipeline duration:

1. Parallel Jobs: Run independent jobs simultaneously

jobs:
- job: TestWindows
  pool:
    vmImage: 'windows-latest'
- job: TestLinux
  pool:
    vmImage: 'ubuntu-latest'

2. Caching Dependencies: Cache package downloads between runs

- task: Cache@2
  inputs:
    key: 'npm | "$(Agent.OS)" | package-lock.json'
    path: $(npm_config_cache)
    restoreKeys: |
      npm | "$(Agent.OS)"

3. Incremental Builds: Build only changed components

4. Matrix Strategy: Test multiple configurations efficiently

strategy:
  matrix:
    Python38:
      python.version: '3.8'
    Python39:
      python.version: '3.9'
    Python310:
      python.version: '3.10'

5. Self-Hosted Agents: Use dedicated agents with pre-installed tools and better performance

6. Conditional Execution: Skip unnecessary steps

- script: echo "Run only on main"
  condition: eq(variables['Build.SourceBranch'], 'refs/heads/main')

7. Artifact Optimization: Minimize artifact size and use artifact caching

Measurement: Use Pipeline Analytics to identify bottlenecks and measure improvement impact.


Permissions & Access Control

23. Explain the permission model in Azure DevOps.

Azure DevOps uses a hierarchical permission model with multiple levels:

Organization Level:

  • Create projects
  • Manage billing
  • Install extensions
  • Manage policies

Project Level:

  • Create repositories
  • Manage pipelines
  • Edit project information
  • Manage teams

Repository Level:

  • Contribute (push code)
  • Create branches
  • Manage permissions
  • Bypass policies

Pipeline Level:

  • Queue builds
  • Edit pipeline
  • Manage pipeline
  • View build

Security Groups:

  • Readers: View-only access
  • Contributors: Read and contribute
  • Build Administrators: Manage pipelines
  • Project Administrators: Full project control

Best Practices:

  • Apply least-privilege principle
  • Use groups instead of individual permissions
  • Regularly audit access
  • Separate production pipeline permissions
  • Use service connections for automation (not personal accounts)
  • Enable conditional access policies for sensitive projects

Configuration: Project Settings → Permissions → Select security group → Set permissions


Real-World Scenarios

24. Design a CI/CD pipeline for a microservices application with multiple services.

Architecture: A microservices application typically has 5-10+ services requiring coordinated deployment:

Pipeline Strategy:

1. Repository Structure: Mono-repo or multi-repo approach

  • Mono-repo: Single repository with all services, using path filters
  • Multi-repo: Separate repositories per service with orchestration pipeline

2. Build Pipeline (per service):

trigger:
  branches:
    include:
    - main
  paths:
    include:
    - services/user-service/*

stages:
- stage: Build
  jobs:
  - job: BuildUserService
    steps:
    - task: Docker@2
      inputs:
        command: build
        repository: 'myapp/user-service'
        dockerfile: 'services/user-service/Dockerfile'
        tags: $(Build.BuildId)
    
    - task: Docker@2
      inputs:
        command: push
        repository: 'myapp/user-service'
        containerRegistry: 'myACR'

3. Integration Testing: Test service interactions

4. Deployment Pipeline:

- stage: DeployDev
  jobs:
  - deployment: DeployServices
    environment: Development
    strategy:
      runOnce:
        deploy:
          steps:
          - task: HelmDeploy@0
            inputs:
              command: upgrade
              chartPath: './helm/user-service'
              releaseName: 'user-service'
              
- stage: DeployProd
  dependsOn: DeployDev
  condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
  jobs:
  - deployment: DeployProduction
    environment: Production  # With manual approval

Considerations:

  • Service versioning and compatibility
  • Database migration coordination
  • Feature flags for gradual rollout
  • Monitoring and alerting integration
  • Rollback strategy per service
  • API gateway configuration updates

25. How would you implement blue-green deployment using Azure DevOps?

Blue-green deployment maintains two identical production environments for zero-downtime releases:

Azure App Service Approach:

1. Setup: Create deployment slots (Blue = production, Green = staging)

2. Pipeline Configuration:

stages:
- stage: DeployToGreen
  jobs:
  - job: DeployGreenSlot
    steps:
    - task: AzureWebApp@1
      inputs:
        azureSubscription: 'MyServiceConnection'
        appName: 'myapp'
        deployToSlotOrASE: true
        resourceGroupName: 'myResourceGroup'
        slotName: 'staging'  # Green environment
        package: '$(Pipeline.Workspace)/**/*.zip'
    
    - task: AzureAppServiceManage@0
      displayName: 'Run smoke tests on Green'
      inputs:
        azureSubscription: 'MyServiceConnection'
        action: 'Start Azure App Service'
        
- stage: SwapSlots
  dependsOn: DeployToGreen
  jobs:
  - job: SwapToProduction
    steps:
    - task: AzureAppServiceManage@0
      inputs:
        azureSubscription: 'MyServiceConnection'
        action: 'Swap Slots'
        webAppName: 'myapp'
        resourceGroupName: 'myResourceGroup'
        sourceSlot: 'staging'  # Swap Green to Blue

Kubernetes/AKS Approach:

  • Use service selectors to switch between blue and green deployments
  • Implement with Helm or Kubernetes manifests
  • Update service to point to new deployment

Benefits: Instant rollback (swap back), testing in production-like environment, zero downtime Challenges: Database migrations, increased resource costs, session management


26. Describe how you would set up a complete DevOps workflow for a team transitioning from manual deployments.

Phase 1: Foundation (Weeks 1-2)

Version Control:

  • Migrate code to Azure Repos (Git)
  • Establish branching strategy (e.g., Gitflow or trunk-based)
  • Configure branch policies (require PR, minimum reviewers)
  • Train team on Git workflows

Project Setup:

  • Create Azure DevOps project
  • Set up teams and areas in Azure Boards
  • Configure work item types (User Stories, Tasks, Bugs)
  • Link repos to work items for traceability

Phase 2: Continuous Integration (Weeks 3-4)

Build Pipeline:

trigger:
- main
- develop

pool:
  vmImage: 'ubuntu-latest'

steps:
- task: UseDotNet@2
  inputs:
    version: '8.x'

- script: dotnet restore
- script: dotnet build --configuration Release

- task: DotNetCoreCLI@2
  inputs:
    command: test
    projects: '**/*Tests.csproj'
    arguments: '--configuration Release --logger trx'

- task: PublishTestResults@2
  inputs:
    testResultsFormat: 'VSTest'
    testResultsFiles: '**/*.trx'

Quality Gates:

  • Automated unit tests
  • Code coverage requirements
  • Static code analysis (SonarQube extension)
  • Build status badges in README

Phase 3: Continuous Deployment (Weeks 5-6)

Environment Setup:

  • Create Dev, Staging, Production environments
  • Configure approvals for Staging and Production
  • Set up service connections to Azure/cloud resources

Release Pipeline:

stages:
- stage: Dev
  jobs:
  - deployment: DeployDev
    environment: Development
    
- stage: Staging
  dependsOn: Dev
  jobs:
  - deployment: DeployStaging
    environment: Staging  # Requires approval
    
- stage: Production
  dependsOn: Staging
  jobs:
  - deployment: DeployProduction
    environment: Production  # Requires approval

Phase 4: Monitoring & Improvement (Weeks 7-8)

Observability:

  • Integrate Application Insights
  • Set up dashboard in Azure DevOps
  • Configure deployment notifications (Teams/Slack)
  • Implement health checks

Continuous Improvement:

  • Review pipeline analytics weekly
  • Collect team feedback
  • Iterate on process based on metrics
  • Document runbooks and troubleshooting guides

Success Metrics:

  • Deployment frequency increases from monthly to weekly/daily
  • Lead time reduces from days to hours
  • Failed deployment rate below 10%
  • Mean time to recovery (MTTR) under 1 hour

Integration & Extensions

27. How does Azure DevOps integrate with GitHub?

Azure DevOps has deep integration with GitHub for organizations using both platforms:

Integration Capabilities:

1. GitHub Repos in Azure Pipelines:

trigger:
  branches:
    include:
    - main

resources:
  repositories:
  - repository: MyGitHubRepo
    type: github
    endpoint: GitHubServiceConnection
    name: myorg/myrepo

steps:
- checkout: MyGitHubRepo

2. Service Connection: Create GitHub service connection using OAuth or PAT

3. PR Validation: Azure Pipelines can validate GitHub pull requests automatically

4. Status Checks: Pipeline results appear as GitHub commit status checks

5. GitHub Actions Integration: Can trigger Azure Pipelines from GitHub Actions

6. Azure Boards + GitHub: Link GitHub commits, PRs, and issues to Azure Boards work items using AB#workitemID in commit messages

Use Cases:

  • Open-source projects on GitHub using Azure Pipelines for free
  • Organizations transitioning between platforms
  • Leveraging both GitHub’s social coding and Azure’s enterprise features

Configuration: Project Settings → Service connections → New service connection → GitHub


CODE EXAMPLES

Complete Multi-Stage Production Pipeline Example

# azure-pipelines.yml - Complete production-ready example

trigger:
  branches:
    include:
    - main
    - develop
  paths:
    exclude:
    - docs/*
    - README.md

variables:
  buildConfiguration: 'Release'
  dockerRegistryServiceConnection: 'myACRConnection'
  imageRepository: 'myapp'
  containerRegistry: 'myregistry.azurecr.io'
  dockerfilePath: '$(Build.SourcesDirectory)/Dockerfile'
  tag: '$(Build.BuildId)'
  vmImageName: 'ubuntu-latest'

stages:
# ============================================
# BUILD STAGE
# ============================================
- stage: Build
  displayName: 'Build and Test'
  jobs:
  - job: Build
    displayName: 'Build Job'
    pool:
      vmImage: $(vmImageName)
    
    steps:
    # Restore dependencies from cache
    - task: Cache@2
      inputs:
        key: 'npm | "$(Agent.OS)" | package-lock.json'
        restoreKeys: |
          npm | "$(Agent.OS)"
        path: $(npm_config_cache)
      displayName: 'Cache npm packages'
    
    # Install dependencies
    - script: npm ci
      displayName: 'Install dependencies'
    
    # Run linting
    - script: npm run lint
      displayName: 'Run ESLint'
    
    # Run unit tests
    - script: npm test -- --coverage --ci
      displayName: 'Run unit tests'
    
    # Publish test results
    - task: PublishTestResults@2
      condition: succeededOrFailed()
      inputs:
        testResultsFormat: 'JUnit'
        testResultsFiles: '**/junit.xml'
        mergeTestResults: true
        testRunTitle: 'Unit Tests'
    
    # Publish code coverage
    - task: PublishCodeCoverageResults@1
      inputs:
        codeCoverageTool: 'Cobertura'
        summaryFileLocation: '$(System.DefaultWorkingDirectory)/coverage/cobertura-coverage.xml'
    
    # Build Docker image
    - task: Docker@2
      displayName: 'Build Docker image'
      inputs:
        command: build
        repository: $(imageRepository)
        dockerfile: $(dockerfilePath)
        containerRegistry: $(dockerRegistryServiceConnection)
        tags: |
          $(tag)
          latest
    
    # Scan Docker image for vulnerabilities
    - task: AzureContainerImageScanTask@0
      displayName: 'Scan Docker image'
      inputs:
        image: '$(containerRegistry)/$(imageRepository):$(tag)'
    
    # Push Docker image
    - task: Docker@2
      displayName: 'Push Docker image'
      inputs:
        command: push
        repository: $(imageRepository)
        containerRegistry: $(dockerRegistryServiceConnection)
        tags: |
          $(tag)
          latest
    
    # Publish Kubernetes manifests as artifact
    - task: PublishPipelineArtifact@1
      inputs:
        targetPath: '$(Build.SourcesDirectory)/k8s'
        artifact: 'manifests'
        publishLocation: 'pipeline'

# ============================================
# DEPLOY TO DEVELOPMENT
# ============================================
- stage: DeployDev
  displayName: 'Deploy to Development'
  dependsOn: Build
  condition: succeeded()
  
  jobs:
  - deployment: DeployDevelopment
    displayName: 'Deploy to Dev Environment'
    environment: 'Development'
    pool:
      vmImage: $(vmImageName)
    
    strategy:
      runOnce:
        deploy:
          steps:
          # Download artifacts
          - download: current
            artifact: manifests
          
          # Replace tokens in manifests
          - task: qetza.replacetokens.replacetokens-task.replacetokens@3
            displayName: 'Replace tokens in k8s manifests'
            inputs:
              targetFiles: '$(Pipeline.Workspace)/manifests/*.yml'
              encoding: 'auto'
              tokenPattern: 'default'
          
          # Deploy to AKS
          - task: Kubernetes@1
            displayName: 'Deploy to AKS Dev'
            inputs:
              connectionType: 'Azure Resource Manager'
              azureSubscriptionEndpoint: 'MyAzureConnection'
              azureResourceGroup: 'myapp-dev-rg'
              kubernetesCluster: 'myapp-dev-aks'
              command: 'apply'
              arguments: '-f $(Pipeline.Workspace)/manifests/'
          
          # Wait for deployment to stabilize
          - task: Kubernetes@1
            displayName: 'Wait for deployment'
            inputs:
              connectionType: 'Azure Resource Manager'
              azureSubscriptionEndpoint: 'MyAzureConnection'
              azureResourceGroup: 'myapp-dev-rg'
              kubernetesCluster: 'myapp-dev-aks'
              command: 'rollout'
              arguments: 'status deployment/myapp -n development'
          
          # Run smoke tests
          - script: |
              echo "Running smoke tests..."
              curl -f https://myapp-dev.example.com/health || exit 1
            displayName: 'Run smoke tests'

# ============================================
# DEPLOY TO STAGING
# ============================================
- stage: DeployStaging
  displayName: 'Deploy to Staging'
  dependsOn: DeployDev
  condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
  
  jobs:
  - deployment: DeployStaging
    displayName: 'Deploy to Staging Environment'
    environment: 'Staging'  # Requires approval in Azure DevOps
    pool:
      vmImage: $(vmImageName)
    
    strategy:
      runOnce:
        deploy:
          steps:
          - download: current
            artifact: manifests
          
          # Get secrets from Key Vault
          - task: AzureKeyVault@2
            inputs:
              azureSubscription: 'MyAzureConnection'
              KeyVaultName: 'myapp-staging-kv'
              SecretsFilter: '*'
              RunAsPreJob: true
          
          - task: qetza.replacetokens.replacetokens-task.replacetokens@3
            displayName: 'Replace tokens'
            inputs:
              targetFiles: '$(Pipeline.Workspace)/manifests/*.yml'
          
          - task: Kubernetes@1
            displayName: 'Deploy to AKS Staging'
            inputs:
              connectionType: 'Azure Resource Manager'
              azureSubscriptionEndpoint: 'MyAzureConnection'
              azureResourceGroup: 'myapp-staging-rg'
              kubernetesCluster: 'myapp-staging-aks'
              command: 'apply'
              arguments: '-f $(Pipeline.Workspace)/manifests/'
          
          # Run integration tests
          - script: npm run test:integration
            displayName: 'Run integration tests'
            env:
              API_URL: 'https://myapp-staging.example.com'

# ============================================
# DEPLOY TO PRODUCTION
# ============================================
- stage: DeployProduction
  displayName: 'Deploy to Production'
  dependsOn: DeployStaging
  condition: succeeded()
  
  jobs:
  - deployment: DeployProduction
    displayName: 'Deploy to Production Environment'
    environment: 'Production'  # Requires approval from multiple approvers
    pool:
      vmImage: $(vmImageName)
    
    strategy:
      runOnce:
        deploy:
          steps:
          - download: current
            artifact: manifests
          
          # Get production secrets
          - task: AzureKeyVault@2
            inputs:
              azureSubscription: 'MyAzureConnection'
              KeyVaultName: 'myapp-prod-kv'
              SecretsFilter: '*'
              RunAsPreJob: true
          
          - task: qetza.replacetokens.replacetokens-task.replacetokens@3
            inputs:
              targetFiles: '$(Pipeline.Workspace)/manifests/*.yml'
          
          # Blue-Green deployment using labels
          - task: Kubernetes@1
            displayName: 'Deploy new version (Green)'
            inputs:
              connectionType: 'Azure Resource Manager'
              azureSubscriptionEndpoint: 'MyAzureConnection'
              azureResourceGroup: 'myapp-prod-rg'
              kubernetesCluster: 'myapp-prod-aks'
              command: 'apply'
              arguments: '-f $(Pipeline.Workspace)/manifests/'
          
          # Health check before traffic switch
          - script: |
              for i in {1..30}; do
                if kubectl rollout status deployment/myapp -n production; then
                  echo "Deployment healthy"
                  exit 0
                fi
                sleep 10
              done
              echo "Deployment failed health check"
              exit 1
           displayName: 'Health check before traffic switch'

# Switch traffic to new version
- task: Kubernetes@1
displayName: 'Switch traffic to Green'
inputs:
connectionType: 'Azure Resource Manager'
azureSubscriptionEndpoint: 'MyAzureConnection'
azureResourceGroup: 'myapp-prod-rg'
kubernetesCluster: 'myapp-prod-aks'
command: 'patch'
arguments: 'service myapp -p ''{"spec":{"selector":{"version":"green"}}}'''

# Post-deployment validation
- script: |
echo "Running production smoke tests..."
for i in {1..10}; do
response=$(curl -s -o /dev/null -w "%{http_code}" https://myapp.example.com/health)
if [ $response -eq 200 ]; then
echo "Health check passed"
else
echo "Health check failed with status: $response"
exit 1
fi
sleep 5
done
displayName: 'Post-deployment validation'

Terraform Integration Example

yaml
# terraform-pipeline.yml - Infrastructure as Code deployment

trigger:
  branches:
    include:
    - main
  paths:
    include:
    - infrastructure/*

variables:
  terraformVersion: '1.5.0'
  workingDirectory: '$(System.DefaultWorkingDirectory)/infrastructure'
  backendResourceGroup: 'terraform-state-rg'
  backendStorageAccount: 'tfstatestorage'
  backendContainerName: 'tfstate'

stages:
- stage: Validate
  displayName: 'Terraform Validate'
  jobs:
  - job: Validate
    pool:
      vmImage: 'ubuntu-latest'
    
    steps:
    # Install Terraform
    - task: TerraformInstaller@0
      displayName: 'Install Terraform'
      inputs:
        terraformVersion: $(terraformVersion)
    
    # Terraform Init
    - task: TerraformTaskV3@3
      displayName: 'Terraform Init'
      inputs:
        provider: 'azurerm'
        command: 'init'
        workingDirectory: $(workingDirectory)
        backendServiceArm: 'MyAzureConnection'
        backendAzureRmResourceGroupName: $(backendResourceGroup)
        backendAzureRmStorageAccountName: $(backendStorageAccount)
        backendAzureRmContainerName: $(backendContainerName)
        backendAzureRmKey: 'prod.terraform.tfstate'
    
    # Terraform Validate
    - task: TerraformTaskV3@3
      displayName: 'Terraform Validate'
      inputs:
        provider: 'azurerm'
        command: 'validate'
        workingDirectory: $(workingDirectory)
    
    # Terraform Format Check
    - script: |
        terraform fmt -check -recursive
      displayName: 'Check Terraform formatting'
      workingDirectory: $(workingDirectory)
    
    # Security Scan with Checkov
    - script: |
        pip install checkov
        checkov -d $(workingDirectory) --output junitxml --output-file-path $(Build.ArtifactStagingDirectory)
      displayName: 'Run Checkov security scan'
      continueOnError: true
    
    # Publish security scan results
    - task: PublishTestResults@2
      condition: succeededOrFailed()
      inputs:
        testResultsFormat: 'JUnit'
        testResultsFiles: '$(Build.ArtifactStagingDirectory)/*.xml'
        testRunTitle: 'Terraform Security Scan'

- stage: Plan
  displayName: 'Terraform Plan'
  dependsOn: Validate
  condition: succeeded()
  jobs:
  - job: Plan
    pool:
      vmImage: 'ubuntu-latest'
    
    steps:
    - task: TerraformInstaller@0
      inputs:
        terraformVersion: $(terraformVersion)
    
    - task: TerraformTaskV3@3
      displayName: 'Terraform Init'
      inputs:
        provider: 'azurerm'
        command: 'init'
        workingDirectory: $(workingDirectory)
        backendServiceArm: 'MyAzureConnection'
        backendAzureRmResourceGroupName: $(backendResourceGroup)
        backendAzureRmStorageAccountName: $(backendStorageAccount)
        backendAzureRmContainerName: $(backendContainerName)
        backendAzureRmKey: 'prod.terraform.tfstate'
    
    # Terraform Plan
    - task: TerraformTaskV3@3
      displayName: 'Terraform Plan'
      inputs:
        provider: 'azurerm'
        command: 'plan'
        workingDirectory: $(workingDirectory)
        environmentServiceNameAzureRM: 'MyAzureConnection'
        commandOptions: '-out=tfplan'
    
    # Publish plan as artifact
    - task: PublishPipelineArtifact@1
      inputs:
        targetPath: '$(workingDirectory)/tfplan'
        artifact: 'terraform-plan'
        publishLocation: 'pipeline'

- stage: Apply
  displayName: 'Terraform Apply'
  dependsOn: Plan
  condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
  jobs:
  - deployment: ApplyInfrastructure
    displayName: 'Apply Infrastructure Changes'
    environment: 'Production-Infrastructure'  # Requires approval
    pool:
      vmImage: 'ubuntu-latest'
    
    strategy:
      runOnce:
        deploy:
          steps:
          - checkout: self
          
          - task: TerraformInstaller@0
            inputs:
              terraformVersion: $(terraformVersion)
          
          - task: TerraformTaskV3@3
            displayName: 'Terraform Init'
            inputs:
              provider: 'azurerm'
              command: 'init'
              workingDirectory: $(workingDirectory)
              backendServiceArm: 'MyAzureConnection'
              backendAzureRmResourceGroupName: $(backendResourceGroup)
              backendAzureRmStorageAccountName: $(backendStorageAccount)
              backendAzureRmContainerName: $(backendContainerName)
              backendAzureRmKey: 'prod.terraform.tfstate'
          
          # Download the plan
          - download: current
            artifact: terraform-plan
          
          # Apply the plan
          - task: TerraformTaskV3@3
            displayName: 'Terraform Apply'
            inputs:
              provider: 'azurerm'
              command: 'apply'
              workingDirectory: $(workingDirectory)
              environmentServiceNameAzureRM: 'MyAzureConnection'
              commandOptions: '$(Pipeline.Workspace)/terraform-plan/tfplan'

Reusable Pipeline Template Examples

Step Template: Build and Test .NET Application

yaml
# templates/dotnet-build-test.yml

parameters:
- name: buildConfiguration
  type: string
  default: 'Release'
- name: dotnetVersion
  type: string
  default: '8.x'
- name: runTests
  type: boolean
  default: true
- name: projectPath
  type: string
  default: '**/*.csproj'

steps:
# Install .NET SDK
- task: UseDotNet@2
  displayName: 'Install .NET ${{ parameters.dotnetVersion }}'
  inputs:
    version: ${{ parameters.dotnetVersion }}

# Restore dependencies
- task: DotNetCoreCLI@2
  displayName: 'Restore NuGet packages'
  inputs:
    command: 'restore'
    projects: '${{ parameters.projectPath }}'

# Build application
- task: DotNetCoreCLI@2
  displayName: 'Build application'
  inputs:
    command: 'build'
    projects: '${{ parameters.projectPath }}'
    arguments: '--configuration ${{ parameters.buildConfiguration }} --no-restore'

# Run tests (conditional)
- ${{ if eq(parameters.runTests, true) }}:
  - task: DotNetCoreCLI@2
    displayName: 'Run unit tests'
    inputs:
      command: 'test'
      projects: '**/*Tests.csproj'
      arguments: '--configuration ${{ parameters.buildConfiguration }} --no-build --collect:"XPlat Code Coverage" --logger trx'
      publishTestResults: true

  # Publish code coverage
  - task: PublishCodeCoverageResults@1
    displayName: 'Publish code coverage'
    condition: succeededOrFailed()
    inputs:
      codeCoverageTool: 'Cobertura'
      summaryFileLocation: '$(Agent.TempDirectory)/**/coverage.cobertura.xml'

# Publish build artifacts
- task: DotNetCoreCLI@2
  displayName: 'Publish application'
  inputs:
    command: 'publish'
    projects: '${{ parameters.projectPath }}'
    arguments: '--configuration ${{ parameters.buildConfiguration }} --output $(Build.ArtifactStagingDirectory) --no-build'
    publishWebProjects: false
    zipAfterPublish: true

- task: PublishPipelineArtifact@1
  displayName: 'Publish pipeline artifact'
  inputs:
    targetPath: '$(Build.ArtifactStagingDirectory)'
    artifact: 'drop'
    publishLocation: 'pipeline'

Using the Template:

yaml
# azure-pipelines.yml

trigger:
- main

pool:
  vmImage: 'ubuntu-latest'

stages:
- stage: Build
  jobs:
  - job: BuildAndTest
    steps:
    - template: templates/dotnet-build-test.yml
      parameters:
        buildConfiguration: 'Release'
        dotnetVersion: '8.x'
        runTests: true
        projectPath: 'src/**/*.csproj'

Job Template: Deploy to Azure App Service

yaml
# templates/deploy-webapp.yml

parameters:
- name: environment
  type: string
- name: azureSubscription
  type: string
- name: appName
  type: string
- name: resourceGroup
  type: string
- name: slotName
  type: string
  default: ''
- name: runSmokeTests
  type: boolean
  default: true

jobs:
- deployment: Deploy${{ parameters.environment }}
  displayName: 'Deploy to ${{ parameters.environment }}'
  environment: ${{ parameters.environment }}
  
  strategy:
    runOnce:
      deploy:
        steps:
        - download: current
          artifact: drop
        
        # Deploy to App Service
        - task: AzureWebApp@1
          displayName: 'Deploy Azure Web App'
          inputs:
            azureSubscription: ${{ parameters.azureSubscription }}
            appType: 'webAppLinux'
            appName: ${{ parameters.appName }}
            resourceGroupName: ${{ parameters.resourceGroup }}
            package: '$(Pipeline.Workspace)/drop/**/*.zip'
            ${{ if ne(parameters.slotName, '') }}:
              deployToSlotOrASE: true
              slotName: ${{ parameters.slotName }}
        
        # Smoke tests (conditional)
        - ${{ if eq(parameters.runSmokeTests, true) }}:
          - script: |
              echo "Running smoke tests for ${{ parameters.environment }}..."
              APP_URL="https://${{ parameters.appName }}.azurewebsites.net"
              
              # Wait for app to be ready
              for i in {1..30}; do
                response=$(curl -s -o /dev/null -w "%{http_code}" $APP_URL/health)
                if [ $response -eq 200 ]; then
                  echo "App is healthy!"
                  break
                fi
                echo "Waiting for app to be ready... (attempt $i/30)"
                sleep 10
              done
              
              # Run basic smoke tests
              if [ $(curl -s -o /dev/null -w "%{http_code}" $APP_URL) -eq 200 ]; then
                echo "Homepage accessible"
              else
                echo "Homepage not accessible"
                exit 1
              fi
            displayName: 'Run smoke tests'
        
        # Post-deployment notification
        - script: |
            echo "Deployment to ${{ parameters.environment }} completed successfully!"
            echo "App URL: https://${{ parameters.appName }}.azurewebsites.net"
          displayName: 'Deployment summary'

Using the Deployment Template:

yaml
# azure-pipelines.yml

stages:
- stage: Build
  jobs:
  - job: BuildJob
    steps:
    - template: templates/dotnet-build-test.yml

- stage: DeployDev
  dependsOn: Build
  jobs:
  - template: templates/deploy-webapp.yml
    parameters:
      environment: 'Development'
      azureSubscription: 'MyAzureConnection'
      appName: 'myapp-dev'
      resourceGroup: 'myapp-dev-rg'
      runSmokeTests: true

- stage: DeployProd
  dependsOn: DeployDev
  condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
  jobs:
  - template: templates/deploy-webapp.yml
    parameters:
      environment: 'Production'
      azureSubscription: 'MyAzureConnection'
      appName: 'myapp-prod'
      resourceGroup: 'myapp-prod-rg'
      slotName: 'staging'
      runSmokeTests: true

Variable Group Management Example

yaml
# Using Variable Groups across environments

variables:
- group: 'common-variables'  # Shared across all environments
- ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/main') }}:
  - group: 'production-variables'
- ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/develop') }}:
  - group: 'development-variables'

stages:
- stage: Build
  jobs:
  - job: BuildJob
    steps:
    - script: |
        echo "Environment: $(environment)"
        echo "API URL: $(apiUrl)"
        echo "Build Number: $(Build.BuildNumber)"
      displayName: 'Display configuration'

Variable Group Configuration (in Azure DevOps UI):

common-variables:

  • buildConfiguration: Release
  • dockerRegistry: myregistry.azurecr.io

development-variables:

production-variables:

  • environment: Production
  • apiUrl: https://api.example.com
  • resourceGroup: myapp-prod-rg
  • dbConnectionString: (secret, linked to Key Vault)

Matrix Build Strategy Example

yaml
# Testing across multiple platforms and versions

trigger:
- main

strategy:
  matrix:
    Linux_Python38:
      imageName: 'ubuntu-latest'
      python.version: '3.8'
    Linux_Python39:
      imageName: 'ubuntu-latest'
      python.version: '3.9'
    Linux_Python310:
      imageName: 'ubuntu-latest'
      python.version: '3.10'
    Windows_Python39:
      imageName: 'windows-latest'
      python.version: '3.9'
    Mac_Python310:
      imageName: 'macOS-latest'
      python.version: '3.10'

pool:
  vmImage: $(imageName)

steps:
- task: UsePythonVersion@0
  inputs:
    versionSpec: '$(python.version)'
  displayName: 'Use Python $(python.version)'

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

- script: |
    pip install pytest pytest-cov
    pytest tests --doctest-modules --junitxml=junit/test-results.xml --cov=. --cov-report=xml
  displayName: 'Run tests with pytest'

- task: PublishTestResults@2
  condition: succeededOrFailed()
  inputs:
    testResultsFiles: '**/test-*.xml'
    testRunTitle: 'Python $(python.version) on $(imageName)'
  displayName: 'Publish test results'

Conditional Pipeline Execution Example

yaml
# azure-pipelines.yml - Smart conditional execution

trigger:
  branches:
    include:
    - main
    - develop
    - feature/*
  paths:
    exclude:
    - docs/**
    - README.md
    - '*.md'

variables:
  isMainBranch: $[eq(variables['Build.SourceBranch'], 'refs/heads/main')]
  isDevelopBranch: $[eq(variables['Build.SourceBranch'], 'refs/heads/develop')]
  isFeatureBranch: $[startsWith(variables['Build.SourceBranch'], 'refs/heads/feature/')]

stages:
# Always run Build stage
- stage: Build
  displayName: 'Build Application'
  jobs:
  - job: BuildJob
    steps:
    - script: echo "Building application..."
    - script: npm install
    - script: npm run build
    
    # Run linting only on feature branches
    - script: npm run lint
      displayName: 'Run ESLint'
      condition: eq(variables.isFeatureBranch, true)

# Run tests on all branches
- stage: Test
  dependsOn: Build
  condition: succeeded()
  jobs:
  - job: UnitTests
    steps:
    - script: npm test
      displayName: 'Unit Tests'
  
  # Integration tests only for develop and main
  - job: IntegrationTests
    condition: or(eq(variables.isMainBranch, true), eq(variables.isDevelopBranch, true))
    steps:
    - script: npm run test:integration
      displayName: 'Integration Tests'

# Deploy to Dev - only for develop branch
- stage: DeployDev
  dependsOn: Test
  condition: and(succeeded(), eq(variables.isDevelopBranch, true))
  jobs:
  - deployment: DeployToDev
    environment: Development
    strategy:
      runOnce:
        deploy:
          steps:
          - script: echo "Deploying to Development"

# Deploy to Staging - only for main branch
- stage: DeployStaging
  dependsOn: Test
  condition: and(succeeded(), eq(variables.isMainBranch, true))
  jobs:
  - deployment: DeployToStaging
    environment: Staging
    strategy:
      runOnce:
        deploy:
          steps:
          - script: echo "Deploying to Staging"

# Deploy to Production - only for main branch with manual approval
- stage: DeployProduction
  dependsOn: DeployStaging
  condition: and(succeeded(), eq(variables.isMainBranch, true))
  jobs:
  - deployment: DeployToProduction
    environment: Production  # Has manual approval configured
    strategy:
      runOnce:
        deploy:
          steps:
          - script: echo "Deploying to Production"

3. TROUBLESHOOTING SCENARIOS

Scenario 1: Pipeline Fails with “No hosted parallelism has been purchased or granted”

Problem: Pipeline queued but never starts running

Solution:

yaml
# Option 1: Use self-hosted agent
pool:
  name: 'Default'  # Your self-hosted agent pool
  
# Option 2: Request free tier for public projects
# Go to: https://aka.ms/azpipelines-parallelism-request

# Option 3: Purchase parallel jobs
# Organization Settings → Billing → Change paid parallel jobs

Scenario 2: Docker Build Fails with “denied: requested access to the resource is denied”

Problem: Cannot push Docker image to registry

Diagnosis Steps:

yaml
# Add debugging
- script: |
    echo "Registry: $(containerRegistry)"
    echo "Repository: $(imageRepository)"
    echo "Tag: $(tag)"
    docker images
  displayName: 'Debug Docker configuration'

# Check service connection
- script: |
    az acr login --name myregistry
  displayName: 'Test ACR login'

Solution:

  1. Verify service connection has AcrPush role
  2. Check repository name format (lowercase only)
  3. Ensure container registry allows anonymous pull if needed
  4. Verify firewall rules allow Azure DevOps IPs

Scenario 3: Variables Not Resolving in Pipeline

Problem: Variables showing as $(variableName) instead of actual values

Common Causes & Solutions:

yaml
# Issue: Using macro syntax in wrong context
# Wrong:
- script: echo $(myVariable)  # Works
- task: SomeTask@1
  inputs:
    value: $(myVariable)  # May not work in all contexts

# Correct: Use runtime expression
- task: SomeTask@1
  inputs:
    value: $[variables.myVariable]

# Issue: Secret variables in different job
# Variables set in one job aren't available in another
jobs:
- job: JobA
  steps:
  - script: echo "##vso[task.setvariable variable=myVar;isOutput=true]myValue"
    name: setVar

- job: JobB
  dependsOn: JobA
  variables:
    myVar: $[ dependencies.JobA.outputs['setVar.myVar'] ]
  steps:
  - script: echo $(myVar)

Scenario 4: Kubernetes Deployment Stuck

Problem: Deployment to AKS hangs or times out

Debugging:

yaml
- task: Kubernetes@1
  displayName: 'Check pod status'
  inputs:
    command: 'get'
    arguments: 'pods -n production'
    
- task: Kubernetes@1
  displayName: 'Describe deployment'
  inputs:
    command: 'describe'
    arguments: 'deployment/myapp -n production'

- task: Kubernetes@1
  displayName: 'Check events'
  inputs:
    command: 'get'
    arguments: 'events -n production --sort-by=.metadata.creationTimestamp'

Common Solutions:

  • Image pull errors: Check service connection and image name
  • Resource limits: Adjust CPU/memory requests
  • Liveness probe failures: Increase initialDelaySeconds
  • ConfigMap/Secret missing: Verify they exist in namespace

Best Practices and Tips for Azure DevOps Interviews

Preparing for an Azure DevOps interview requires not only understanding the platform’s features but also demonstrating practical knowledge of DevOps principles and workflows. Here are some tips to help you succeed:

Section Image

Understand the DevOps Culture and Principles

Interviewers often assess your grasp of DevOps beyond tools. Be ready to discuss how Azure DevOps supports collaboration, automation, continuous improvement, and faster delivery.

Demonstrate Hands-on Experience

Practical experience with setting up pipelines, managing repositories, and using Azure Boards can set you apart. Be prepared to explain your approach to solving common challenges like merge conflicts, deployment failures, or test automation.

Stay Updated on New Features

Azure DevOps evolves continuously. Familiarize yourself with recent updates, new extensions, and best practices to show that you keep your skills current.

Prepare for Scenario-Based Questions

Many interviews include scenario questions where you must design or troubleshoot a DevOps pipeline or workflow. Practice articulating your thought process clearly and logically.

Conclusion

Azure DevOps remains a critical platform for organizations adopting DevOps practices in 2026. Its comprehensive suite of tools covering source control, CI/CD, project management, artifact handling, and testing makes it indispensable for modern software development teams.

Section Image

By mastering the questions outlined in this article, candidates can confidently demonstrate their knowledge and practical skills during interviews. Understanding both the technical capabilities and the cultural aspects of DevOps will help you stand out and secure your desired role. Make sure to also review the top DevOps skills for 2026 to round out your preparation.

For more detailed learning, consider exploring official Microsoft documentation and hands-on labs to deepen your expertise in Azure DevOps. If you want to validate your skills formally, our overview of top Azure DevOps certifications can help you choose the right path.

Nathan Cole Avatar

Leave a Reply

Your email address will not be published. Required fields are marked *