cheat sheet
az
Cross-platform command-line interface for managing Azure resources, running ARM-based and data-plane operations from a terminal or pipeline.
az — Azure CLI
What it is
az is Microsoft's official command-line tool for managing Azure resources. It is a Python application maintained at Azure/azure-cli (current stable: 2.87.0, released June 2026) that wraps the Azure Resource Manager REST API plus a long list of data-plane services (Storage, Key Vault, Container Registry, Batch, etc.). Reach for it when you want a single uniform interface for shell scripts, CI pipelines, and ad-hoc cloud operations — alternatives are Azure PowerShell (Az modules), the Azure Portal, Terraform, and Bicep, but az is the lightest-weight and most universally available.
Install
az ships as native packages on every major OS, as a tarball, and via pip/conda. Microsoft maintains an apt repo for Debian/Ubuntu and a dnf/yum repo for RHEL/Fedora; the official one-line installer is the fastest path on Linux.
# Debian/Ubuntu — official Microsoft repo
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
# RHEL / Fedora / Rocky / Alma
sudo dnf install -y azure-cli
# macOS
brew update && brew install azure-cli
# Windows (PowerShell, run as admin)
winget install --exact --id Microsoft.AzureCLI
# Cross-platform via pip (inside a venv)
python3 -m pip install --user azure-cli
# Verify
az version
Output:
{
"azure-cli": "2.87.0",
"azure-cli-core": "2.87.0",
"azure-cli-telemetry": "1.1.0",
"extensions": {}
}
Syntax
Every az invocation follows a verb-noun command group structure. The first positional token after az is a command group (a service like vm, storage, network), followed by a sub-group or action, then flags.
az <command-group> [<sub-group>] <action> [--global-flags] [--command-flags]
Output: (none — exits 0 on success)
A few concrete shapes:
az login
az account show
az group create --name MyResourceGroup --location westus2
az vm list --resource-group MyResourceGroup --output table
az storage blob upload --account-name alicedev01 --container-name data --name report.csv --file ./report.csv
Output: (none — see per-command sections below)
Essential options
| Option | Meaning |
|---|---|
--help / -h | Print help for the current command group or command. az vm --help lists every sub-command. |
--output / -o | Output format: json (default), jsonc, yaml, yamlc, table, tsv, none. |
--query | JMESPath expression filtering the response — runs locally after the API call. |
--subscription | Override the active subscription for one command. Takes a name or GUID. |
--resource-group / -g | Target resource group. With defaults.group set, you can omit it. |
--location / -l | Azure region (e.g. westus2, eastus, northeurope). |
--verbose | INFO-level logging to stderr. |
--debug | DEBUG-level logging including HTTP request/response (useful for failures). |
--only-show-errors | Suppress warnings (preview/deprecation banners). Good for CI. |
--no-wait | Return immediately for long-running operations rather than polling. |
--yes / -y | Skip confirmation prompts. |
Configuration
az reads settings from three layers — command-line flags, environment variables, and an INI config file — in that precedence order. The config file path is $AZURE_CONFIG_DIR/config (defaults to ~/.azure/config on Linux/macOS and %USERPROFILE%\.azure\config on Windows). Reach for the file (or az config set) when you want a setting to persist across shells; reach for environment variables when scripting CI; reach for flags for one-off overrides.
File locations
| OS | Path | Notes |
|---|---|---|
| Linux | $AZURE_CONFIG_DIR/config (defaults to ~/.azure/config) | Per-user only; system-wide configs are not supported. Tokens and contexts live alongside in the same directory. |
| macOS | ~/.azure/config (same default — not the App Support directory) | Identical to Linux. |
| Windows | %USERPROFILE%\.azure\config (e.g. C:\Users\Alice Dev\.azure\config) | Roaming-profile path. Same INI format as Linux/macOS. |
Loading precedence (highest to lowest):
- Command-line parameters (
--output table,--subscription …) - Environment variables (
AZURE_CORE_OUTPUT=table,AZURE_DEFAULTS_GROUP=…) - Values written to
$AZURE_CONFIG_DIR/configbyaz config setoraz init - Built-in defaults
Options reference — every option is exposed both in the INI file ([section] → key) and as an environment variable named AZURE_{SECTION}_{KEY} (all uppercase). For example, [core] output = table is equivalent to AZURE_CORE_OUTPUT=table.
Core
| Option | Type | Default | Possible values | Description |
|---|---|---|---|---|
core.output | enum | json | json | jsonc | yaml | yamlc | table | tsv | none | Default output format when --output is not passed. |
core.disable_confirm_prompt | bool | false | true | false | Skip all confirmation prompts (Are you sure?). |
core.collect_telemetry | bool | true | true | false | Send anonymous usage telemetry to Microsoft. |
core.only_show_errors | bool | false | true | false | Suppress preview/deprecation warnings on stderr. |
core.no_color | bool | false | true | false | Disable ANSI color in stdout/stderr. |
core.enable_broker_on_windows | bool | true | true | false | Use Web Account Manager (WAM) for az login on Windows. |
core.login_experience_v2 | bool | true | true | false | Show the multi-subscription picker after az login. |
core.display_region_identified | bool | true | true | false | Show region-recommendation message when CLI detects a closer region. |
core.survey_message | enum | yes | yes | no | Show the periodic CLI satisfaction survey banner. |
Logging
| Option | Type | Default | Possible values | Description |
|---|---|---|---|---|
logging.enable_log_file | bool | false | true | false | Write a rolling log file in addition to stderr. |
logging.log_dir | string | ${AZURE_CONFIG_DIR}/logs | any writable directory | Directory for log files when enable_log_file=true. |
Defaults (implicit arguments)
| Option | Type | Default | Possible values | Description |
|---|---|---|---|---|
defaults.group | string | "" | any RG name | Resource group used when -g is omitted. |
defaults.location | string | "" | any Azure region | Location used when -l is omitted (e.g. westus2). |
defaults.web | string | "" | any web app name | Default app for az webapp commands. |
defaults.vm | string | "" | any VM name | Default VM for az vm commands. |
defaults.vmss | string | "" | any VMSS name | Default scale set for az vmss commands. |
defaults.acr | string | "" | any registry name | Default container registry for az acr commands. |
Storage data-plane
| Option | Type | Default | Possible values | Description |
|---|---|---|---|---|
storage.account | string | "" | storage account name | Default account for az storage data-plane commands. |
storage.key | string | "" | account key | Default access key (avoid — prefer RBAC). |
storage.sas_token | string | "" | SAS token | Default SAS token for data-plane calls. |
storage.connection_string | string | "" | connection string | Default connection string used in place of account+key. |
Cloud
| Option | Type | Default | Possible values | Description |
|---|---|---|---|---|
cloud.name | enum | AzureCloud | AzureCloud | AzureChinaCloud | AzureUSGovernment | Active sovereign cloud. Switch with az cloud set --name. |
Batch
| Option | Type | Default | Possible values | Description |
|---|---|---|---|---|
batch.account | string | "" | account name | Default Batch account. |
batch.access_key | string | "" | shared key | Default access key (used with auth_mode=shared_key). |
batch.endpoint | string | "" | URL | Default Batch endpoint. |
batch.auth_mode | enum | shared_key | shared_key | aad | Authentication mode for az batch commands. |
Extension
| Option | Type | Default | Possible values | Description |
|---|---|---|---|---|
extension.use_dynamic_install | enum | no | no | yes_prompt | yes_without_prompt | Install missing extensions on demand. |
extension.run_after_dynamic_install | bool | false | true | false | Run the original command after a dynamic install completes. |
extension.index_url | string | "" | URL | Private extension index URL (overrides the public one). |
Example config — a realistic file for a developer working in a single subscription and region:
# ~/.azure/config
[core]
output = table
collect_telemetry = no
only_show_errors = yes
no_color = no
[logging]
enable_log_file = yes
log_dir = /home/alice/.azure/logs
[defaults]
group = MyResourceGroup
location = westus2
[extension]
use_dynamic_install = yes_without_prompt
run_after_dynamic_install = true
[cloud]
name = AzureCloud
Output: (none — file content)
Equivalent environment variables for a CI runner where you don't want to ship a config file:
export AZURE_CORE_OUTPUT=json
export AZURE_CORE_ONLY_SHOW_ERRORS=true
export AZURE_CORE_COLLECT_TELEMETRY=false
export AZURE_DEFAULTS_GROUP=MyResourceGroup
export AZURE_DEFAULTS_LOCATION=westus2
Output: (none — exits 0 on success)
Authentication
az login establishes the credential context for every subsequent command. The CLI supports five distinct credential types — interactive browser, device-code (headless), service principal with secret, service principal with certificate, and managed identity — and the right one depends on where the CLI is running. Tokens are cached under ~/.azure/ and refreshed automatically until the refresh token expires.
# Interactive — opens the system browser
az login
# Device code — for SSH sessions or browser-less hosts
az login --use-device-code
# Service principal (client secret)
az login --service-principal \
--username 00000000-0000-0000-0000-000000000000 \
--password "$AZURE_CLIENT_SECRET" \
--tenant 11111111-1111-1111-1111-111111111111
# Service principal (certificate)
az login --service-principal \
--username 00000000-0000-0000-0000-000000000000 \
--password /home/alice/.azure/sp-cert.pem \
--tenant 11111111-1111-1111-1111-111111111111
# Managed identity (system-assigned) — only inside Azure VMs / App Service
az login --identity
# Managed identity (user-assigned)
az login --identity --username 22222222-2222-2222-2222-222222222222
# Show the current credential
az account show --output table
Output:
EnvironmentName HomeTenantId IsDefault Name State TenantId
----------------- ------------------------------------ ----------- ------------------ ------- ------------------------------------
AzureCloud 11111111-1111-1111-1111-111111111111 True Pay-As-You-Go Enabled 11111111-1111-1111-1111-111111111111
az account — subscriptions, tenants, management groups
az account is the management surface for the identity-and-billing layer. A single Microsoft Entra principal often spans multiple subscriptions across one or more tenants, and many enterprises group those subscriptions into a hierarchy of management groups for centralized policy and RBAC. az account lists everything you can see, switches the active context, mints raw access tokens, and (with az account management-group and az account lock) reaches up into governance.
Subscriptions
A subscription is the billing and isolation boundary — every resource you create belongs to exactly one. az account list shows the cached set; az account set chooses one as the default for every subsequent command (it writes to ~/.azure/azureProfile.json, so the choice persists across shells).
# Show every subscription this identity can see (table view)
az account list --output table
# Refresh the cached list after a new role assignment was granted
az account list --refresh
# Show the active context — sub + tenant + user
az account show
# Just the sub ID (for variable capture)
az account show --query id -o tsv
# Make a subscription the default — by display name or GUID
az account set --subscription "Pay-As-You-Go"
az account set --subscription 33333333-3333-3333-3333-333333333333
# Clear the default (forces every command to specify --subscription)
az account clear
Output:
Name CloudName SubscriptionId TenantId State IsDefault
------------------ ----------- ------------------------------------ ------------------------------------ ------- -----------
Pay-As-You-Go AzureCloud 33333333-3333-3333-3333-333333333333 11111111-1111-1111-1111-111111111111 Enabled True
Sandbox AzureCloud 44444444-4444-4444-4444-444444444444 11111111-1111-1111-1111-111111111111 Enabled False
Tenants
A tenant is the Microsoft Entra directory — every subscription belongs to exactly one. Use az account tenant list when an identity is a guest in multiple directories and you want to see every tenant you can sign into without leaving the current login session.
# List every tenant this identity is a member or guest of
az account tenant list --output table
# Show the tenant ID for the active subscription
az account show --query tenantId -o tsv
# List subscriptions filtered to a single tenant
az account list --query "[?tenantId=='11111111-1111-1111-1111-111111111111']" -o table
Output:
TenantId DisplayName DefaultDomain
------------------------------------ ---------------- ------------------------
11111111-1111-1111-1111-111111111111 Contoso Ltd contoso.onmicrosoft.com
55555555-5555-5555-5555-555555555555 Fabrikam Inc. fabrikam.onmicrosoft.com
Access tokens
az account get-access-token mints a bearer token for the active credential, scoped to a chosen audience. Useful for one-off curl calls into APIs that don't have CLI coverage, and for scripting against Microsoft Graph / Key Vault / Storage when you don't want to bring in an SDK.
# Default audience: ARM (management.azure.com)
az account get-access-token --query accessToken -o tsv
# Microsoft Graph
az account get-access-token --resource https://graph.microsoft.com --query accessToken -o tsv
# Key Vault data plane
az account get-access-token --resource https://vault.azure.net --query accessToken -o tsv
# Use it with curl
TOKEN=$(az account get-access-token --resource https://graph.microsoft.com --query accessToken -o tsv)
curl -sH "Authorization: Bearer $TOKEN" "https://graph.microsoft.com/v1.0/me" | jq .userPrincipalName
Output:
"alice@example.com"
Management groups
Management groups give you a hierarchy above subscriptions — policy assignments and RBAC role assignments on a management group cascade to every subscription beneath it. The root group is the tenant; below it you can build any tree shape (Microsoft caps the depth at 6 levels).
# Enable management-group hierarchy for the current tenant (one-time, idempotent)
az account management-group create --name root --display-name "Tenant Root"
# Create a child group nested under another
az account management-group create --name engineering --display-name "Engineering" --parent root
az account management-group create --name eng-prod --display-name "Engineering — Prod" --parent engineering
az account management-group create --name eng-sandbox --display-name "Engineering — Sandbox" --parent engineering
# List every management group in the tenant
az account management-group list --output table
# Show one group's metadata
az account management-group show --name engineering --expand --recurse --output yaml
# Move a subscription into a group
az account management-group subscription add \
--name eng-sandbox \
--subscription 44444444-4444-4444-4444-444444444444
# Remove a subscription from a group (returns it to the parent)
az account management-group subscription remove \
--name eng-sandbox \
--subscription 44444444-4444-4444-4444-444444444444
# Rename / update
az account management-group update --name engineering --display-name "Engineering Org"
# Delete (empty groups only — move children out first)
az account management-group delete --name eng-sandbox
Output:
Name DisplayName TenantId
----------- --------------------- ------------------------------------
root Tenant Root 11111111-1111-1111-1111-111111111111
engineering Engineering Org 11111111-1111-1111-1111-111111111111
eng-prod Engineering — Prod 11111111-1111-1111-1111-111111111111
eng-sandbox Engineering — Sandbox 11111111-1111-1111-1111-111111111111
Subscription-level locks
az account lock (alias for az lock filtered to subscription scope) prevents accidental deletes or modifications at the subscription level. CanNotDelete blocks deletion but allows changes; ReadOnly blocks any write. Locks cascade to child resources, so a CanNotDelete at the subscription protects everything.
# Apply a delete lock on the active subscription
az account lock create \
--name no-delete-prod \
--lock-type CanNotDelete \
--notes "Prod sub — break-glass change required"
# List locks on the active subscription
az account lock list --output table
# Remove a lock
az account lock delete --name no-delete-prod
Output:
Name Level Notes
---------------- -------------- --------------------------------------
no-delete-prod CanNotDelete Prod sub — break-glass change required
az devops — Azure DevOps configuration & projects
The az devops, az repos, az pipelines, az boards, and az artifacts command groups all ship in the azure-devops extension — they are not in core az. Install once, then az devops login (which prompts for a Personal Access Token) authenticates you against an organization at https://dev.azure.com/<org>. After login, az devops configure --defaults lets you stop typing --organization and --project on every command — by far the biggest ergonomic win for DevOps scripting.
# Install the extension (once per machine)
az extension add --name azure-devops
az extension show --name azure-devops --query version -o tsv
# Authenticate against an organization (PAT prompt on stdin)
echo "$AZDO_PAT" | az devops login --organization https://dev.azure.com/contoso
# Set defaults so subsequent commands don't need --organization / --project
az devops configure --defaults \
organization=https://dev.azure.com/contoso \
project=ContosoWebApp
# Show the current defaults
az devops configure --list
# Clear a single default
az devops configure --defaults project=''
# Log out (clears the cached PAT from the keyring)
az devops logout
Output:
organization = https://dev.azure.com/contoso
project = ContosoWebApp
Projects
A project is the top-level container inside an organization — every repo, pipeline, board, and artifact feed lives inside exactly one. az devops project create/list/show/delete is enough for full lifecycle management; the four key settings to think about at creation time are visibility (private/public), the source-control type (git is universal — tfvc is legacy), the work-item process (Agile/Scrum/Basic/CMMI), and the description.
# List every project in the configured org
az devops project list --output table
# Show one project's metadata
az devops project show --project ContosoWebApp
# Create a new project (private, Git, Agile process)
az devops project create \
--name ContosoAPI \
--description "Backend services for Contoso storefront" \
--visibility private \
--source-control git \
--process Agile
# Update visibility or description
az devops project update --project ContosoAPI --description "Backend microservices" --visibility private
# Delete (irreversible — prompts for confirmation unless --yes)
az devops project delete --id $(az devops project show --project Sandbox --query id -o tsv) --yes
Output:
ID Name Visibility Process
------------------------------------ ------------- ------------ --------
66666666-6666-6666-6666-666666666666 ContosoWebApp private Agile
77777777-7777-7777-7777-777777777777 ContosoAPI private Agile
Teams, service endpoints, security
Teams are sub-units inside a project that map to work-item areas and dashboards. Service endpoints are the connections to external systems (GitHub, Docker registries, Azure subscriptions for pipelines). Security uses az devops security (groups, permissions, namespaces).
# List teams in the default project
az devops team list --output table
# Create a team and add members
az devops team create --name "Platform" --description "Platform engineering"
az devops user add --email-id alice@example.com --license-type express
az devops team add-member --team Platform --user alice@example.com
# Service endpoints — list and create a GitHub one
az devops service-endpoint list --output table
az devops service-endpoint github create \
--name "github-contoso" \
--github-url https://github.com/contoso/storefront
# Security groups in the project
az devops security group list --scope project --output table
Output:
Name Description
---------------- --------------------------
Contoso Team The default project team
Platform Platform engineering
az repos — repositories & pull requests
az repos covers the Git repositories that live inside an Azure DevOps project — create, list, import, set policies, and manage pull requests end-to-end. The most useful sub-groups are az repos (the Git repos themselves), az repos pr (pull requests with full review workflow), and az repos policy (branch policies — required reviewers, build validation, comment resolution).
Repositories
# List every repo in the default project
az repos list --output table
# Show one repo's metadata (clone URLs, default branch)
az repos show --repository ContosoWeb --query "{name:name, defaultBranch:defaultBranch, remoteUrl:remoteUrl}"
# Create a new empty repo
az repos create --name ContosoMobile
# Import from an external Git URL (GitHub, GitLab, …)
az repos import create \
--git-source-url https://github.com/contoso/legacy-app.git \
--repository ContosoLegacy
# Rename
az repos update --repository ContosoMobile --default-branch refs/heads/main
# Delete (by ID — `az repos list` for the ID)
az repos delete --id $(az repos show --repository Throwaway --query id -o tsv) --yes
Output:
Default Branch ID Name Project Size
----------------- ------------------------------------ --------------- ------------- --------
refs/heads/main 88888888-8888-8888-8888-888888888888 ContosoWeb ContosoWebApp 4823920
refs/heads/main 99999999-9999-9999-9999-999999999999 ContosoLegacy ContosoWebApp 1284560
Pull requests
az repos pr mirrors what you'd do in the browser: create, list, edit, approve, merge, and abandon PRs. Combined with --auto-complete it lets you queue a PR that merges itself once all required policies pass — the most common use case in CI-driven workflows.
# Create a PR from a feature branch into main
az repos pr create \
--repository ContosoWeb \
--source-branch feature/login-refresh \
--target-branch main \
--title "Refresh login flow to use Entra B2C" \
--description "Fixes #1284. Replaces legacy ASP.NET Identity with MSAL." \
--reviewers alice@example.com bob@example.com \
--work-items 1284 1287 \
--draft false \
--auto-complete true \
--delete-source-branch true \
--squash true
# List PRs (filter: active, mine, target=main)
az repos pr list --status active --creator alice@example.com --target-branch main --output table
# Show one PR
az repos pr show --id 4271 --query "{id:pullRequestId, title:title, status:status, mergeStatus:mergeStatus}"
# Add reviewers post-creation
az repos pr reviewer add --id 4271 --reviewers carol@example.com
# Vote: approve / approve-with-suggestions / wait / reject / reset
az repos pr set-vote --id 4271 --vote approve
# Add a comment
az repos pr work-item add --id 4271 --work-items 1290
# Complete (merge) manually
az repos pr update --id 4271 --status completed --merge-commit-message "Merged via az repos pr"
# Abandon
az repos pr update --id 4271 --status abandoned
Output:
ID Created Title Status Vote
---- -------------------------------- ------------------------------------------ ------- ------
4271 2026-06-08T11:24:01.123456+00:00 Refresh login flow to use Entra B2C active waiting
4268 2026-06-07T16:02:14.987654+00:00 Bump @azure/identity to 4.5 active approved
Branch policies
Branch policies enforce quality gates on PRs targeting a protected branch — minimum reviewer count, build validation, work-item linking, comment resolution. az repos policy lets you script the same set of policies across every protected branch in every repo, which is the standard way enterprises maintain governance at scale.
REPO_ID=$(az repos show --repository ContosoWeb --query id -o tsv)
# List every policy on a repo (or a specific branch)
az repos policy list --repository-id $REPO_ID --output table
az repos policy list --repository-id $REPO_ID --branch main --output table
# Require N approving reviewers
az repos policy approver-count create \
--repository-id $REPO_ID \
--branch main \
--blocking true \
--enabled true \
--minimum-approver-count 2 \
--creator-vote-counts false \
--allow-downvotes false \
--reset-on-source-push true
# Require build validation (pipeline must pass before merge)
PIPELINE_ID=$(az pipelines show --name contoso-web-ci --query id -o tsv)
az repos policy build create \
--repository-id $REPO_ID \
--branch main \
--blocking true \
--enabled true \
--build-definition-id $PIPELINE_ID \
--display-name "CI must pass" \
--queue-on-source-update-only true \
--manual-queue-only false \
--valid-duration 1440
# Require all comments resolved
az repos policy comment-required create \
--repository-id $REPO_ID \
--branch main \
--blocking true \
--enabled true
# Require linked work items
az repos policy work-item-linking create \
--repository-id $REPO_ID \
--branch main \
--blocking true \
--enabled true
# Update a policy (toggle enabled/blocking)
az repos policy update --id 1421 --enabled false
# Delete
az repos policy delete --id 1421 --yes
Output:
ID Name Is Blocking Is Enabled Branch
---- ---------------------------- ------------- ------------ -----------------
1418 Minimum number of reviewers True True refs/heads/main
1421 Build (CI must pass) True True refs/heads/main
1424 Comment requirements True True refs/heads/main
1427 Work item linking True True refs/heads/main
az pipelines — build & release pipelines
az pipelines is the build/release pipeline surface — YAML pipelines and the older Classic UI-defined ones both work here. The day-to-day sub-groups are az pipelines itself (create, run, show, list, delete pipelines), az pipelines runs (queue/show/list/cancel runs), az pipelines variable and az pipelines variable-group (build-time variables, individual and shared), az pipelines agent / az pipelines pool (self-hosted agent management), and az pipelines release (Classic releases — being deprecated in favor of multi-stage YAML).
Creating and listing pipelines
# Create a YAML pipeline tied to a repo file (auto-runs once on creation)
az pipelines create \
--name "contoso-web-ci" \
--description "Build, test, deploy ContosoWeb" \
--repository ContosoWeb \
--repository-type tfsgit \
--branch main \
--yaml-path .azure-pipelines/ci.yml
# Create from a YAML file in an external GitHub repo
az pipelines create \
--name "contoso-mobile-ci" \
--repository contoso/mobile \
--repository-type github \
--service-connection $(az devops service-endpoint list --query "[?name=='github-contoso'].id | [0]" -o tsv) \
--branch main \
--yaml-path azure-pipelines.yml
# List all pipelines in the default project
az pipelines list --output table
# Show one pipeline (definition)
az pipelines show --name contoso-web-ci --query "{name:name, queue:queue.name, branch:repository.defaultBranch}"
# Update branch or YAML path
az pipelines update --name contoso-web-ci --new-name contoso-web-ci-v2 --branch release/v2
# Delete
az pipelines delete --name contoso-web-ci-v2 --yes
Output:
ID Name Type Repository
---- ---------------- ------ ------------
12 contoso-web-ci build ContosoWeb
13 contoso-mobile build contoso/mobile
Pipeline runs
az pipelines runs queues a build and surfaces every state transition. Combine with --parameters to pass runtime template parameters and --variables to set/override build variables for a single run — useful for promoting the same pipeline across dev/staging/prod from one definition.
# Queue a run on the default branch
az pipelines run --name contoso-web-ci --branch main
# Run with parameters + variables + a specific commit
az pipelines run \
--name contoso-web-ci \
--branch main \
--commit-id 3f2c91a4e8b7d1c9a0f4e6b8c2d1a3f5e7b9c4d6 \
--parameters environment=staging deployRegion=westus2 \
--variables DEPLOY_TARGET=staging API_KEY=$STAGING_API_KEY \
--open
# List recent runs (filter by pipeline, status, branch, top N)
az pipelines runs list \
--pipeline-ids 12 \
--branch main \
--status completed \
--result succeeded \
--top 10 \
--output table
# Show a single run
az pipelines runs show --id 8842 --query "{id:id, status:status, result:result, branch:sourceBranch}"
# Cancel a running build
az pipelines runs update --id 8842 --status cancelling
# Tag a run for downstream filtering
az pipelines runs tag add --run-id 8842 --tags release-candidate v2.3.1
# List artifacts produced by a run
az pipelines runs artifact list --run-id 8842 --output table
# Download an artifact
az pipelines runs artifact download \
--run-id 8842 \
--artifact-name drop \
--path ./build-output
Output:
Run ID Number Status Result Pipeline ID Pipeline Name Source Branch Queued Time
-------- ----------------- ----------- --------- ------------- ----------------- ------------------- --------------------------------
8842 20260608.4 completed succeeded 12 contoso-web-ci refs/heads/main 2026-06-08T14:30:02.123+00:00
8841 20260608.3 completed failed 12 contoso-web-ci refs/heads/feat-x 2026-06-08T13:11:45.987+00:00
Variables and variable groups
Individual pipeline variables live on a single pipeline definition; variable groups are shared across multiple pipelines (and optionally backed by an Azure Key Vault). Secrets in either are write-only via the CLI — you can update or rotate them, but you can't read the cleartext back.
PID=$(az pipelines show --name contoso-web-ci --query id -o tsv)
# Add a plain variable to a pipeline
az pipelines variable create \
--pipeline-id $PID \
--name DEPLOY_TARGET \
--value staging \
--allow-override true
# Add a secret variable
az pipelines variable create \
--pipeline-id $PID \
--name API_KEY \
--value "$REAL_SECRET_VALUE" \
--secret true \
--allow-override false
# List variables on a pipeline
az pipelines variable list --pipeline-id $PID --output table
# Update a variable (or rotate a secret)
az pipelines variable update --pipeline-id $PID --name API_KEY --value "$NEW_SECRET" --secret true
# Delete
az pipelines variable delete --pipeline-id $PID --name DEPLOY_TARGET --yes
# Create a variable group (shared across pipelines)
az pipelines variable-group create \
--name contoso-shared \
--description "Shared deploy settings" \
--authorize true \
--variables REGION=westus2 STORAGE_ACCOUNT=alicedev01
# Add a Key-Vault-backed variable group
SP_ID=$(az devops service-endpoint list --query "[?name=='azure-contoso'].id | [0]" -o tsv)
az pipelines variable-group create \
--name contoso-kv \
--description "Secrets from Key Vault" \
--authorize true \
--variables KV_PLACEHOLDER=ignored
# Link / unlink variables in a group
az pipelines variable-group variable create --group-id 14 --name DB_USER --value alicedev
az pipelines variable-group variable update --group-id 14 --name DB_USER --value bobdev
az pipelines variable-group variable delete --group-id 14 --name DB_USER --yes
# List all groups
az pipelines variable-group list --output table
Output:
Name Allow Override Is Secret Value
---------------- ---------------- ----------- --------
DEPLOY_TARGET True False staging
API_KEY False True ***
Agents and pools
Microsoft-hosted agents are the default — pools like Azure Pipelines and ubuntu-latest are pre-provisioned. Self-hosted pools are for organizations with build hosts that need access to private networks, custom toolchains, or GPUs. az pipelines pool and az pipelines agent cover the read side; agent registration itself happens via the agent installer, not the CLI.
# List every agent pool in the org
az pipelines pool list --output table
# Show one pool
az pipelines pool show --pool-name "Default" --query "{name:name, isHosted:isHosted, size:size}"
# List agents in a pool
az pipelines agent list --pool-id 5 --output table
# Show one agent's status
az pipelines agent show --pool-id 5 --agent-id 27 --query "{name:name, status:status, version:version, online:enabled}"
Output:
ID Name Is Hosted Pool Type
---- -------------- ----------- -----------
1 Azure Pipelines True automation
5 Default False automation
Releases (Classic)
Classic release pipelines are being superseded by multi-stage YAML pipelines, but a huge installed base remains. az pipelines release covers create-definition / list / show / cancel; for new work, prefer YAML pipelines with environments and approval gates.
# List release definitions
az pipelines release definition list --output table
# Trigger a release
az pipelines release create --definition-id 7 --description "Manual prod release"
# List releases
az pipelines release list --definition-id 7 --top 5 --output table
# Show a single release
az pipelines release show --id 84 --query "{name:name, status:status, environments:environments[].name}"
Output:
Name ID Status Created On Created By
---------------- ---- --------- ------------------------------- --------------------
Release-84 84 active 2026-06-08T15:02:11+00:00 alice@example.com
Release-83 83 completed 2026-06-07T09:14:33+00:00 bob@example.com
Resource groups and resources
Resource groups are the unit of lifecycle management in Azure — every resource lives in exactly one group, and deleting the group deletes everything inside. The az group and az resource command groups together give you the generic create/list/move/delete surface that maps directly to the Azure Resource Manager API.
# Create a new RG in West US 2
az group create --name MyResourceGroup --location westus2
# List groups (table format)
az group list --output table
# Show one group's metadata
az group show --name MyResourceGroup
# List every resource inside a group
az resource list --resource-group MyResourceGroup --output table
# Tag a group (or any resource)
az group update --name MyResourceGroup --tags owner=alicedev env=dev
# Move a resource between groups (same subscription)
az resource move --destination-group MyResourceGroup-prod \
--ids $(az resource show -g MyResourceGroup -n mystorage --resource-type Microsoft.Storage/storageAccounts --query id -o tsv)
# Delete an RG and everything in it (no confirmation in CI)
az group delete --name MyResourceGroup --yes --no-wait
Output:
Name Location Status
---------------- ---------- ---------
MyResourceGroup westus2 Succeeded
Output formatting and JMESPath queries
--output controls the serializer; --query runs a JMESPath expression against the response before serialization. Together they replace ad-hoc jq pipelines for almost everything — the query runs client-side after the API returns, so it doesn't reduce the request payload, but it makes scripts much easier to read.
# Default: JSON
az vm list
# Table — flattens common columns
az vm list --output table
# TSV — perfect for `read` / `awk` / `cut`
az vm list --query "[].name" --output tsv
# Project specific fields
az vm list --query "[].{name:name, size:hardwareProfile.vmSize, os:storageProfile.osDisk.osType}" \
--output table
# Filter by tag
az vm list --query "[?tags.env=='prod'].name" --output tsv
# Get the first hit
az vm list --query "[0].name" --output tsv
# Chain: get the public IP of a VM by name
az vm list-ip-addresses --name myvm \
--query "[].virtualMachine.network.publicIpAddresses[0].ipAddress" -o tsv
Output:
Name ResourceGroup Location Zones
---------- ---------------- --------- -----
myvm MyResourceGroup westus2
appserver MyResourceGroup westus2 1
Extensions
Most newer or preview Azure services ship as CLI extensions rather than in the core binary. They live under ~/.azure/cliextensions/<name> and are managed with az extension. Set extension.use_dynamic_install = yes_without_prompt once and the CLI will install missing extensions on demand the first time you invoke a command that needs them.
# List installed extensions
az extension list --output table
# Search for extensions matching a name
az extension list-available --output table | grep -i bastion
# Add an extension
az extension add --name azure-devops
az extension add --name containerapp
# Update one (or all)
az extension update --name azure-devops
az extension list --query "[].name" -o tsv | xargs -n1 az extension update --name
# Remove
az extension remove --name azure-devops
# Use a private index
az config set extension.index_url=https://myhost/internal/index.json
Output:
Name Version Preview Experimental ExtensionType
------------- --------- --------- -------------- ---------------
azure-devops 1.0.4 False False whl
containerapp 1.1.0 False False whl
Long-running operations and --no-wait
Many Azure operations (VM creation, AKS cluster provisioning, role assignment propagation) are asynchronous — ARM returns a 202 with a status URL and the CLI polls it until success or failure. --no-wait short-circuits the polling so your script can fire-and-forget, then use az resource wait or service-specific wait sub-commands to synchronize at a later checkpoint.
# Fire off a VM creation and move on
az vm create \
--resource-group MyResourceGroup \
--name appserver \
--image Ubuntu2204 \
--admin-username alicedev \
--generate-ssh-keys \
--no-wait
# Block until it reaches a terminal state
az vm wait --resource-group MyResourceGroup --name appserver --created --timeout 600
# Generic wait — any resource type, any condition expressed as JMESPath
az resource wait \
--ids $(az vm show -g MyResourceGroup -n appserver --query id -o tsv) \
--custom "provisioningState=='Succeeded'" \
--interval 10 --timeout 600
Output:
{
"fqdns": "",
"id": "/subscriptions/33333333-.../resourceGroups/MyResourceGroup/providers/Microsoft.Compute/virtualMachines/appserver",
"powerState": "VM running",
"publicIpAddress": "20.55.12.34",
"resourceGroup": "MyResourceGroup",
"zones": ""
}
Generic REST calls with az rest
When a service is too new to have CLI coverage, or when you need an obscure ARM endpoint, az rest reuses your existing authentication context and signs an arbitrary HTTPS request. It's the escape hatch that means you almost never need to mint a token manually with az account get-access-token and call curl.
# GET a single resource by ID
az rest --method get \
--uri "/subscriptions/$(az account show --query id -o tsv)/resourceGroups/MyResourceGroup?api-version=2024-03-01"
# GET against Microsoft Graph (changes the audience automatically)
az rest --method get --uri "https://graph.microsoft.com/v1.0/me"
# POST with a body
az rest --method post \
--uri "https://management.azure.com/subscriptions/$(az account show --query id -o tsv)/providers/Microsoft.ResourceGraph/resources?api-version=2022-10-01" \
--body '{"subscriptions":["33333333-3333-3333-3333-333333333333"],"query":"Resources | project name, type, location"}' \
--headers Content-Type=application/json
Output:
{
"id": "/subscriptions/33333333-.../resourceGroups/MyResourceGroup",
"location": "westus2",
"name": "MyResourceGroup",
"properties": {"provisioningState": "Succeeded"},
"tags": {"env": "dev"},
"type": "Microsoft.Resources/resourceGroups"
}
ARM and Bicep deployments
az deployment is the imperative wrapper around Azure Resource Manager template deployments. You can submit either a JSON ARM template or a Bicep file (the CLI compiles it on the fly when you have the Bicep tool installed). The four scope flags — group, sub, mg, tenant — pick which scope the deployment runs at.
# Validate before deploying
az deployment group validate \
--resource-group MyResourceGroup \
--template-file ./main.bicep \
--parameters env=dev sku=Standard_LRS
# What-if (preview the diff)
az deployment group what-if \
--resource-group MyResourceGroup \
--template-file ./main.bicep
# Deploy
az deployment group create \
--name infra-$(date +%Y%m%d-%H%M) \
--resource-group MyResourceGroup \
--template-file ./main.bicep \
--parameters @./params.json
# Subscription-scope deployment (creates the RG itself, etc.)
az deployment sub create \
--name bootstrap \
--location westus2 \
--template-file ./bootstrap.bicep
# List recent deployments
az deployment group list --resource-group MyResourceGroup --output table
Output:
Name State Timestamp Mode
---------------- --------- -------------------------------- ----------
infra-20260608 Succeeded 2026-06-08T14:21:00.123456+00:00 Incremental
Common pitfalls
- Forgetting
--output tsvfor variable capture — JSON output is wrapped in quotes ("westus2") and breaks$()interpolation. Use--output tsv(or-o tsv) for any value you intend to pass to another command. - JMESPath
--queryafter API call, not before —--queryruns locally, so it doesn't reduce server-side load. For huge lists, use server-side filters likeaz resource list --resource-group … --resource-type …first, then--query. az loginopens a browser by default — on a headless VM/SSH session this dumps an error aboutxdg-open; use--use-device-codeor service principal auth instead.- Service-principal credentials in
--passwordleak into shell history — read from an env var or a file (--password $AZURE_CLIENT_SECRET,--password /path/to/secret) and treat the file as a secret. - Default subscription is per-machine, not per-shell —
az account setwrites to~/.azure/azureProfile.jsonand affects every shell. For per-script overrides, pass--subscriptionon every command. - Confirmation prompts hang CI — set
core.disable_confirm_prompt = yesin config or pass--yeson each destructive command. Preview warnings can still appear on stderr; silence them with--only-show-errorsorcore.only_show_errors = yes. - Long-running operations block by default —
az vm createreturns only after the VM is fully provisioned (~2 minutes). Use--no-waitplusaz resource waitif you have more work to do in parallel. - Extensions and core can drift — after
az upgrade, runaz extension update --name <each>(or list-pipe-update). Stale extensions cause cryptic auth or schema errors against current ARM API versions. az config setdoes not validate keys — typos likecore.outputtare silently accepted and have no effect. Round-trip withaz config get core.outputtafter setting to confirm.- WSL
az logincan't open the Windows browser without WSLU — installwsluor pass--use-device-code. Tokens then cache in the WSL filesystem, not the Windows side. az devopscommands silently use stale defaults —az devops configure --defaults project=ContosoOldlingers across shells. Runaz devops configure --listwhenever arepos/pipelinescommand targets a project you don't expect.- PAT vs
az loginconfusion —az devops loginuses a Personal Access Token (PAT) scoped to a single org, while coreaz loginuses Microsoft Entra. Someaz devops/az repos/az pipelinescalls fall back to the Entra token automatically (--detect); explicit PAT login is more predictable in CI. az pipelines run --variablesonly overrides variables markedallow-override— set--allow-override trueat create time or the runtime value is ignored without an error.- Secret variables can't be read back —
az pipelines variable listshows secrets as***. To rotate,az pipelines variable update --secret true --value $NEW. To "view" one, dump it from a pipeline step (withisOutput=trueand a${{ }}reference) — never in cleartext logs. - Subscription locks block management-group moves too — a
ReadOnlylock on a subscription preventsaz account management-group subscription addfrom succeeding. Remove the lock, move, re-apply.
Real-world recipes
Create a resource group, storage account, and upload a blob
End-to-end provisioning of a storage account with RBAC-only access plus uploading a file — the typical "land some data in Azure" pipeline.
RG=MyResourceGroup
LOC=westus2
SA=alicedev$(openssl rand -hex 3)
CONTAINER=data
az group create -n "$RG" -l "$LOC"
az storage account create -n "$SA" -g "$RG" -l "$LOC" --sku Standard_LRS --allow-blob-public-access false
az storage container create \
--account-name "$SA" \
--name "$CONTAINER" \
--auth-mode login
az storage blob upload \
--account-name "$SA" \
--container-name "$CONTAINER" \
--name report.csv \
--file ./report.csv \
--auth-mode login
az storage blob list --account-name "$SA" --container-name "$CONTAINER" --auth-mode login -o table
Output:
Name Blob Type Blob Tier Length Content Type Last Modified
---------- ----------- ----------- -------- -------------- -------------------------
report.csv BlockBlob Hot 12431 text/csv 2026-06-08T14:22:11+00:00
Tear down everything tagged env=sandbox
A weekly sweeper for sandbox resources — uses --query to filter and xargs to fan out into az group delete calls.
az group list --query "[?tags.env=='sandbox'].name" -o tsv \
| xargs -I {} az group delete --name {} --yes --no-wait
echo "Deletion requested for every sandbox RG."
Output:
Deletion requested for every sandbox RG.
Service-principal-driven deployment in GitHub Actions
Login non-interactively, deploy a Bicep file, and assert success — all using environment variables passed in as Actions secrets.
az login --service-principal \
--username "$AZURE_CLIENT_ID" \
--password "$AZURE_CLIENT_SECRET" \
--tenant "$AZURE_TENANT_ID" \
--only-show-errors
az account set --subscription "$AZURE_SUBSCRIPTION_ID"
az deployment group create \
--name "ci-$GITHUB_RUN_NUMBER" \
--resource-group MyResourceGroup \
--template-file ./infra/main.bicep \
--parameters @./infra/params.json \
--query "properties.provisioningState" -o tsv
Output:
Succeeded
Cost: list every VM with its size and OS
A snapshot for an inventory spreadsheet — combine --query projections with --output tsv and pipe straight into a CSV file.
echo "name,resource_group,size,os,location" > vms.csv
az vm list \
--query "[].{name:name, rg:resourceGroup, size:hardwareProfile.vmSize, os:storageProfile.osDisk.osType, loc:location}" \
-o tsv \
| awk -F'\t' '{print $1","$2","$3","$4","$5}' >> vms.csv
head -3 vms.csv
Output:
name,resource_group,size,os,location
appserver,MyResourceGroup,Standard_D2s_v3,Linux,westus2
db-01,MyResourceGroup,Standard_E4s_v3,Linux,westus2
Diagnose an ARM 4xx with --debug
When a command fails with a vague error, --debug dumps the full HTTP request URL, headers, body, and the ARM error payload — that's almost always enough to identify a missing role assignment, a quota issue, or a malformed property.
az vm create \
-g MyResourceGroup -n badvm \
--image Ubuntu2204 --size Standard_NOPE \
--admin-username alicedev --generate-ssh-keys \
--debug 2>&1 \
| grep -E "(Request URL|Response status|error|InvalidParameter)" \
| head
Output:
cli.azure.cli.core.sdk.policies: Request URL: 'https://management.azure.com/subscriptions/.../providers/Microsoft.Compute/locations/westus2/vmSizes?api-version=2024-07-01'
cli.azure.cli.core.sdk.policies: Response status: 200
cli.azure.cli.core.sdk.policies: Request URL: 'https://management.azure.com/.../providers/Microsoft.Compute/virtualMachines/badvm?api-version=2024-07-01'
cli.azure.cli.core.sdk.policies: Response status: 400
cli.azure.cli.core.azclierror: The provided VM size 'Standard_NOPE' is not available...
Switch sovereign clouds (commercial → Azure US Government)
When working with a customer on a regulated tenant, point the CLI at a different sovereign cloud — every subsequent call routes to the gov endpoints (management.usgovcloudapi.net, etc.).
az cloud list --output table
az cloud set --name AzureUSGovernment
az login
az account show --query "environmentName" -o tsv
Output:
AzureUSGovernment
Bootstrap a project + repo + CI pipeline + branch policies
Spin up an Azure DevOps project from scratch, import a Git repo, create a YAML pipeline, and apply the standard branch-policy gates (2 reviewers + build validation + comments resolved) in one script. The kind of thing you copy once and reuse on every new microservice.
ORG=https://dev.azure.com/contoso
PROJ=ContosoAPI
REPO_NAME=storefront-svc
PIPE_NAME=storefront-svc-ci
az devops configure --defaults organization=$ORG project=$PROJ
az devops project create --name "$PROJ" --visibility private --source-control git --process Agile
az repos import create \
--git-source-url https://github.com/contoso/storefront-svc.git \
--repository "$REPO_NAME"
REPO_ID=$(az repos show --repository "$REPO_NAME" --query id -o tsv)
az pipelines create \
--name "$PIPE_NAME" \
--repository "$REPO_NAME" \
--repository-type tfsgit \
--branch main \
--yaml-path .azure-pipelines/ci.yml
PIPE_ID=$(az pipelines show --name "$PIPE_NAME" --query id -o tsv)
az repos policy approver-count create --repository-id $REPO_ID --branch main \
--blocking true --enabled true --minimum-approver-count 2 \
--creator-vote-counts false --allow-downvotes false --reset-on-source-push true
az repos policy build create --repository-id $REPO_ID --branch main \
--blocking true --enabled true --build-definition-id $PIPE_ID \
--display-name "CI must pass" --queue-on-source-update-only true \
--manual-queue-only false --valid-duration 1440
az repos policy comment-required create --repository-id $REPO_ID --branch main \
--blocking true --enabled true
echo "Bootstrap complete for $PROJ/$REPO_NAME — pipeline $PIPE_NAME (#$PIPE_ID)"
Output:
Bootstrap complete for ContosoAPI/storefront-svc — pipeline storefront-svc-ci (#42)
Promote a release through dev → staging → prod
Run the same CI pipeline three times against the same commit, each with a different environment parameter and matching variable group — the canonical "manual promotion" flow when you don't yet have multi-stage YAML approvals wired up.
PIPE_NAME=storefront-svc-ci
COMMIT=$(git rev-parse main)
for ENV in dev staging prod; do
RUN_ID=$(az pipelines run \
--name "$PIPE_NAME" \
--branch main \
--commit-id "$COMMIT" \
--parameters environment=$ENV \
--variables DEPLOY_TARGET=$ENV \
--query id -o tsv)
echo "Queued $ENV deploy as run #$RUN_ID — waiting for success"
for i in $(seq 1 60); do
STATUS=$(az pipelines runs show --id $RUN_ID --query "{s:status, r:result}" -o tsv)
case "$STATUS" in
"completed succeeded") echo " → $ENV succeeded"; break ;;
"completed "*) echo " → $ENV failed: $STATUS"; exit 1 ;;
*) sleep 15 ;;
esac
done
done
Output:
Queued dev deploy as run #8851 — waiting for success
→ dev succeeded
Queued staging deploy as run #8852 — waiting for success
→ staging succeeded
Queued prod deploy as run #8853 — waiting for success
→ prod succeeded
Audit every PR open longer than 7 days across all repos
A weekly hygiene sweep — list active PRs by age and post a Slack-ready summary. Combines az repos list to fan out across repos with az repos pr list per repo, then jq to filter and format.
THRESHOLD_DAYS=7
NOW=$(date -u +%s)
az repos list --query "[].id" -o tsv | while read REPO_ID; do
az repos pr list --status active --repository "$REPO_ID" \
--query "[].{id:pullRequestId, title:title, creator:createdBy.uniqueName, created:creationDate}" \
-o json
done | jq -s --argjson now "$NOW" --argjson th "$THRESHOLD_DAYS" '
add
| map(. + {ageDays: (($now - (.created | sub("\\.\\d+"; "") | fromdateiso8601)) / 86400 | floor)})
| map(select(.ageDays >= $th))
| sort_by(-.ageDays)
| .[] | "\(.ageDays)d #\(.id) \(.creator) \(.title)"'
Output:
14d #4189 bob@example.com Refactor auth middleware
11d #4203 alice@example.com Add metrics for cold-start latency
8d #4231 carol@example.com Bump @azure/identity to 4.5
Tail Activity Log for a single resource group
When something just deleted itself, this is the first place to look. --max-events keeps the request small and --query flattens the payload to the columns that matter for a quick scan.
az monitor activity-log list \
--resource-group MyResourceGroup \
--max-events 30 \
--query "[].{time:eventTimestamp, op:operationName.localizedValue, caller:caller, status:status.value}" \
-o table
Output:
Time Op Caller State
-------------------------------- -------------------------------------------- -------------------- ---------
2026-06-08T14:33:11.123456+00:00 Delete Storage Account alicedev@example.com Succeeded
2026-06-08T14:30:02.987654+00:00 Update Resource Group alicedev@example.com Succeeded
Sources
References consulted while writing this article. Links open in a new tab.
- Azure CLI release notes — Confirmed the current stable version (2.87.0, June 2026) and upcoming 2.88.0 / 2.89.0 schedule cited in What it is and Install.
- Azure CLI configuration options — Source for the full
[core]/[logging]/[defaults]/[storage]/[cloud]/[batch]/[extension]option tables and theAZURE_{SECTION}_{KEY}environment-variable pattern. - Install the Azure CLI — Provided the canonical apt/dnf/brew/winget/pip install commands and the
aka.ms/InstallAzureCLIDebone-liner. - Sign in with the Azure CLI — Authoritative list of the five credential types (interactive, device code, service principal with secret, service principal with cert, managed identity) used in Authentication.
- Sign in with a service principal — Exact flag shape (
--service-principal --username … --password … --tenant …) used in the CI recipe. - Upcoming breaking changes — Confirmed 2.87.0 breaking changes (e.g.
--access-keys-authdefault flip) referenced in What it is. - Azure/azure-cli on GitHub — Canonical repository; release tags, issue tracker, and Python source.
- Manage Azure subscriptions with the Azure CLI — Source for
az account list/set/clearsemantics and the--refreshflag used in the az account section. - az account management-group reference — Exact create/list/show/update/delete and the nested
subscription add/removesub-group used to build the hierarchy example. - Get started with Azure DevOps CLI — Established that
az devops/az repos/az pipelinesship in theazure-devopsextension and requireaz devops loginwith a PAT. - azure-devops-cli-extension getting started — Provided the
az devops configure --defaults organization=… project=…ergonomic pattern. - Manage pipelines with the Azure DevOps CLI — Source for
az pipelines create/run/runs/runs artifactpatterns and the YAML-pipeline-from-repo example. - az pipelines variable reference — Flag shape for
--secret,--allow-override, and the rotation-vs-read constraint cited in Common pitfalls. - az repos pr reference — Full flag list for
az repos pr create(auto-complete, reviewers, work-items, squash, delete-source-branch). - az repos pr policy reference — Source for
approver-count/build/comment-required/work-item-linkingbranch-policy commands and their flag combinations.