Azure DevOps

Version ControlDevOpsMicrosoftPlatformCI/CDEnterpriseCloudGit

Microsoft DevOps Platform

Azure DevOps

Overview

Azure DevOps is Microsoft's comprehensive cloud-based DevOps platform that provides version control, project management, build automation, testing, and deployment capabilities. Launched in 2018 as the evolution of Visual Studio Team Services, Azure DevOps integrates seamlessly with Microsoft's ecosystem while supporting cross-platform development. The platform offers both cloud-hosted services and on-premises deployment options through Azure DevOps Server.

Details

Azure DevOps consists of five main services: Azure Repos (Git and TFVC version control), Azure Pipelines (CI/CD), Azure Boards (work tracking), Azure Test Plans (testing), and Azure Artifacts (package management). These services can be used independently or together as an integrated platform.

Azure Repos supports both Git (distributed) and Team Foundation Version Control (TFVC, centralized) repositories. The Git implementation provides full compatibility with standard Git workflows while adding enterprise features like path-based permissions and large file support.

The platform excels in enterprise environments with features like Azure Active Directory integration, advanced security policies, and compliance capabilities. Azure DevOps also provides excellent integration with Visual Studio, VS Code, and other Microsoft development tools.

Key differentiators include unlimited private Git repositories, built-in CI/CD pipelines, comprehensive project management tools, and seamless integration with Azure cloud services for deployment and monitoring.

Advantages and Disadvantages

Advantages

  • Comprehensive Platform: Complete DevOps toolchain in one service
  • Microsoft Integration: Seamless integration with Microsoft ecosystem
  • Free Tier: Generous free tier with unlimited private repositories
  • Enterprise Features: Advanced security, compliance, and governance
  • Multi-platform Support: Supports development across all platforms
  • Scalable Pipelines: Robust CI/CD with auto-scaling capabilities
  • Project Management: Integrated work tracking and planning tools
  • Visual Studio Integration: Deep integration with Microsoft IDEs

Disadvantages

  • Microsoft Ecosystem Lock-in: Best features require Microsoft stack
  • Complex Interface: Can be overwhelming for simple projects
  • Learning Curve: Many features require significant learning investment
  • Cost Scaling: Can become expensive for large teams
  • Third-party Integration: Limited compared to specialized tools
  • Performance Issues: Can be slow for very large repositories

Reference Pages

Code Examples

Repository Setup and Basic Git Operations

# Clone Azure DevOps repository
git clone https://dev.azure.com/organization/project/_git/repository

# Add Azure DevOps as remote
git remote add origin https://dev.azure.com/org/project/_git/repo

# Push to Azure DevOps
git push -u origin main

# Clone with personal access token
git clone https://username:[email protected]/org/project/_git/repo

# Configure Git for Azure DevOps
git config credential.helper manager-core
git config credential.https://dev.azure.com.useHttpPath true

Azure Pipelines YAML Configuration

# azure-pipelines.yml
trigger:
  branches:
    include:
    - main
    - develop
  paths:
    exclude:
    - docs/*
    - README.md

variables:
  buildConfiguration: 'Release'
  vmImageName: 'ubuntu-latest'

stages:
- stage: Build
  displayName: Build stage
  jobs:
  - job: Build
    displayName: Build
    pool:
      vmImage: $(vmImageName)
    steps:
    - task: NodeTool@0
      inputs:
        versionSpec: '18.x'
      displayName: 'Install Node.js'
    
    - script: |
        npm ci
        npm run build
        npm test
      displayName: 'npm install, build and test'
    
    - task: PublishTestResults@2
      condition: succeededOrFailed()
      inputs:
        testRunner: JUnit
        testResultsFiles: '**/test-results.xml'
    
    - task: PublishCodeCoverageResults@1
      inputs:
        codeCoverageTool: Cobertura
        summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/*coverage.xml'

- stage: Deploy
  displayName: Deploy stage
  dependsOn: Build
  condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
  jobs:
  - deployment: Deploy
    displayName: Deploy
    environment: 'production'
    pool:
      vmImage: $(vmImageName)
    strategy:
      runOnce:
        deploy:
          steps:
          - task: AzureWebApp@1
            displayName: 'Azure Web App Deploy'
            inputs:
              azureSubscription: 'azure-service-connection'
              appType: 'webAppLinux'
              appName: 'my-web-app'
              package: '$(Pipeline.Workspace)/drop/*.zip'

Multi-stage Pipeline with Environments

# azure-pipelines.yml
trigger: none # Manual trigger only

variables:
  - group: production-variables
  - name: buildConfiguration
    value: 'Release'

stages:
- stage: Build
  jobs:
  - job: Build
    pool:
      vmImage: 'windows-latest'
    steps:
    - task: DotNetCoreCLI@2
      displayName: 'Restore packages'
      inputs:
        command: 'restore'
        projects: '**/*.csproj'
    
    - task: DotNetCoreCLI@2
      displayName: 'Build solution'
      inputs:
        command: 'build'
        projects: '**/*.csproj'
        arguments: '--configuration $(buildConfiguration)'
    
    - task: DotNetCoreCLI@2
      displayName: 'Run tests'
      inputs:
        command: 'test'
        projects: '**/*Tests/*.csproj'
        arguments: '--configuration $(buildConfiguration) --collect "Code coverage"'
    
    - task: DotNetCoreCLI@2
      displayName: 'Publish application'
      inputs:
        command: 'publish'
        publishWebProjects: true
        arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)'
    
    - publish: $(Build.ArtifactStagingDirectory)
      artifact: drop

- stage: DeployToStaging
  dependsOn: Build
  jobs:
  - deployment: DeployStaging
    environment: 'staging'
    strategy:
      runOnce:
        deploy:
          steps:
          - download: current
            artifact: drop
          - task: AzureRmWebAppDeployment@4
            inputs:
              ConnectionType: 'AzureRM'
              azureSubscription: 'staging-service-connection'
              appType: 'webApp'
              WebAppName: 'myapp-staging'
              packageForLinux: '$(Pipeline.Workspace)/drop/*.zip'

- stage: DeployToProduction
  dependsOn: DeployToStaging
  condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
  jobs:
  - deployment: DeployProduction
    environment: 'production'
    strategy:
      runOnce:
        deploy:
          steps:
          - download: current
            artifact: drop
          - task: AzureRmWebAppDeployment@4
            inputs:
              ConnectionType: 'AzureRM'
              azureSubscription: 'production-service-connection'
              appType: 'webApp'
              WebAppName: 'myapp-production'
              packageForLinux: '$(Pipeline.Workspace)/drop/*.zip'

Azure DevOps CLI Usage

# Install Azure DevOps CLI extension
az extension add --name azure-devops

# Configure default organization and project
az devops configure --defaults organization=https://dev.azure.com/myorg project=myproject

# Login to Azure DevOps
az login
az devops login

# Repository operations
az repos list
az repos create --name new-repository
az repos delete --id repository-id

# Pipeline operations
az pipelines list
az pipelines create --name "Build Pipeline" --yml-path azure-pipelines.yml
az pipelines run --name "Build Pipeline"

# Work item operations
az boards work-item create --title "New feature" --type "User Story"
az boards work-item list --wiql "SELECT [Id], [Title] FROM WorkItems WHERE [State] = 'Active'"

# Pull request operations
az repos pr create --title "Add new feature" --source-branch feature/new-feature
az repos pr list --status active

Azure DevOps REST API Usage

# Set variables
ORGANIZATION="your-org"
PROJECT="your-project"
PAT="your-personal-access-token"
API_VERSION="7.1-preview.1"

# Get repositories
curl -u :$PAT \
  "https://dev.azure.com/$ORGANIZATION/$PROJECT/_apis/git/repositories?api-version=$API_VERSION"

# Create pull request
curl -u :$PAT \
  -H "Content-Type: application/json" \
  -d '{
    "sourceRefName": "refs/heads/feature/new-feature",
    "targetRefName": "refs/heads/main",
    "title": "Add new feature",
    "description": "This PR adds a new feature"
  }' \
  "https://dev.azure.com/$ORGANIZATION/$PROJECT/_apis/git/repositories/REPO_ID/pullrequests?api-version=$API_VERSION"

# Get build definitions
curl -u :$PAT \
  "https://dev.azure.com/$ORGANIZATION/$PROJECT/_apis/build/definitions?api-version=$API_VERSION"

# Queue a build
curl -u :$PAT \
  -H "Content-Type: application/json" \
  -d '{
    "definition": {"id": DEFINITION_ID},
    "sourceBranch": "refs/heads/main"
  }' \
  "https://dev.azure.com/$ORGANIZATION/$PROJECT/_apis/build/builds?api-version=$API_VERSION"

Branch Policies Configuration

// Branch policy via REST API
{
  "type": {
    "id": "fa4e907d-c16b-4a4c-9dfa-4906e5d171dd"  // Build validation policy
  },
  "isEnabled": true,
  "isBlocking": true,
  "settings": {
    "buildDefinitionId": 123,
    "queueOnSourceUpdateOnly": true,
    "manualQueueOnly": false,
    "displayName": "Build validation",
    "validDuration": 720
  }
}

Work Item Tracking Integration

# Pipeline with work item linking
trigger:
  branches:
    include:
    - main

variables:
  workItemId: $[variables.System.PullRequest.AssociatedWorkItemId]

steps:
- script: |
    echo "Processing work item: $(workItemId)"
    # Custom logic based on work item
  displayName: 'Process work item'

- task: WorkItemUpdater@2
  inputs:
    workItemId: $(workItemId)
    state: 'Done'
    assignedTo: '[email protected]'

Package Management with Azure Artifacts

# Configure npm to use Azure Artifacts feed
npm config set registry https://pkgs.dev.azure.com/org/project/_packaging/feed/npm/registry/
npm config set always-auth true

# Install packages from Azure Artifacts
npm install @myorg/my-package

# Publish package to Azure Artifacts
npm publish
<!-- NuGet.config for .NET packages -->
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <add key="MyFeed" value="https://pkgs.dev.azure.com/org/project/_packaging/feed/nuget/v3/index.json" />
  </packageSources>
</configuration>

Integration with Visual Studio

// .vscode/settings.json for VS Code integration
{
  "azure-devops.organization": "https://dev.azure.com/myorg",
  "azure-devops.project": "myproject",
  "azure-devops.repo": "myrepo",
  "git.defaultCloneDirectory": "C:/Source",
  "azure-boards.workItemTypes": ["Bug", "User Story", "Task"]
}

Custom Dashboard and Widgets

// Dashboard configuration via REST API
{
  "name": "Project Dashboard",
  "description": "Main project dashboard",
  "widgets": [
    {
      "name": "Build History",
      "position": {"row": 1, "column": 1},
      "size": {"rowSpan": 2, "columnSpan": 2},
      "widgetType": "Microsoft.VisualStudioOnline.Dashboards.BuildHistogramWidget"
    },
    {
      "name": "Work Item Chart",
      "position": {"row": 1, "column": 3},
      "size": {"rowSpan": 1, "columnSpan": 2},
      "widgetType": "Microsoft.VisualStudioOnline.Dashboards.WorkItemChartWidget"
    }
  ]
}

Security and Compliance

# Pipeline with security scanning
steps:
- task: CredScan@3
  inputs:
    toolMajorVersion: 'V2'
    scanFolder: '$(Build.SourcesDirectory)'
    debugMode: false

- task: SdtReport@2
  inputs:
    GdnExportAllTools: false
    GdnExportGdnToolCredScan: true

- task: PublishSecurityAnalysisLogs@3
  inputs:
    ArtifactName: 'CodeAnalysisLogs'
    ArtifactType: 'Container'

- task: PostAnalysis@2
  inputs:
    GdnBreakAllTools: false
    GdnBreakGdnToolCredScan: true