Files
claude-config/skills/azure-devops-pipelines/SKILL.md
Yaojia Wang 2876cca8fe chore: initial backup of Claude Code configuration
Includes: CLAUDE.md, settings.json, agents, commands, rules, skills,
hooks, contexts, evals, get-shit-done, plugin configs (installed list
and marketplace sources). Excludes credentials, runtime caches,
telemetry, session data, and plugin binary cache.
2026-03-24 22:26:05 +01:00

19 KiB

name, description
name description
azure-devops-pipelines Manage Azure DevOps build pipelines, release pipelines, pipeline runs, deployments, and pull requests via Azure CLI. Trigger builds, create releases, approve/vote on PRs, merge PRs, manage reviewers, monitor status, and manage artifacts.

Azure DevOps Pipelines

Prerequisites

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

# Auth: interactive login
az login

# Auth: PAT-based login
az devops login --organization https://dev.azure.com/ORG
# Then paste your PAT when prompted

# Set defaults (avoids passing --org and --project every time)
az devops configure --defaults organization=https://dev.azure.com/ORG project=PROJECT

Common Flags

Every command below supports these global flags. Omitted from examples for brevity:

Flag Purpose
--org URL Override default organization
--project NAME Override default project
--detect false Disable auto-detection from git remote (recommended in scripts)
--output table Human-readable output
--output json Machine-readable output
--query JMESPATH Filter JSON output

1. YAML Pipelines (Modern)

Run a pipeline

# By name
az pipelines run --name "MyPipeline"

# By ID
az pipelines run --id 42

# With branch
az pipelines run --name "MyPipeline" --branch refs/heads/feature/xyz

# With variables
az pipelines run --name "MyPipeline" --variables "env=staging" "debug=true"

# With parameters (template parameters)
az pipelines run --name "MyPipeline" --parameters "image=ubuntu-latest" "pool=MyPool"

# With commit
az pipelines run --name "MyPipeline" --commit-id abc123def

# Open in browser after queuing
az pipelines run --name "MyPipeline" --open

List pipelines

# All pipelines
az pipelines list --output table

# Filter by name (supports wildcards)
az pipelines list --name "Deploy*" --output table

# Filter by folder
az pipelines list --folder-path "production" --top 20

# Get pipeline IDs only
az pipelines list --query "[].{ID:id, Name:name}" --output table

Show pipeline details

az pipelines show --id 42
az pipelines show --name "MyPipeline" --open

Create / Update / Delete pipeline

# Create from YAML in Azure Repos
az pipelines create --name "NewPipeline" \
  --repository RepoName --branch master \
  --repository-type tfsgit \
  --yaml-path azure-pipelines.yml

# Create from GitHub
az pipelines create --name "NewPipeline" \
  --repository Owner/Repo --branch main \
  --repository-type github \
  --service-connection SERVICE_CONN_ID \
  --yaml-path .azure/pipelines.yml

# Skip first run on create
az pipelines create --name "NewPipeline" \
  --repository RepoName --branch main \
  --repository-type tfsgit \
  --yaml-path azure-pipelines.yml \
  --skip-first-run true

# Update pipeline
az pipelines update --id 42 --new-name "RenamedPipeline"
az pipelines update --id 42 --yaml-path new-pipeline.yml --branch main
az pipelines update --id 42 --new-folder-path "team/production"

# Delete pipeline
az pipelines delete --id 42 --yes

2. Classic Builds

Queue a build

# By definition ID
az pipelines build queue --definition-id 10

# By definition name
az pipelines build queue --definition-name "LegacyBuild"

# With branch and variables
az pipelines build queue --definition-id 10 \
  --branch refs/heads/release/1.0 \
  --variables "config=Release" "deploy=true"

# Open results in browser
az pipelines build queue --definition-id 10 --open

List builds

# Recent builds
az pipelines build list --top 10 --output table

# Filter by definition
az pipelines build list --definition-ids 10 20 --top 5

# Filter by status
az pipelines build list --status inProgress --output table
az pipelines build list --status completed --result failed --top 10

# Filter by branch
az pipelines build list --branch refs/heads/main --top 5

# Filter by reason
az pipelines build list --reason pullRequest --top 10

# Useful JMESPath queries
az pipelines build list --top 5 \
  --query "[].{ID:id, Status:status, Result:result, Pipeline:definition.name}" \
  --output table

Show build details

az pipelines build show --id 1234
az pipelines build show --id 1234 --open

Cancel a build

az pipelines build cancel --build-id 1234

Build definitions

# List all build definitions
az pipelines build definition list --output table
az pipelines build definition list --query "[].{ID:id, Name:name, Path:path}" --output table

# Show definition details
az pipelines build definition show --id 10
az pipelines build definition show --name "MyBuildDef" --open

Build tags

# Add tags
az pipelines build tag add --build-id 1234 --tags "production" "v1.0"

# List tags
az pipelines build tag list --build-id 1234

# Delete a tag
az pipelines build tag delete --build-id 1234 --tag "v1.0"

3. Release Pipelines

Create a release

# By definition ID
az pipelines release create --definition-id 5

# By definition name
az pipelines release create --definition-name "MyRelease"

# With description
az pipelines release create --definition-id 5 \
  --description "Release v1.2.3 - hotfix for login bug"

# With artifact version
az pipelines release create --definition-id 5 \
  --artifact-metadata-list "alias1=version_id1" "alias2=version_id2"

# Open in browser
az pipelines release create --definition-id 5 --open

List releases

# Recent releases
az pipelines release list --top 10 --output table

# Filter by definition
az pipelines release list --definition-id 5 --top 10

# Filter by status
az pipelines release list --status active --top 10

# Filter by branch
az pipelines release list --source-branch refs/heads/main

# Filter by time range
az pipelines release list --min-created-time "2025-01-01" --max-created-time "2025-02-01"

# Useful JMESPath queries
az pipelines release list --top 5 \
  --query "[].{ID:id, Name:name, Status:status, CreatedOn:createdOn}" \
  --output table

Show release details

az pipelines release show --id 100
az pipelines release show --id 100 --open

Release definitions

# List all release definitions
az pipelines release definition list --output table
az pipelines release definition list --name "Deploy*" --top 10

# Filter by artifact type
az pipelines release definition list --artifact-type build

# Show definition details
az pipelines release definition show --id 5
az pipelines release definition show --name "MyRelease" --open

# Get environments from a release definition
az pipelines release definition show --id 5 \
  --query "environments[].{ID:id, Name:name, Rank:rank}"

4. Pipeline Runs

List runs

# Recent runs
az pipelines runs list --top 10 --output table

# Filter by pipeline
az pipelines runs list --pipeline-ids 42 --top 5

# Multiple pipelines
az pipelines runs list --pipeline-ids 42 43 44 --top 10

# Filter by status and result
az pipelines runs list --status completed --result succeeded --top 10
az pipelines runs list --status inProgress --output table

# Order by time
az pipelines runs list --query-order FinishTimeDesc --top 10

# Useful JMESPath
az pipelines runs list --top 5 \
  --query "[].{ID:id, Pipeline:pipeline.name, Status:status, Result:result}" \
  --output table

Show run details

az pipelines runs show --id 5678
az pipelines runs show --id 5678 --open

Run artifacts

# List artifacts for a run
az pipelines runs artifact list --run-id 5678

# Download an artifact
az pipelines runs artifact download --run-id 5678 \
  --artifact-name "drop" --path ./artifacts

# Upload an artifact
az pipelines runs artifact upload --run-id 5678 \
  --artifact-name "test-results" --path ./test-output

Run tags

az pipelines runs tag add --run-id 5678 --tags "deployed" "v2.0"
az pipelines runs tag list --run-id 5678
az pipelines runs tag delete --run-id 5678 --tag "deployed"

5. Variables & Variable Groups

Pipeline variables

# List variables for a pipeline
az pipelines variable list --pipeline-id 42 --output table

# Create a variable
az pipelines variable create --pipeline-id 42 \
  --name "MY_VAR" --value "my_value"

# Create a secret variable
az pipelines variable create --pipeline-id 42 \
  --name "MY_SECRET" --value "s3cret" --is-secret true

# Update a variable
az pipelines variable update --pipeline-id 42 \
  --name "MY_VAR" --new-value "updated_value"

# Delete a variable
az pipelines variable delete --pipeline-id 42 --name "MY_VAR" --yes

Variable groups

# List variable groups
az pipelines variable-group list --output table

# Create a variable group
az pipelines variable-group create --name "MyVarGroup" \
  --variables "key1=val1" "key2=val2"

# Show variable group
az pipelines variable-group show --id 1
az pipelines variable-group show --group-name "MyVarGroup"

# Update variable group
az pipelines variable-group update --id 1 --name "RenamedGroup"

# Delete variable group
az pipelines variable-group delete --id 1 --yes

# Manage variables within a group
az pipelines variable-group variable list --group-id 1 --output table
az pipelines variable-group variable create --group-id 1 --name "NEW_VAR" --value "val"
az pipelines variable-group variable update --group-id 1 --name "NEW_VAR" --new-value "val2"
az pipelines variable-group variable delete --group-id 1 --name "NEW_VAR" --yes

6. Agent Pools & Queues

# List agent pools
az pipelines pool list --output table
az pipelines pool show --id 1

# List agents in a pool
az pipelines agent list --pool-id 1 --output table
az pipelines agent show --pool-id 1 --agent-id 5

# List agent queues
az pipelines queue list --output table
az pipelines queue show --id 1

7. Pipeline Folders

# List folders
az pipelines folder list --output table

# Create a folder
az pipelines folder create --path "team/production"

# Update folder
az pipelines folder update --path "team/production" --new-path "team/prod"

# Delete folder
az pipelines folder delete --path "team/prod" --yes

8. Advanced: REST API via az devops invoke

For operations not directly supported by the CLI, use az devops invoke.

Approve a release deployment

# Step 1: Get pending approvals
az devops invoke --area release --resource approvals \
  --route-parameters project=PROJECT \
  --query-parameters releaseId=RELEASE_ID \
  --api-version 7.1 --http-method GET

# Step 2: Approve (PATCH)
az devops invoke --area release --resource approvals \
  --route-parameters project=PROJECT approvalId=APPROVAL_ID \
  --api-version 7.1 --http-method PATCH \
  --in-file approval-body.json

Where approval-body.json:

{
  "status": "approved",
  "comments": "Approved via CLI"
}

Deploy to a specific environment

# Trigger deployment of a release to an environment
az devops invoke --area release --resource releases \
  --route-parameters project=PROJECT releaseId=RELEASE_ID \
  --resource-sub-type environments --resource-id ENV_ID \
  --api-version 7.1 --http-method PATCH \
  --in-file deploy-body.json

Where deploy-body.json:

{
  "status": "inProgress",
  "comment": "Deploying via CLI"
}

Get build timeline / logs

# Get build timeline (stages, jobs, tasks)
az devops invoke --area build --resource timeline \
  --route-parameters project=PROJECT buildId=BUILD_ID \
  --api-version 7.1 --http-method GET

# Get build logs
az devops invoke --area build --resource logs \
  --route-parameters project=PROJECT buildId=BUILD_ID \
  --api-version 7.1 --http-method GET

Check run approvals (YAML pipeline environments)

# List checks for a pipeline run
az devops invoke --area pipelines --resource runs \
  --route-parameters project=PROJECT pipelineId=PIPELINE_ID runId=RUN_ID \
  --api-version 7.1 --http-method GET

9. Composite Workflows

Build then release

# 1. Queue a build and capture the build ID
BUILD_JSON=$(az pipelines build queue --definition-id 10 --output json)
BUILD_ID=$(echo "$BUILD_JSON" | jq -r '.id')
echo "Build queued: $BUILD_ID"

# 2. Poll until complete
while true; do
  STATUS=$(az pipelines build show --id "$BUILD_ID" \
    --query "status" --output tsv)
  RESULT=$(az pipelines build show --id "$BUILD_ID" \
    --query "result" --output tsv)
  echo "Build $BUILD_ID: status=$STATUS result=$RESULT"
  if [ "$STATUS" = "completed" ]; then break; fi
  sleep 30
done

# 3. Check result
if [ "$RESULT" != "succeeded" ]; then
  echo "Build failed with result: $RESULT"
  exit 1
fi

# 4. Create release
az pipelines release create --definition-id 5 \
  --description "Auto-release from build $BUILD_ID"

Run YAML pipeline and wait

# 1. Run pipeline and capture run ID
RUN_JSON=$(az pipelines run --id 42 --branch refs/heads/main --output json)
RUN_ID=$(echo "$RUN_JSON" | jq -r '.id')
echo "Pipeline run queued: $RUN_ID"

# 2. Poll until complete
while true; do
  STATE=$(az pipelines runs show --id "$RUN_ID" \
    --query "state" --output tsv)
  RESULT=$(az pipelines runs show --id "$RUN_ID" \
    --query "result" --output tsv)
  echo "Run $RUN_ID: state=$STATE result=$RESULT"
  if [ "$STATE" = "completed" ]; then break; fi
  sleep 30
done

# 3. Download artifacts on success
if [ "$RESULT" = "succeeded" ]; then
  az pipelines runs artifact download --run-id "$RUN_ID" \
    --artifact-name "drop" --path ./artifacts
fi

List failed builds across multiple pipelines

az pipelines build list \
  --definition-ids 10 20 30 \
  --result failed \
  --top 20 \
  --query "[].{ID:id, Pipeline:definition.name, Branch:sourceBranch, Time:finishTime}" \
  --output table

Find latest successful build for a branch

az pipelines build list \
  --definition-ids 10 \
  --branch refs/heads/main \
  --result succeeded \
  --top 1 \
  --query "[0].{ID:id, BuildNumber:buildNumber, Time:finishTime}" \
  --output table

Release status dashboard

# Show recent releases with environment statuses
az pipelines release list --definition-id 5 --top 5 \
  --query "[].{ID:id, Name:name, Status:status, Envs:environments[].{Name:name,Status:status}}" \
  --output json | jq '.'

10. Pull Request Management

PR 操作用 az repos pr 命令,完全原生支持,无需 REST API。

Approve / Vote on a PR

# Approve
az repos pr set-vote --id 123 --vote approve

# Approve with suggestions
az repos pr set-vote --id 123 --vote approve-with-suggestions

# Reject
az repos pr set-vote --id 123 --vote reject

# Wait for author
az repos pr set-vote --id 123 --vote wait-for-author

# Reset vote
az repos pr set-vote --id 123 --vote reset

Create a PR

# Basic
az repos pr create --title "feat: add login page" \
  --source-branch feature/login --target-branch main

# With description and reviewers
az repos pr create \
  --title "feat: add login page" \
  --description "Implements OAuth2 login flow" "See JIRA-123" \
  --source-branch feature/login \
  --target-branch main \
  --required-reviewers "user@company.com" "team@company.com" \
  --reviewers "optional@company.com"

# With auto-complete and squash merge
az repos pr create \
  --title "feat: add login page" \
  --source-branch feature/login \
  --target-branch main \
  --auto-complete true \
  --squash true \
  --delete-source-branch true

# Create as draft
az repos pr create --title "WIP: new feature" \
  --source-branch feature/xyz --draft true

# Open in browser after creation
az repos pr create --title "My PR" \
  --source-branch feature/xyz --open

List PRs

# All active PRs
az repos pr list --status active --output table

# PRs targeting main
az repos pr list --target-branch main --output table

# PRs created by me
az repos pr list --creator "me@company.com" --output table

# PRs where I'm a reviewer
az repos pr list --reviewer "me@company.com" --output table

# From a specific branch
az repos pr list --source-branch feature/login

# Completed/merged PRs
az repos pr list --status completed --top 10 --output table

# All PRs (active + completed + abandoned)
az repos pr list --status all --top 20 \
  --query "[].{ID:pullRequestId, Title:title, Status:status, Author:createdBy.displayName}" \
  --output table

Show PR details

az repos pr show --id 123
az repos pr show --id 123 --open

Update a PR

# Merge/complete a PR
az repos pr update --id 123 --status completed

# Abandon a PR
az repos pr update --id 123 --status abandoned

# Reactivate an abandoned PR
az repos pr update --id 123 --status active

# Rename title
az repos pr update --id 123 --title "fix: corrected login flow"

# Update description
az repos pr update --id 123 --description "Updated description" "Second line"

# Enable auto-complete
az repos pr update --id 123 --auto-complete true

# Publish draft PR
az repos pr update --id 123 --draft false

# Convert to draft
az repos pr update --id 123 --draft true

# Bypass policies and force complete (use with caution)
az repos pr update --id 123 --status completed \
  --bypass-policy true --bypass-policy-reason "Emergency hotfix"

Manage reviewers

# Add reviewers
az repos pr reviewer add --id 123 --reviewers "user1@company.com" "user2@company.com"

# List reviewers
az repos pr reviewer list --id 123 --output table

# Remove a reviewer
az repos pr reviewer remove --id 123 --reviewers "user1@company.com"

Manage policies

# List policies on a PR
az repos pr policy list --id 123 --output table

# Re-queue a failed policy check
az repos pr policy queue --id 123 --evaluation-id EVAL_ID

Work items

# Link work items to a PR
az repos pr work-item add --id 123 --work-items 456 789

# List linked work items
az repos pr work-item list --id 123 --output table

# Unlink work items
az repos pr work-item remove --id 123 --work-items 456

Checkout PR branch locally

az repos pr checkout --id 123

Composite: Create PR and wait for approval

# 1. Create PR
PR_JSON=$(az repos pr create \
  --title "feat: new feature" \
  --source-branch feature/xyz \
  --target-branch main \
  --output json)
PR_ID=$(echo "$PR_JSON" | jq -r '.pullRequestId')
echo "PR created: $PR_ID"

# 2. Poll until completed or abandoned
while true; do
  STATUS=$(az repos pr show --id "$PR_ID" --query "status" --output tsv)
  echo "PR $PR_ID status: $STATUS"
  if [ "$STATUS" = "completed" ] || [ "$STATUS" = "abandoned" ]; then
    break
  fi
  sleep 60
done

11. Useful JMESPath Patterns

# Get only IDs
--query "[].id" --output tsv

# ID + Name table
--query "[].{ID:id, Name:name}" --output table

# Filter in query (e.g., only inProgress)
--query "[?status=='inProgress'].{ID:id, Name:name}" --output table

# Nested: release environments
--query "environments[].{Env:name, Status:status}" --output table

# First item only
--query "[0].id" --output tsv

# Sort by field
--query "sort_by([],&finishTime)" --output json