Manage Azure DevOps resources via CLI including projects, repos, pipelines, builds, pull requests, work items, artifacts, and service endpoints. Use when working with Azure DevOps, az commands, devops automation, CI/CD, or when user mentions Azure DevOps CLI.
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
Manage Azure DevOps resources via CLI including projects, repos, pipelines, builds, pull requests, work items, artifacts, and service endpoints. Use when working with Azure DevOps, az commands, devops automation, CI/CD, or when user mentions Azure DevOps CLI.
Azure DevOps CLI
This Skill helps manage Azure DevOps resources using the Azure CLI with Azure DevOps extension.
CLI Version: 2.81.0 (current as of 2025)
Prerequisites
Install Azure CLI and Azure DevOps extension:
# Install Azure CLI
brew install azure-cli # macOS
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash # Linux
pip install azure-cli # via pip# Verify installation
az --version
# Install Azure DevOps extension
az extension add --name azure-devops
az extension show --name azure-devops
CLI Structure
az devops # Main DevOps commands
├── admin # Administration (banner)
├── extension # Extension management
├── project # Team projects
├── security # Security operations
│ ├── group # Security groups
│ └── permission # Security permissions
├── service-endpoint # Service connections
├── team # Teams
├── user # Users
├── wiki # Wikis
├── configure # Set defaults
├── invoke # Invoke REST API
├── login # Authenticate
└── logout # Clear credentials
az pipelines # Azure Pipelines
├── agent # Agents
├── build # Builds
├── folder # Pipeline folders
├── pool # Agent pools
├── queue # Agent queues
├── release # Releases
├── runs # Pipeline runs
├── variable # Pipeline variables
└── variable-group # Variable groups
az boards # Azure Boards
├── area # Area paths
├── iteration # Iterations
└── work-item # Work items
az repos # Azure Repos
├── import # Git imports
├── policy # Branch policies
├── pr # Pull requests
└── ref # Git references
az artifacts # Azure Artifacts
└── universal # Universal Packages
├── download # Download packages
└── publish # Publish packages
Authentication
Login to Azure DevOps
# Interactive login (prompts for PAT)
az devops login --organization https://dev.azure.com/{org}
# Login with PAT token
az devops login --organization https://dev.azure.com/{org} --token YOUR_PAT_TOKEN
# Logout
az devops logout --organization https://dev.azure.com/{org}
Configure Defaults
# Set default organization and project
az devops configure --defaults organization=https://dev.azure.com/{org} project={project}
# List current configuration
az devops configure --list
# Enable Git aliases
az devops configure --use-git-aliases true
Extension Management
List Extensions
# List available extensions
az extension list-available --output table
# List installed extensions
az extension list --output table
Manage Azure DevOps Extension
# Install Azure DevOps extension
az extension add --name azure-devops
# Update Azure DevOps extension
az extension update --name azure-devops
# Remove extension
az extension remove --name azure-devops
# Install from local path
az extension add --source ~/extensions/azure-devops.whl
Projects
List Projects
az devops project list --organization https://dev.azure.com/{org}
az devops project list --top 10 --output table
Create Project
az devops project create \
--name myNewProject \
--organization https://dev.azure.com/{org} \
--description "My new DevOps project" \
--source-control git \
--visibility private
Show Project Details
az devops project show --project {project-name} --org https://dev.azure.com/{org}
Delete Project
az devops project delete --id {project-id} --org https://dev.azure.com/{org} --yes
Repositories
List Repositories
az repos list --org https://dev.azure.com/{org} --project {project}
az repos list --output table
Show Repository Details
az repos show --repository {repo-name} --project {project}
Create Repository
az repos create --name {repo-name} --project {project}
Delete Repository
az repos delete --id {repo-id} --project {project} --yes
Update Repository
az repos update --id {repo-id} --name {new-name} --project {project}
Repository Import
Import Git Repository
# Import from public Git repository
az repos import create \
--git-source-url https://github.com/user/repo \
--repository {repo-name}
# Import with authentication
az repos import create \
--git-source-url https://github.com/user/private-repo \
--repository {repo-name} \
--user {username} \
--password {password-or-pat}
# All PRs
az repos pr list --repository {repo}
# Filter by status
az repos pr list --repository {repo} --status active
# Filter by creator
az repos pr list --repository {repo} --creator {email}
# Output as table
az repos pr list --repository {repo} --output table
Show PR Details
az repos pr show --id {pr-id}
az repos pr show --id {pr-id} --open # Open in browser
Update PR (Complete/Abandon/Draft)
# Complete PR
az repos pr update --id {pr-id} --status completed
# Abandon PR
az repos pr update --id {pr-id} --status abandoned
# Set to draft
az repos pr update --id {pr-id} --draft true# Publish draft PR
az repos pr update --id {pr-id} --draft false# Auto-complete when policies pass
az repos pr update --id {pr-id} --auto-complete true# Set title and description
az repos pr update --id {pr-id} --title "New title" --description "New description"
Checkout PR Locally
# Checkout PR branch
az repos pr checkout --id {pr-id}
# Checkout with specific remote
az repos pr checkout --id {pr-id} --remote-name upstream
Vote on PR
az repos pr set-vote --id {pr-id} --vote approve
az repos pr set-vote --id {pr-id} --vote approve-with-suggestions
az repos pr set-vote --id {pr-id} --vote reject
az repos pr set-vote --id {pr-id} --vote wait-for-author
az repos pr set-vote --id {pr-id} --vote reset
PR Reviewers
# Add reviewers
az repos pr reviewer add --id {pr-id} --reviewers user1@example.com user2@example.com
# List reviewers
az repos pr reviewer list --id {pr-id}
# Remove reviewers
az repos pr reviewer remove --id {pr-id} --reviewers user1@example.com
PR Work Items
# Add work items to PR
az repos pr work-item add --id {pr-id} --work-items {id1} {id2}
# List PR work items
az repos pr work-item list --id {pr-id}
# Remove work items from PR
az repos pr work-item remove --id {pr-id} --work-items {id1}
PR Policies
# List policies for a PR
az repos pr policy list --id {pr-id}
# Queue policy evaluation for a PR
az repos pr policy queue --id {pr-id} --evaluation-id {evaluation-id}
Pipelines
List Pipelines
az pipelines list --output table
az pipelines list --query "[?name=='myPipeline']"
az pipelines list --folder-path 'folder/subfolder'
Create Pipeline
# From local repository context (auto-detects settings)
az pipelines create --name 'ContosoBuild' --description 'Pipeline for contoso project'# With specific branch and YAML path
az pipelines create \
--name {pipeline-name} \
--repository {repo} \
--branch main \
--yaml-path azure-pipelines.yml \
--description "My CI/CD pipeline"# For GitHub repository
az pipelines create \
--name 'GitHubPipeline' \
--repository https://github.com/Org/Repo \
--branch main \
--repository-type github
# Skip first run
az pipelines create --name 'MyPipeline' --skip-run true
Show Pipeline
az pipelines show --id {pipeline-id}
az pipelines show --name {pipeline-name}
Update Pipeline
az pipelines update --id {pipeline-id} --name "New name" --description "Updated description"
Delete Pipeline
az pipelines delete --id {pipeline-id} --yes
Run Pipeline
# Run by name
az pipelines run --name {pipeline-name} --branch main
# Run by ID
az pipelines run --id {pipeline-id} --branch refs/heads/main
# With parameters
az pipelines run --name {pipeline-name} --parameters version=1.0.0 environment=prod
# With variables
az pipelines run --name {pipeline-name} --variables buildId=123 configuration=release
# Open results in browser
az pipelines run --name {pipeline-name} --open
Pipeline Runs
List Runs
az pipelines runs list --pipeline {pipeline-id}
az pipelines runs list --name {pipeline-name} --top 10
az pipelines runs list --branch main --status completed
Show Run Details
az pipelines runs show --run-id {run-id}
az pipelines runs show --run-id {run-id} --open
Pipeline Artifacts
# List artifacts for a run
az pipelines runs artifact list --run-id {run-id}
# Download artifact
az pipelines runs artifact download \
--artifact-name '{artifact-name}' \
--path {local-path} \
--run-id {run-id}
# Upload artifact
az pipelines runs artifact upload \
--artifact-name '{artifact-name}' \
--path {local-path} \
--run-id {run-id}
Pipeline Run Tags
# Add tag to run
az pipelines runs tag add --run-id {run-id} --tags production v1.0
# List run tags
az pipelines runs tag list --run-id {run-id} --output table
Builds
List Builds
az pipelines build list
az pipelines build list --definition {build-definition-id}
az pipelines build list --status completed --result succeeded
Queue Build
az pipelines build queue --definition {build-definition-id} --branch main
az pipelines build queue --definition {build-definition-id} --parameters version=1.0.0
Show Build Details
az pipelines build show --id {build-id}
Cancel Build
az pipelines build cancel --id {build-id}
Build Tags
# Add tag to build
az pipelines build tag add --build-id {build-id} --tags prod release
# Delete tag from build
az pipelines build tag delete --build-id {build-id} --tag prod
Build Definitions
List Build Definitions
az pipelines build definition list
az pipelines build definition list --name {definition-name}
Show Build Definition
az pipelines build definition show --id {definition-id}
Releases
List Releases
az pipelines release list
az pipelines release list --definition {release-definition-id}
Create Release
az pipelines release create --definition {release-definition-id}
az pipelines release create --definition {release-definition-id} --description "Release v1.0"
Show Release
az pipelines release show --id {release-id}
Release Definitions
List Release Definitions
az pipelines release definition list
Show Release Definition
az pipelines release definition show --id {definition-id}
Pipeline Variables
List Variables
az pipelines variable list --pipeline-id {pipeline-id}
az pipelines folder create --path 'folder/subfolder' --description "My folder"
Delete Folder
az pipelines folder delete --path 'folder/subfolder'
Update Folder
az pipelines folder update --path 'old-folder' --new-path 'new-folder'
Agent Pools
List Agent Pools
az pipelines pool list
az pipelines pool list --pool-type automation
az pipelines pool list --pool-type deployment
Show Agent Pool
az pipelines pool show --pool-id {pool-id}
Agent Queues
List Agent Queues
az pipelines queue list
az pipelines queue list --pool-name {pool-name}
Show Agent Queue
az pipelines queue show --id {queue-id}
Work Items (Boards)
Query Work Items
# WIQL query
az boards query \
--wiql "SELECT [System.Id], [System.Title], [System.State] FROM WorkItems WHERE [System.AssignedTo] = @Me AND [System.State] = 'Active'"# Query with output format
az boards query --wiql "SELECT * FROM WorkItems" --output table
Show Work Item
az boards work-item show --id {work-item-id}
az boards work-item show --id {work-item-id} --open
Create Work Item
# Basic work item
az boards work-item create \
--title "Fix login bug" \
--type Bug \
--assigned-to user@example.com \
--description "Users cannot login with SSO"# With area and iteration
az boards work-item create \
--title "New feature" \
--type"User Story" \
--area "Project\\Area1" \
--iteration "Project\\Sprint 1"# With custom fields
az boards work-item create \
--title "Task" \
--type Task \
--fields "Priority=1""Severity=2"# With discussion comment
az boards work-item create \
--title "Issue" \
--type Bug \
--discussion "Initial investigation completed"# Open in browser after creation
az boards work-item create --title "Bug" --type Bug --open
Update Work Item
# Update state, title, and assignee
az boards work-item update \
--id {work-item-id} \
--state "Active" \
--title "Updated title" \
--assigned-to user@example.com
# Move to different area
az boards work-item update \
--id {work-item-id} \
--area "{ProjectName}\\{Team}\\{Area}"# Change iteration
az boards work-item update \
--id {work-item-id} \
--iteration "{ProjectName}\\Sprint 5"# Add comment/discussion
az boards work-item update \
--id {work-item-id} \
--discussion "Work in progress"# Update with custom fields
az boards work-item update \
--id {work-item-id} \
--fields "Priority=1""StoryPoints=5"
Delete Work Item
# Soft delete (can be restored)
az boards work-item delete --id {work-item-id} --yes# Permanent delete
az boards work-item delete --id {work-item-id} --destroy --yes
Work Item Relations
# List relations
az boards work-item relation list --id {work-item-id}
# List supported relation types
az boards work-item relation list-type
# Add relation
az boards work-item relation add --id {work-item-id} --relation-type parent --target-id {parent-id}
# Remove relation
az boards work-item relation remove --id {work-item-id} --relation-id {relation-id}
Area Paths
List Areas for Project
az boards area project list --project {project}
az boards area project show --path "Project\\Area1" --project {project}
Create Area
az boards area project create --path "Project\\NewArea" --project {project}
Update Area
az boards area project update \
--path "Project\\OldArea" \
--new-path "Project\\UpdatedArea" \
--project {project}
Delete Area
az boards area project delete --path "Project\\AreaToDelete" --project {project} --yes
Area Team Management
# List areas for team
az boards area team list --team {team-name} --project {project}
# Add area to team
az boards area team add \
--team {team-name} \
--path "Project\\NewArea" \
--project {project}
# Remove area from team
az boards area team remove \
--team {team-name} \
--path "Project\\AreaToRemove" \
--project {project}
# Update team area
az boards area team update \
--team {team-name} \
--path "Project\\Area" \
--project {project} \
--include-sub-areas true
Iterations
List Iterations for Project
az boards iteration project list --project {project}
az boards iteration project show --path "Project\\Sprint 1" --project {project}
Create Iteration
az boards iteration project create --path "Project\\Sprint 1" --project {project}
az repos policy case-enforcement create \
--blocking true \
--enabled true \
--branch main \
--repository-id {repo-id}
Comment Required Policy
az repos policy comment-required create \
--blocking true \
--enabled true \
--branch main \
--repository-id {repo-id}
File Size Policy
az repos policy file-size create \
--blocking true \
--enabled true \
--branch main \
--repository-id {repo-id} \
--maximum-file-size 10485760 # 10MB in bytes
Service Endpoints
List Service Endpoints
az devops service-endpoint list --project {project}
az devops service-endpoint list --project {project} --output table
Show Service Endpoint
az devops service-endpoint show --id {endpoint-id} --project {project}
Create Service Endpoint
# Using configuration file
az devops service-endpoint create --service-endpoint-configuration endpoint.json --project {project}
Delete Service Endpoint
az devops service-endpoint delete --id {endpoint-id} --project {project} --yes
Teams
List Teams
az devops team list --project {project}
Show Team
az devops team show --team {team-name} --project {project}
Create Team
az devops team create \
--name {team-name} \
--description "Team description" \
--project {project}
Update Team
az devops team update \
--team {team-name} \
--project {project} \
--name "{new-team-name}" \
--description "Updated description"
Delete Team
az devops team delete --team {team-name} --project {project} --yes
Show Team Members
az devops team list-member --team {team-name} --project {project}
Users
List Users
az devops user list --org https://dev.azure.com/{org}
az devops user list --top 10 --output table
Show User
az devops user show --user {user-id-or-email} --org https://dev.azure.com/{org}
Add User
az devops user add \
--email user@example.com \
--license-type express \
--org https://dev.azure.com/{org}
Update User
az devops user update \
--user {user-id-or-email} \
--license-type advanced \
--org https://dev.azure.com/{org}
Remove User
az devops user remove --user {user-id-or-email} --org https://dev.azure.com/{org} --yes
Security Groups
List Groups
# List all groups in project
az devops security group list --project {project}
# List all groups in organization
az devops security group list --scope organization
# List with filtering
az devops security group list --project {project} --subject-types vstsgroup
Show Group Details
az devops security group show --group-id {group-id}
Create Group
az devops security group create \
--name {group-name} \
--description "Group description" \
--project {project}
Update Group
az devops security group update \
--group-id {group-id} \
--name "{new-group-name}" \
--description "Updated description"
Delete Group
az devops security group delete --group-id {group-id} --yes
Group Memberships
# List memberships
az devops security group membership list --id {group-id}
# Add member
az devops security group membership add \
--group-id {group-id} \
--member-id {member-id}
# Remove member
az devops security group membership remove \
--group-id {group-id} \
--member-id {member-id} --yes
Security Permissions
List Namespaces
az devops security permission namespace list
Show Namespace Details
# Show permissions available in a namespace
az devops security permission namespace show --namespace "GitRepositories"
List Permissions
# List permissions for user/group and namespace
az devops security permission list \
--id {user-or-group-id} \
--namespace "GitRepositories" \
--project {project}
# List for specific token (repository)
az devops security permission list \
--id {user-or-group-id} \
--namespace "GitRepositories" \
--project {project} \
--token "repoV2/{project}/{repository-id}"
Show Permissions
az devops security permission show \
--id {user-or-group-id} \
--namespace "GitRepositories" \
--project {project} \
--token "repoV2/{project}/{repository-id}"
az pipelines agent show --agent-id {agent-id} --pool-id {pool-id}
Git Aliases
After enabling git aliases:
# Enable Git aliases
az devops configure --use-git-aliases true# Use Git commands for DevOps operations
git pr create --target-branch main
git pr list
git pr checkout 123
Output Formats
All commands support multiple output formats:
# Table format (human-readable)
az pipelines list --output table
# JSON format (default, machine-readable)
az pipelines list --output json
# JSONC (colored JSON)
az pipelines list --output jsonc
# YAML format
az pipelines list --output yaml
# YAMLC (colored YAML)
az pipelines list --output yamlc
# TSV format (tab-separated values)
az pipelines list --output tsv
# None (no output)
az pipelines list --output none
JMESPath Queries
Filter and transform output:
# Filter by name
az pipelines list --query "[?name=='myPipeline']"# Get specific fields
az pipelines list --query "[].{Name:name, ID:id}"# Chain queries
az pipelines list --query "[?name.contains('CI')].{Name:name, ID:id}" --output table
# Get first result
az pipelines list --query "[0]"# Get top N
az pipelines list --query "[0:5]"
# From local git repository (auto-detects repo, branch, etc.)
az pipelines create --name 'CI-Pipeline' --description 'Continuous Integration'
Bulk update work items
# Query items and update in loopforidin $(az boards query --wiql "SELECT ID FROM WorkItems WHERE State='New'" -o tsv); do
az boards work-item update --id$id --state "Active"done
Best Practices
Authentication and Security
# Use PAT from environment variable (most secure)export AZURE_DEVOPS_EXT_PAT=$MY_PAT
az devops login --organization $ORG_URL# Pipe PAT securely (avoids shell history)echo$MY_PAT | az devops login --organization $ORG_URL# Set defaults to avoid repetition
az devops configure --defaults organization=$ORG_URL project=$PROJECT# Clear credentials after use
az devops logout --organization $ORG_URL
Idempotent Operations
# Always use --detect for auto-detection
az devops configure --defaults organization=$ORG_URL project=$PROJECT# Check existence before creationif ! az pipelines show --id$PIPELINE_ID 2>/dev/null; then
az pipelines create --name "$PIPELINE_NAME" --yaml-path azure-pipelines.yml
fi# Use --output tsv for shell parsing
PIPELINE_ID=$(az pipelines list --query "[?name=='MyPipeline'].id" --output tsv)
# Use --output json for programmatic access
BUILD_STATUS=$(az pipelines build show --id$BUILD_ID --query "status" --output json)
Script-Safe Output
# Suppress warnings and errors
az pipelines list --only-show-errors
# No output (useful for commands that only need to execute)
az pipelines run --name "$PIPELINE_NAME" --output none
# TSV format for shell scripts (clean, no formatting)
az repos pr list --output tsv --query "[].{ID:pullRequestId,Title:title}"# JSON with specific fields
az pipelines list --output json --query "[].{Name:name, ID:id, URL:url}"
Pipeline Orchestration
# Run pipeline and wait for completion
RUN_ID=$(az pipelines run --name "$PIPELINE_NAME" --query "id" -o tsv)
whiletrue; do
STATUS=$(az pipelines runs show --run-id $RUN_ID --query "status" -o tsv)
if [[ "$STATUS" != "inProgress" && "$STATUS" != "notStarted" ]]; thenbreakfisleep 10
done# Check result
RESULT=$(az pipelines runs show --run-id $RUN_ID --query "result" -o tsv)
if [[ "$RESULT" == "succeeded" ]]; thenecho"Pipeline succeeded"elseecho"Pipeline failed with result: $RESULT"exit 1
fi
Variable Group Management
# Create variable group idempotently
VG_NAME="production-variables"
VG_ID=$(az pipelines variable-group list --query "[?name=='$VG_NAME'].id" -o tsv)
if [[ -z "$VG_ID" ]]; then
VG_ID=$(az pipelines variable-group create \
--name "$VG_NAME" \
--variables API_URL=$API_URL API_KEY=$API_KEY \
--authorize true \
--query "id" -o tsv)
echo"Created variable group with ID: $VG_ID"elseecho"Variable group already exists with ID: $VG_ID"fi
# Create PR with work items and reviewers
PR_ID=$(az repos pr create \
--repository "$REPO_NAME" \
--source-branch "$FEATURE_BRANCH" \
--target-branch main \
--title "Feature: $(git log -1 --pretty=%B)" \
--description "$(git log -1 --pretty=%B)" \
--work-items $WORK_ITEM_1$WORK_ITEM_2 \
--reviewers "$REVIEWER_1""$REVIEWER_2" \
--required-reviewers "$LEAD_EMAIL" \
--labels "enhancement""backlog" \
--open \
--query "pullRequestId" -o tsv)
# Set auto-complete when policies pass
az repos pr update --id$PR_ID --auto-complete true
Error Handling and Retry Patterns
Retry Logic for Transient Failures
# Retry function for network operationsretry_command() {
local max_attempts=3
local attempt=1
local delay=5
while [[ $attempt -le $max_attempts ]]; doif"$@"; thenreturn 0
fiecho"Attempt $attempt failed. Retrying in ${delay}s..."sleep$delay
((attempt++))
delay=$((delay * 2))
doneecho"All $max_attempts attempts failed"return 1
}
# Usage
retry_command az pipelines run --name "$PIPELINE_NAME"
Check and Handle Errors
# Check if pipeline exists before operations
PIPELINE_ID=$(az pipelines list --query "[?name=='$PIPELINE_NAME'].id" -o tsv)
if [[ -z "$PIPELINE_ID" ]]; thenecho"Pipeline not found. Creating..."
az pipelines create --name "$PIPELINE_NAME" --yaml-path azure-pipelines.yml
elseecho"Pipeline exists with ID: $PIPELINE_ID"fi
Validate Inputs
# Validate required parametersif [[ -z "$PROJECT" || -z "$REPO" ]]; thenecho"Error: PROJECT and REPO must be set"exit 1
fi# Check if branch existsif ! az repos ref list --repository "$REPO" --query "[?name=='refs/heads/$BRANCH']" -o tsv | grep -q .; thenecho"Error: Branch $BRANCH does not exist"exit 1
fi
# Run pipeline and check result
RUN_ID=$(az pipelines run --name "$PIPELINE_NAME" --query "id" -o tsv)
# Wait for completionwhiletrue; do
STATUS=$(az pipelines runs show --run-id $RUN_ID --query "status" -o tsv)
if [[ "$STATUS" != "inProgress" && "$STATUS" != "notStarted" ]]; thenbreakfisleep 10
done# Check result and create work item on failure
RESULT=$(az pipelines runs show --run-id $RUN_ID --query "result" -o tsv)
if [[ "$RESULT" != "succeeded" ]]; then
BUILD_NUMBER=$(az pipelines runs show --run-id $RUN_ID --query "buildNumber" -o tsv)
az boards work-item create \
--title "Build $BUILD_NUMBER failed" \
--type Bug \
--description "Pipeline run $RUN_ID failed with result: $RESULT\n\nURL: $ORG_URL/$PROJECT/_build/results?buildId=$RUN_ID"fi
Graceful Degradation
# Try to download artifact, fallback to alternative sourceif ! az pipelines runs artifact download \
--artifact-name 'webapp' \
--path ./output \
--run-id $RUN_ID 2>/dev/null; thenecho"Warning: Failed to download from pipeline run. Falling back to backup source..."# Alternative download method
curl -L "$BACKUP_URL" -o ./output/backup.zip
fi
Advanced JMESPath Queries
Filtering and Sorting
# Filter by multiple conditions
az pipelines list --query "[?name.contains('CI') && enabled==true]"# Filter by status and result
az pipelines runs list --query "[?status=='completed' && result=='succeeded']"# Sort by date (descending)
az pipelines runs list --query "sort_by([?status=='completed'], &finishTime | reverse(@))"# Get top N items after filtering
az pipelines runs list --query "[?result=='succeeded'] | [0:5]"
Nested Queries
# Extract nested properties
az pipelines show --id$PIPELINE_ID --query "{Name:name, Repo:repository.{Name:name, Type:type}, Folder:folder}"# Query build details
az pipelines build show --id$BUILD_ID --query "{ID:id, Number:buildNumber, Status:status, Result:result, Requested:requestedFor.displayName}"
Complex Filtering
# Find pipelines with specific YAML path
az pipelines list --query "[?process.type.name=='yaml' && process.yamlFilename=='azure-pipelines.yml']"# Find PRs from specific reviewer
az repos pr list --query "[?contains(reviewers[?displayName=='John Doe'].displayName, 'John Doe')]"# Find work items with specific iteration and state
az boards work-item show --id$WI_ID --query "{Title:fields['System.Title'], State:fields['System.State'], Iteration:fields['System.IterationPath']}"
Aggregation
# Count items by status
az pipelines runs list --query "groupBy([?status=='completed'], &[result]) | {Succeeded: [?key=='succeeded'][0].count, Failed: [?key=='failed'][0].count}"# Get unique reviewers
az repos pr list --query "unique_by(reviewers[], &displayName)"# Sum values
az pipelines runs list --query "[?result=='succeeded'] | [].{Duration:duration} | [0].Duration"
Conditional Transformation
# Format dates
az pipelines runs list --query "[].{ID:id, Date:createdDate, Formatted:createdDate | format_datetime(@, 'yyyy-MM-dd HH:mm')}"# Conditional output
az pipelines list --query "[].{Name:name, Status:(enabled ? 'Enabled' : 'Disabled')}"# Extract with defaults
az pipelines show --id$PIPELINE_ID --query "{Name:name, Folder:folder || 'Root', Description:description || 'No description'}"
Complex Workflows
# Find longest running builds
az pipelines build list --query "sort_by([?result=='succeeded'], &queueTime) | reverse(@) | [0:3].{ID:id, Number:buildNumber, Duration:duration}"# Get PR statistics per reviewer
az repos pr list --query "groupBy([], &reviewers[].displayName) | [].{Reviewer:@.key, Count:length(@)}"# Find work items with multiple child items
az boards work-item relation list --id$PARENT_ID --query "[?rel=='System.LinkTypes.Hierarchy-Forward'] | [].{ChildID:url | split('/', @) | [-1]}"
Scripting Patterns for Idempotent Operations
Create or Update Pattern
# Ensure pipeline exists, update if differentensure_pipeline() {
local name=$1local yaml_path=$2
PIPELINE=$(az pipelines list --query "[?name=='$name']" -o json)
if [[ -z "$PIPELINE" ]]; thenecho"Creating pipeline: $name"
az pipelines create --name "$name" --yaml-path "$yaml_path"elseecho"Pipeline exists: $name"fi
}
Ensure Variable Group
# Create variable group with idempotent updatesensure_variable_group() {
local vg_name=$1shiftlocal variables=("$@")
VG_ID=$(az pipelines variable-group list --query "[?name=='$vg_name'].id" -o tsv)
if [[ -z "$VG_ID" ]]; thenecho"Creating variable group: $vg_name"
VG_ID=$(az pipelines variable-group create \
--name "$vg_name" \
--variables "${variables[@]}" \
--authorize true \
--query "id" -o tsv)
elseecho"Variable group exists: $vg_name (ID: $VG_ID)"fiecho"$VG_ID"
}
Ensure Service Connection
# Check if service connection exists, create if notensure_service_connection() {
local name=$1local project=$2
SC_ID=$(az devops service-endpoint list \
--project "$project" \
--query "[?name=='$name'].id" \
-o tsv)
if [[ -z "$SC_ID" ]]; thenecho"Service connection not found. Creating..."# Create logic hereelseecho"Service connection exists: $name"echo"$SC_ID"fi
}
Idempotent Work Item Creation
# Create work item only if doesn't exist with same titlecreate_work_item_if_new() {
local title=$1localtype=$2
WI_ID=$(az boards query \
--wiql "SELECT ID FROM WorkItems WHERE [System.WorkItemType]='$type' AND [System.Title]='$title'" \
--query "[0].id" -o tsv)
if [[ -z "$WI_ID" ]]; thenecho"Creating work item: $title"
WI_ID=$(az boards work-item create --title "$title" --type"$type" --query "id" -o tsv)
elseecho"Work item exists: $title (ID: $WI_ID)"fiecho"$WI_ID"
}
Bulk Idempotent Operations
# Ensure multiple pipelines existdeclare -a PIPELINES=(
"ci-pipeline:azure-pipelines.yml""deploy-pipeline:deploy.yml""test-pipeline:test.yml"
)
for pipeline in"${PIPELINES[@]}"; do
IFS=':'read -r name yaml <<< "$pipeline"
ensure_pipeline "$name""$yaml"done
Configuration Synchronization
# Sync variable groups from config filesync_variable_groups() {
local config_file=$1while IFS=','read -r vg_name variables; do
ensure_variable_group "$vg_name""$variables"done < "$config_file"
}
# config.csv format:# prod-vars,API_URL=prod.com,API_KEY=secret123# dev-vars,API_URL=dev.com,API_KEY=secret456
# Create PR from feature branch with automationcreate_automated_pr() {
local branch=$1local title=$2# Get branch info
LAST_COMMIT=$(git log -1 --pretty=%B "$branch")
COMMIT_SHA=$(git rev-parse "$branch")
# Find related work items
WORK_ITEMS=$(az boards query \
--wiql "SELECT ID FROM WorkItems WHERE [System.ChangedBy] = @Me AND [System.State] = 'Active'" \
--query "[].id" -o tsv)
# Create PR
PR_ID=$(az repos pr create \
--source-branch "$branch" \
--target-branch main \
--title "$title" \
--description "$LAST_COMMIT" \
--work-items $WORK_ITEMS \
--auto-complete true \
--query "pullRequestId" -o tsv)
# Set required reviewers
az repos pr reviewer add \
--id$PR_ID \
--reviewers $(git log -1 --pretty=format:'%ae'"$branch") \
--required trueecho"Created PR #$PR_ID"
}
Pipeline Monitoring and Alerting
# Monitor pipeline and alert on failuremonitor_pipeline() {
local pipeline_name=$1local slack_webhook=$2whiletrue; do# Get latest run
RUN_ID=$(az pipelines list --query "[?name=='$pipeline_name'] | [0].id" -o tsv)
RUNS=$(az pipelines runs list --pipeline $RUN_ID --top 1)
LATEST_RUN_ID=$(echo"$RUNS" | jq -r '.[0].id')
RESULT=$(echo"$RUNS" | jq -r '.[0].result')
# Check if failed and not already processedif [[ "$RESULT" == "failed" ]]; then# Send Slack alert
curl -X POST "$slack_webhook" \
-H 'Content-Type: application/json' \
-d "{\"text\": \"Pipeline $pipeline_name failed! Run ID: $LATEST_RUN_ID\"}"fisleep 300 # Check every 5 minutesdone
}
Bulk Work Item Management
# Bulk update work items based on querybulk_update_work_items() {
local wiql=$1local updates=("$@")
# Query work items
WI_IDS=$(az boards query --wiql "$wiql" --query "[].id" -o tsv)
# Update each work itemfor wi_id in$WI_IDS; do
az boards work-item update --id$wi_id"${updates[@]}"echo"Updated work item: $wi_id"done
}
# Usage: bulk_update_work_items "SELECT ID FROM WorkItems WHERE State='New'" --state "Active" --assigned-to "user@example.com"
Branch Policy Automation
# Apply branch policies to all repositoriesapply_branch_policies() {
local branch=$1local project=$2# Get all repositories
REPOS=$(az repos list --project "$project" --query "[].id" -o tsv)
for repo_id in$REPOS; doecho"Applying policies to repo: $repo_id"# Require minimum approvers
az repos policy approver-count create \
--blocking true \
--enabled true \
--branch "$branch" \
--repository-id "$repo_id" \
--minimum-approver-count 2 \
--creator-vote-counts true# Require work item linking
az repos policy work-item-linking create \
--blocking true \
--branch "$branch" \
--enabled true \
--repository-id "$repo_id"# Require build validation
BUILD_ID=$(az pipelines list --query "[?name=='CI'].id" -o tsv | head -1)
az repos policy build create \
--blocking true \
--enabled true \
--branch "$branch" \
--repository-id "$repo_id" \
--build-definition-id "$BUILD_ID" \
--queue-on-source-update-only truedone
}
Multi-Environment Deployment
# Deploy across multiple environmentsdeploy_to_environments() {
local run_id=$1shiftlocal environments=("$@")
# Download artifacts
ARTIFACT_NAME=$(az pipelines runs artifact list --run-id $run_id --query "[0].name" -o tsv)
az pipelines runs artifact download \
--artifact-name "$ARTIFACT_NAME" \
--path ./artifacts \
--run-id $run_id# Deploy to each environmentforenvin"${environments[@]}"; doecho"Deploying to: $env"# Get environment-specific variables
VG_ID=$(az pipelines variable-group list --query "[?name=='$env-vars'].id" -o tsv)
# Run deployment pipeline
DEPLOY_RUN_ID=$(az pipelines run \
--name "Deploy-$env" \
--variables ARTIFACT_PATH=./artifacts ENV="$env" \
--query "id" -o tsv)
# Wait for deploymentwhiletrue; do
STATUS=$(az pipelines runs show --run-id $DEPLOY_RUN_ID --query "status" -o tsv)
if [[ "$STATUS" != "inProgress" ]]; thenbreakfisleep 10
donedone
}
Enhanced Global Arguments
Parameter
Description
--help / -h
Show command help
--output / -o
Output format (json, jsonc, none, table, tsv, yaml, yamlc)
# General help
az devops --help# Help for specific command group
az pipelines --help
az repos pr --help# Help for specific command
az repos pr create --help# Search for examples
az find "az repos pr create"