ado

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
<!-- markdownlint-disable-file MD041 -->
STARTER_CHARACTER = 🔷
<!-- markdownlint-disable-file MD041 -->
STARTER_CHARACTER = 🔷

Azure DevOps Operations

Azure DevOps 操作

Use the
az
CLI and ADO REST API to interact with Azure DevOps resources.
使用
az
CLI 和 ADO REST API 与 Azure DevOps 资源进行交互。

Prerequisites

前置条件

Auth:
$AZURE_DEVOPS_EXT_PAT
(always set). No login needed.
Repo ops require ADO remote (
dev.azure.com
or
visualstudio.com
).
身份验证:
$AZURE_DEVOPS_EXT_PAT
(始终设置)。无需登录。
存储库操作需要 ADO 远程仓库(
dev.azure.com
或
visualstudio.com
)。

Default Org and Project

默认组织和项目

The shell environment provides default values via
$ADO_DEFAULT_ORG
and
$ADO_DEFAULT_PROJECT
. Use these as fallbacks when org or project cannot be parsed from the git remote, or when operating outside a git repo.
bash
org="${org:-$ADO_DEFAULT_ORG}"
project="${project:-$ADO_DEFAULT_PROJECT}"
Pass them to
az
commands via
--org "https://dev.azure.com/${org}"
and
--project "$project"
.
Shell 环境通过
$ADO_DEFAULT_ORG
和
$ADO_DEFAULT_PROJECT
提供默认值。当无法从 Git remote 解析出组织或项目,或者在 Git 仓库之外执行操作时,使用这些值作为回退。
bash
org="${org:-$ADO_DEFAULT_ORG}"
project="${project:-$ADO_DEFAULT_PROJECT}"
通过
--org "https://dev.azure.com/${org}"
和
--project "$project"
将它们传递给
az
命令。

URL Parsing

URL 解析

Azure DevOps remotes come in three formats. Parse org, project, and repo from the remote URL to construct web URLs and pass parameters to
az
commands.
bash
remote_url=$(git remote get-url origin 2>/dev/null)
Azure DevOps remote 有三种格式。解析 remote URL 中的组织、项目和存储库,以构建 Web URL 并向
az
命令传递参数。
bash
remote_url=$(git remote get-url origin 2>/dev/null)

Format 1: dev.azure.com HTTPS

格式 1:dev.azure.com HTTPS

Pattern:
https://dev.azure.com/{org}/{project}/_git/{repo}
or
https://{user}@dev.azure.com/{org}/{project}/_git/{repo}
bash
clean_url=$(echo "$remote_url" | sed 's|https://[^@]*@|https://|')
org=$(echo "$clean_url" | sed -n 's|https://dev\.azure\.com/\([^/]*\)/.*|\1|p')
project=$(echo "$clean_url" | sed -n 's|https://dev\.azure\.com/[^/]*/\([^/]*\)/_git/.*|\1|p')
repo=$(echo "$clean_url" | sed -n 's|.*/_git/\(.*\)|\1|p')
模式:
https://dev.azure.com/{org}/{project}/_git/{repo}
或
https://{user}@dev.azure.com/{org}/{project}/_git/{repo}
bash
clean_url=$(echo "$remote_url" | sed 's|https://[^@]*@|https://|')
org=$(echo "$clean_url" | sed -n 's|https://dev\\.azure\\.com/\\([^/]*\\)/.*|\\1|p')
project=$(echo "$clean_url" | sed -n 's|https://dev\\.azure\\.com/[^/]*/\\([^/]*\\)/_git/.*|\\1|p')
repo=$(echo "$clean_url" | sed -n 's|.*/_git/\\(.*\\)|\\1|p')

Format 2: visualstudio.com

格式 2:visualstudio.com

Pattern:
https://{org}.visualstudio.com/DefaultCollection/{project}/_git/{repo}
bash
clean_url=$(echo "$remote_url" | sed 's|https://[^@]*@|https://|')
org=$(echo "$clean_url" | sed -n 's|^https://\([^.]*\)\..*|\1|p')
project=$(echo "$clean_url" | sed -n 's|.*/DefaultCollection/\([^/]*\)/_git/.*|\1|p')
repo=$(echo "$clean_url" | sed -n 's|.*/_git/\(.*\)|\1|p')
模式:
https://{org}.visualstudio.com/DefaultCollection/{project}/_git/{repo}
bash
clean_url=$(echo "$remote_url" | sed 's|https://[^@]*@|https://|')
org=$(echo "$clean_url" | sed -n 's|^https://\\([^.]*\\)\\..*|\\1|p')
project=$(echo "$clean_url" | sed -n 's|.*/DefaultCollection/\\([^/]*\\)/_git/.*|\\1|p')
repo=$(echo "$clean_url" | sed -n 's|.*/_git/\\(.*\\)|\\1|p')

Format 3: SSH

格式 3:SSH

Pattern:
git@ssh.dev.azure.com:v3/{org}/{project}/{repo}
bash
org=$(echo "$remote_url" | sed -n 's|git@ssh\.dev\.azure\.com:v3/\([^/]*\)/.*|\1|p')
project=$(echo "$remote_url" | sed -n 's|git@ssh\.dev\.azure\.com:v3/[^/]*/\([^/]*\)/.*|\1|p')
repo=$(echo "$remote_url" | sed -n 's|.*[^/]*/\([^/]*\)$|\1|p')
模式:
git@ssh.dev.azure.com:v3/{org}/{project}/{repo}
bash
org=$(echo "$remote_url" | sed -n 's|git@ssh\\.dev\\.azure\\.com:v3/\\([^/]*\\)/.*|\\1|p')
project=$(echo "$remote_url" | sed -n 's|git@ssh\\.dev\\.azure\\.com:v3/[^/]*/\\([^/]*\\)/.*|\\1|p')
repo=$(echo "$remote_url" | sed -n 's|.*[^/]*/\\([^/]*\\)$|\\1|p')

Constructing Web URLs

构建 Web URL

URL-encode spaces in project names (
%20
), then build:
text
base_url=https://dev.azure.com/{org}/{project}/_git/{repo}
pr_url={base_url}/pullrequest/{pr_id}
On macOS, open URLs with
open "$url"
.

对项目名称中的空格进行 URL 编码(
%20
),然后构建:
text
base_url=https://dev.azure.com/{org}/{project}/_git/{repo}
pr_url={base_url}/pullrequest/{pr_id}
在 macOS 上,使用
open "$url"
打开 URL。

Browse

浏览

Open Repo

打开存储库

Parse the remote URL, construct the web URL, and open it.
bash
open "https://dev.azure.com/${org}/${project}/_git/${repo}"
解析 remote URL,构建 Web URL,然后打开。
bash
open "https://dev.azure.com/${org}/${project}/_git/${repo}"

Open PR

打开 PR

bash
open "https://dev.azure.com/${org}/${project}/_git/${repo}/pullrequest/${pr_id}"

bash
open "https://dev.azure.com/${org}/${project}/_git/${repo}/pullrequest/${pr_id}"

Projects

项目

List Projects

列出项目

bash
az devops project list --organization "https://dev.azure.com/${org}" --query "value[].{Name:name,ID:id,State:state}" -o table
bash
az devops project list --organization "https://dev.azure.com/${org}" --query "value[].{Name:name,ID:id,State:state}" -o table

Show Project Details

显示项目详细信息

bash
az devops project show --project "$project" --organization "https://dev.azure.com/${org}"
bash
az devops project show --project "$project" --organization "https://dev.azure.com/${org}"

Get Project ID

获取项目 ID

bash
az devops project show --project "$project" --organization "https://dev.azure.com/${org}" --query id -o tsv

bash
az devops project show --project "$project" --organization "https://dev.azure.com/${org}" --query id -o tsv

Repositories

存储库

Create

创建

bash
az repos create \
  --name "<repo-name>" \
  --project "$project" \
  --org "https://dev.azure.com/${org}" \
  --output table \
  --query "{Name:name,Project:project.name,URL:webUrl}"
bash
az repos create \\
  --name "<repo-name>" \\
  --project "$project" \\
  --org "https://dev.azure.com/${org}" \\
  --output table \\
  --query "{Name:name,Project:project.name,URL:webUrl}"

Delete

删除

Step 1: Look up the repository ID.
bash
repo_id=$(az repos show \
  --repository "<repo-name>" \
  --project "$project" \
  --query id --output tsv)
Step 2: Delete by ID.
bash
az repos delete \
  --id "$repo_id" \
  --project "$project" \
  --yes
步骤 1:查找存储库 ID。
bash
repo_id=$(az repos show \\
  --repository "<repo-name>" \\
  --project "$project" \\
  --query id --output tsv)
步骤 2:按 ID 删除。
bash
az repos delete \\
  --id "$repo_id" \\
  --project "$project" \\
  --yes

List

列出

bash
az repos list --organization "https://dev.azure.com/${org}" --project "$project" --query "[].{Name:name,ID:id,DefaultBranch:defaultBranch}" -o table
bash
az repos list --organization "https://dev.azure.com/${org}" --project "$project" --query "[].{Name:name,ID:id,DefaultBranch:defaultBranch}" -o table

Show

显示

bash
az repos show --repository <REPO_NAME> --organization "https://dev.azure.com/${org}" --project "$project"
bash
az repos show --repository <REPO_NAME> --organization "https://dev.azure.com/${org}" --project "$project"

Get Clone URL

获取克隆 URL

bash
az repos show --repository <REPO_NAME> --organization "https://dev.azure.com/${org}" --project "$project" --query remoteUrl -o tsv

bash
az repos show --repository <REPO_NAME> --organization "https://dev.azure.com/${org}" --project "$project" --query remoteUrl -o tsv

Pull Requests (CLI)

Pull Request(CLI)

All PR commands use JMESPath queries for structured output. The
base_url
variable is constructed from the parsed remote URL (see URL Parsing above).
所有 PR 命令都使用 JMESPath 查询生成结构化输出。
base_url
变量基于解析后的 remote URL 构建(参见上方的“URL 解析”)。

Create

创建

bash
az repos pr create \
  "$@" \
  --output table \
  --query "{PR:pullRequestId,Status:status,URL:join(\`\`,[\ \`${base_url}\`,\`/pullrequest/\`,to_string(pullRequestId)])}"
Common flags:
--title
,
--description
,
--source-branch
,
--target-branch
,
--reviewers
,
--auto-complete
,
--draft
bash
az repos pr create \\
  "$@" \\
  --output table \\
  --query "{PR:pullRequestId,Status:status,URL:join(\\`\\`,[\\ \\`${base_url}\\`,\\`/pullrequest/\\`,to_string(pullRequestId)])}"
常用参数:
--title
、
--description
、
--source-branch
、
--target-branch
、
--reviewers
、
--auto-complete
、
--draft

List

列出

bash
az repos pr list \
  --output table \
  --query "[].{PR:pullRequestId,Title:title,Creator:createdBy.uniqueName,Created:creationDate,URL:join(\`\`,[\`${base_url}\`,\`/pullrequest/\`,to_string(pullRequestId)])}"
Common flags:
--status
,
--creator
,
--reviewer
,
--source-branch
,
--target-branch
bash
az repos pr list \\
  --output table \\
  --query "[].{PR:pullRequestId,Title:title,Creator:createdBy.uniqueName,Created:creationDate,URL:join(\\`\\`,[\\`${base_url}\\`,\\`/pullrequest/\\`,to_string(pullRequestId)])}"
常用参数:
--status
、
--creator
、
--reviewer
、
--source-branch
、
--target-branch

Show

显示

bash
az repos pr show \
  --id <pr-id> \
  --output table \
  --query "{PR:pullRequestId,Title:title,Creator:createdBy.uniqueName,Created:creationDate,URL:join(\`\`,[\`${base_url}\`,\`/pullrequest/\`,to_string(pullRequestId)])}"
bash
az repos pr show \\
  --id <pr-id> \\
  --output table \\
  --query "{PR:pullRequestId,Title:title,Creator:createdBy.uniqueName,Created:creationDate,URL:join(\\`\\`,[\\`${base_url}\\`,\\`/pullrequest/\\`,to_string(pullRequestId)])}"

Update

更新

bash
az repos pr update \
  --id <pr-id> \
  --output table \
  --query "{PR:pullRequestId,Status:status,URL:join(\`\`,[\`${base_url}\`,\`/pullrequest/\`,to_string(pullRequestId)])}"
Common flags:
--title
,
--description
,
--status
,
--auto-complete
,
--draft
bash
az repos pr update \\
  --id <pr-id> \\
  --output table \\
  --query "{PR:pullRequestId,Status:status,URL:join(\\`\\`,[\\`${base_url}\\`,\\`/pullrequest/\\`,to_string(pullRequestId)])}"
常用参数:
--title
、
--description
、
--status
、
--auto-complete
、
--draft

Complete

完成

Complete (merge) a pull request by setting status to completed with policy bypass.
bash
az repos pr update \
  --id <pr-id> \
  --status completed \
  --bypass-policy true \
  --output table \
  --query "{PR:pullRequestId,Status:status,URL:join(\`\`,[\`${base_url}\`,\`/pullrequest/\`,to_string(pullRequestId)])}"
Additional flags:
--merge-commit-message
Completion is async. The response will still show
active
status. Follow up with
az repos pr show --id <pr-id>
to confirm
status: completed
and
mergeStatus: succeeded
.
通过将状态设置为 completed 并绕过策略来完成(合并)Pull Request。
bash
az repos pr update \\
  --id <pr-id> \\
  --status completed \\
  --bypass-policy true \\
  --output table \\
  --query "{PR:pullRequestId,Status:status,URL:join(\\`\\`,[\\`${base_url}\\`,\\`/pullrequest/\\`,to_string(pullRequestId)])}"
其他参数:
--merge-commit-message
完成操作是异步的。响应中仍会显示
active
状态。随后运行
az repos pr show --id <pr-id>
,确认
status: completed
和
mergeStatus: succeeded
。

Abandon

放弃

bash
az repos pr update \
  --id <pr-id> \
  --status abandoned \
  --output table \
  --query "{PR:pullRequestId,Status:status,URL:join(\`\`,[\`${base_url}\`,\`/pullrequest/\`,to_string(pullRequestId)])}"
bash
az repos pr update \\
  --id <pr-id> \\
  --status abandoned \\
  --output table \\
  --query "{PR:pullRequestId,Status:status,URL:join(\\`\\`,[\\`${base_url}\\`,\\`/pullrequest/\\`,to_string(pullRequestId)])}"

Vote/Approve

投票/批准

bash
az repos pr set-vote \
  --id <pr-id> \
  --vote approve
After voting, show the PR details:
bash
az repos pr show \
  --id <pr-id> \
  --output table \
  --query "{PR:pullRequestId,Title:title,Creator:createdBy.uniqueName,Created:creationDate,URL:join(\`\`,[\`${base_url}\`,\`/pullrequest/\`,to_string(pullRequestId)])}"
Valid vote values:
approve
,
approve-with-suggestions
,
wait-for-author
,
reject
,
reset

bash
az repos pr set-vote \\
  --id <pr-id> \\
  --vote approve
投票后显示 PR 详细信息:
bash
az repos pr show \\
  --id <pr-id> \\
  --output table \\
  --query "{PR:pullRequestId,Title:title,Creator:createdBy.uniqueName,Created:creationDate,URL:join(\\`\\`,[\\`${base_url}\\`,\\`/pullrequest/\\`,to_string(pullRequestId)])}"
有效投票值:
approve
、
approve-with-suggestions
、
wait-for-author
、
reject
、
reset

PR Comments and Threads (REST API)

PR 评论和 Threads(REST API)

Post Comment

发布评论

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X POST \
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/pullRequests/<PR_ID>/threads?api-version=7.0" \
  -H "Content-Type: application/json" \
  -d '{
    "comments": [{"parentCommentId": 0, "content": "Comment text here", "commentType": 1}],
    "status": 1
  }'
bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X POST \\
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/pullRequests/<PR_ID>/threads?api-version=7.0" \\
  -H "Content-Type: application/json" \\
  -d '{
    "comments": [{"parentCommentId": 0, "content": "Comment text here", "commentType": 1}],
    "status": 1
  }'

Get Comments/Threads

获取评论/Threads

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/pullRequests/<PR_ID>/threads?api-version=7.0" \
  | jq '.value[] | {id: .id, status: .status, comments: [.comments[] | {author: .author.displayName, content: .content}]}'
bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \\
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/pullRequests/<PR_ID>/threads?api-version=7.0" \\
  | jq '.value[] | {id: .id, status: .status, comments: [.comments[] | {author: .author.displayName, content: .content}]}'

Search for Comment Containing Text

搜索包含指定文本的评论

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/pullRequests/<PR_ID>/threads?api-version=7.0" \
  | jq '.value[].comments[] | select(.content | contains("SEARCH_TEXT")) | {author: .author.displayName, content: .content}'

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \\
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/pullRequests/<PR_ID>/threads?api-version=7.0" \\
  | jq '.value[].comments[] | select(.content | contains("SEARCH_TEXT")) | {author: .author.displayName, content: .content}'

Service Connections

Service Connections

List

列出

bash
az devops service-endpoint list --organization "https://dev.azure.com/${org}" --project "$project" --query "[].{Name:name,Type:type,ID:id,Scheme:authorization.scheme}" -o table
bash
az devops service-endpoint list --organization "https://dev.azure.com/${org}" --project "$project" --query "[].{Name:name,Type:type,ID:id,Scheme:authorization.scheme}" -o table

Show Details

显示详细信息

bash
az devops service-endpoint show --id <ENDPOINT_ID> --organization "https://dev.azure.com/${org}" --project "$project"
bash
az devops service-endpoint show --id <ENDPOINT_ID> --organization "https://dev.azure.com/${org}" --project "$project"

Get by Name

按名称获取

bash
az devops service-endpoint list --organization "https://dev.azure.com/${org}" --project "$project" --query "[?name=='<NAME>']" -o json
bash
az devops service-endpoint list --organization "https://dev.azure.com/${org}" --project "$project" --query "[?name=='<NAME>']" -o json

Delete

删除

bash
az devops service-endpoint delete --id <ENDPOINT_ID> --organization "https://dev.azure.com/${org}" --project "$project" --yes
bash
az devops service-endpoint delete --id <ENDPOINT_ID> --organization "https://dev.azure.com/${org}" --project "$project" --yes

Get WIF Details (REST API)

获取 WIF 详细信息(REST API)

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \
  "https://dev.azure.com/${org}/${project}/_apis/serviceendpoint/endpoints?api-version=7.1" \
  | jq ".value[] | select(.name == \"<NAME>\") | {issuer: .authorization.parameters.workloadIdentityFederationIssuer, subject: .authorization.parameters.workloadIdentityFederationSubject}"
bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \\
  "https://dev.azure.com/${org}/${project}/_apis/serviceendpoint/endpoints?api-version=7.1" \\
  | jq ".value[] | select(.name == \\"<NAME>\\") | {issuer: .authorization.parameters.workloadIdentityFederationIssuer, subject: .authorization.parameters.workloadIdentityFederationSubject}"

Authorize for All Pipelines (REST API)

为所有 Pipelines 授权(REST API)

bash
SC_ID=$(az devops service-endpoint list --organization "https://dev.azure.com/${org}" --project "$project" --query "[?name=='<NAME>'].id" -o tsv)
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X PATCH \
  "https://dev.azure.com/${org}/${project}/_apis/pipelines/pipelinePermissions/endpoint/${SC_ID}?api-version=7.1-preview.1" \
  -H "Content-Type: application/json" \
  -d '{"allPipelines": {"authorized": true}}'

bash
SC_ID=$(az devops service-endpoint list --organization "https://dev.azure.com/${org}" --project "$project" --query "[?name=='<NAME>'].id" -o tsv)
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X PATCH \\
  "https://dev.azure.com/${org}/${project}/_apis/pipelines/pipelinePermissions/endpoint/${SC_ID}?api-version=7.1-preview.1" \\
  -H "Content-Type: application/json" \\
  -d '{"allPipelines": {"authorized": true}}'

Agent Pools

Agent Pools

Pools are organization-level and shared across projects.
Pool 属于组织级别,可在项目之间共享。

List All

列出所有 Pool

bash
az pipelines pool list --organization "https://dev.azure.com/${org}" --query "[].{Name:name,ID:id,PoolType:poolType,IsHosted:isHosted,Size:size}" -o table
bash
az pipelines pool list --organization "https://dev.azure.com/${org}" --query "[].{Name:name,ID:id,PoolType:poolType,IsHosted:isHosted,Size:size}" -o table

List by Name Pattern

按名称模式列出

bash
az pipelines pool list --organization "https://dev.azure.com/${org}" --query "[?contains(name, '<PATTERN>')].{Name:name,ID:id,PoolType:poolType,Size:size}" -o table
bash
az pipelines pool list --organization "https://dev.azure.com/${org}" --query "[?contains(name, '<PATTERN>')].{Name:name,ID:id,PoolType:poolType,Size:size}" -o table

Get Pool ID by Name

按名称获取 Pool ID

bash
az pipelines pool list --organization "https://dev.azure.com/${org}" --query "[?name=='<POOL_NAME>'].id" -o tsv
bash
az pipelines pool list --organization "https://dev.azure.com/${org}" --query "[?name=='<POOL_NAME>'].id" -o tsv

Show Details

显示详细信息

bash
az pipelines pool show --organization "https://dev.azure.com/${org}" --pool-id <POOL_ID>
bash
az pipelines pool show --organization "https://dev.azure.com/${org}" --pool-id <POOL_ID>

Create (REST API)

创建(REST API)

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X POST \
  "https://dev.azure.com/${org}/_apis/distributedtask/pools?api-version=7.1" \
  -H "Content-Type: application/json" \
  -d '{"name": "<POOL_NAME>", "poolType": "automation", "isHosted": false, "autoProvision": false}'
bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X POST \\
  "https://dev.azure.com/${org}/_apis/distributedtask/pools?api-version=7.1" \\
  -H "Content-Type: application/json" \\
  -d '{"name": "<POOL_NAME>", "poolType": "automation", "isHosted": false, "autoProvision": false}'

Delete (REST API)

删除(REST API)

bash
POOL_ID=$(az pipelines pool list --organization "https://dev.azure.com/${org}" --query "[?name=='<POOL_NAME>'].id" -o tsv)
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X DELETE \
  "https://dev.azure.com/${org}/_apis/distributedtask/pools/${POOL_ID}?api-version=7.1"

bash
POOL_ID=$(az pipelines pool list --organization "https://dev.azure.com/${org}" --query "[?name=='<POOL_NAME>'].id" -o tsv)
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X DELETE \\
  "https://dev.azure.com/${org}/_apis/distributedtask/pools/${POOL_ID}?api-version=7.1"

Agents

Agents

Agents run within pools.
Agent 在 Pool 中运行。

List Agents in Pool

列出 Pool 中的 Agent

bash
POOL_ID=$(az pipelines pool list --organization "https://dev.azure.com/${org}" --query "[?name=='<POOL_NAME>'].id" -o tsv)
az pipelines agent list --organization "https://dev.azure.com/${org}" --pool-id $POOL_ID --query "[].{Name:name,ID:id,Status:status,Version:version}" -o table
bash
POOL_ID=$(az pipelines pool list --organization "https://dev.azure.com/${org}" --query "[?name=='<POOL_NAME>'].id" -o tsv)
az pipelines agent list --organization "https://dev.azure.com/${org}" --pool-id $POOL_ID --query "[].{Name:name,ID:id,Status:status,Version:version}" -o table

List Online Agents

列出在线 Agent

bash
POOL_ID=$(az pipelines pool list --organization "https://dev.azure.com/${org}" --query "[?name=='<POOL_NAME>'].id" -o tsv)
az pipelines agent list --organization "https://dev.azure.com/${org}" --pool-id $POOL_ID --query "[?status=='online'].{Name:name,ID:id,Version:version}" -o table
bash
POOL_ID=$(az pipelines pool list --organization "https://dev.azure.com/${org}" --query "[?name=='<POOL_NAME>'].id" -o tsv)
az pipelines agent list --organization "https://dev.azure.com/${org}" --pool-id $POOL_ID --query "[?status=='online'].{Name:name,ID:id,Version:version}" -o table

Show Agent Details

显示 Agent 详细信息

bash
az pipelines agent show --organization "https://dev.azure.com/${org}" --pool-id <POOL_ID> --agent-id <AGENT_ID>
bash
az pipelines agent show --organization "https://dev.azure.com/${org}" --pool-id <POOL_ID> --agent-id <AGENT_ID>

Count Online Agents

统计在线 Agent 数量

bash
POOL_ID=$(az pipelines pool list --organization "https://dev.azure.com/${org}" --query "[?name=='<POOL_NAME>'].id" -o tsv)
az pipelines agent list --organization "https://dev.azure.com/${org}" --pool-id $POOL_ID --query "[?status=='online']" -o tsv | wc -l

bash
POOL_ID=$(az pipelines pool list --organization "https://dev.azure.com/${org}" --query "[?name=='<POOL_NAME>'].id" -o tsv)
az pipelines agent list --organization "https://dev.azure.com/${org}" --pool-id $POOL_ID --query "[?status=='online']" -o tsv | wc -l

Queues

Queues

Queues are project-level references to organization-level pools. Pipeline authorization works on queues, not pools.
Queue 是对组织级 Pool 的项目级引用。Pipeline 授权作用于 Queue,而不是 Pool。

List All

列出所有 Queue

bash
az pipelines queue list --organization "https://dev.azure.com/${org}" --project "$project" --query "[].{Name:name,QueueID:id,PoolID:pool.id}" -o table
bash
az pipelines queue list --organization "https://dev.azure.com/${org}" --project "$project" --query "[].{Name:name,QueueID:id,PoolID:pool.id}" -o table

List by Name Pattern

按名称模式列出

bash
az pipelines queue list --organization "https://dev.azure.com/${org}" --project "$project" --query "[?contains(name, '<PATTERN>')].{Name:name,QueueID:id,PoolID:pool.id}" -o table
bash
az pipelines queue list --organization "https://dev.azure.com/${org}" --project "$project" --query "[?contains(name, '<PATTERN>')].{Name:name,QueueID:id,PoolID:pool.id}" -o table

Get Queue ID for Pool

获取 Pool 对应的 Queue ID

bash
POOL_ID=$(az pipelines pool list --organization "https://dev.azure.com/${org}" --query "[?name=='<POOL_NAME>'].id" -o tsv)
az pipelines queue list --organization "https://dev.azure.com/${org}" --project "$project" --query "[?pool.id==\`${POOL_ID}\`].id" -o tsv
bash
POOL_ID=$(az pipelines pool list --organization "https://dev.azure.com/${org}" --query "[?name=='<POOL_NAME>'].id" -o tsv)
az pipelines queue list --organization "https://dev.azure.com/${org}" --project "$project" --query "[?pool.id==\\`${POOL_ID}\\`].id" -o tsv

Create Queue for Pool (REST API)

为 Pool 创建 Queue(REST API)

bash
POOL_ID=$(az pipelines pool list --organization "https://dev.azure.com/${org}" --query "[?name=='<POOL_NAME>'].id" -o tsv)
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X POST \
  "https://dev.azure.com/${org}/${project}/_apis/distributedtask/queues?api-version=7.1" \
  -H "Content-Type: application/json" \
  -d '{"name": "<QUEUE_NAME>", "pool": {"id": '${POOL_ID}'}}'
bash
POOL_ID=$(az pipelines pool list --organization "https://dev.azure.com/${org}" --query "[?name=='<POOL_NAME>'].id" -o tsv)
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X POST \\
  "https://dev.azure.com/${org}/${project}/_apis/distributedtask/queues?api-version=7.1" \\
  -H "Content-Type: application/json" \\
  -d '{"name": "<QUEUE_NAME>", "pool": {"id": '${POOL_ID}'}}'

Authorize Queue for All Pipelines (REST API)

为所有 Pipelines 授权 Queue(REST API)

bash
QUEUE_ID=$(az pipelines queue list --organization "https://dev.azure.com/${org}" --project "$project" --query "[?name=='<QUEUE_NAME>'].id" -o tsv)
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X PATCH \
  "https://dev.azure.com/${org}/${project}/_apis/pipelines/pipelinePermissions/queue/${QUEUE_ID}?api-version=7.1-preview.1" \
  -H "Content-Type: application/json" \
  -d '{"allPipelines": {"authorized": true}}'
bash
QUEUE_ID=$(az pipelines queue list --organization "https://dev.azure.com/${org}" --project "$project" --query "[?name=='<QUEUE_NAME>'].id" -o tsv)
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X PATCH \\
  "https://dev.azure.com/${org}/${project}/_apis/pipelines/pipelinePermissions/queue/${QUEUE_ID}?api-version=7.1-preview.1" \\
  -H "Content-Type: application/json" \\
  -d '{"allPipelines": {"authorized": true}}'

Authorize Queue for Specific Pipeline (REST API)

为特定 Pipeline 授权 Queue(REST API)

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X PATCH \
  "https://dev.azure.com/${org}/${project}/_apis/pipelines/pipelinePermissions/queue/<QUEUE_ID>?api-version=7.1-preview.1" \
  -H "Content-Type: application/json" \
  -d '{"pipelines": [{"id": <PIPELINE_ID>, "authorized": true}]}'

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X PATCH \\
  "https://dev.azure.com/${org}/${project}/_apis/pipelines/pipelinePermissions/queue/<QUEUE_ID>?api-version=7.1-preview.1" \\
  -H "Content-Type: application/json" \\
  -d '{"pipelines": [{"id": <PIPELINE_ID>, "authorized": true}]}'

Pipelines

Pipelines

List All

列出所有 Pipeline

bash
az pipelines list --organization "https://dev.azure.com/${org}" --project "$project" --query "[].{Name:name,ID:id,Folder:folder,QueueStatus:queueStatus}" -o table
bash
az pipelines list --organization "https://dev.azure.com/${org}" --project "$project" --query "[].{Name:name,ID:id,Folder:folder,QueueStatus:queueStatus}" -o table

List by Name Pattern

按名称模式列出

bash
az pipelines list --organization "https://dev.azure.com/${org}" --project "$project" --name "<PATTERN>*" --query "[].{Name:name,ID:id}" -o table
bash
az pipelines list --organization "https://dev.azure.com/${org}" --project "$project" --name "<PATTERN>*" --query "[].{Name:name,ID:id}" -o table

Show Details

显示详细信息

bash
az pipelines show --organization "https://dev.azure.com/${org}" --project "$project" --name <PIPELINE_NAME>
bash
az pipelines show --organization "https://dev.azure.com/${org}" --project "$project" --name <PIPELINE_NAME>

Get Pipeline ID by Name

按名称获取 Pipeline ID

bash
az pipelines list --organization "https://dev.azure.com/${org}" --project "$project" --query "[?name=='<PIPELINE_NAME>'].id" -o tsv
bash
az pipelines list --organization "https://dev.azure.com/${org}" --project "$project" --query "[?name=='<PIPELINE_NAME>'].id" -o tsv

Create

创建

bash
az pipelines create \
  --organization "https://dev.azure.com/${org}" \
  --project "$project" \
  --name <PIPELINE_NAME> \
  --repository <REPO_NAME> \
  --repository-type tfsgit \
  --branch main \
  --yml-path azure-pipelines.yml \
  --skip-first-run
bash
az pipelines create \\
  --organization "https://dev.azure.com/${org}" \\
  --project "$project" \\
  --name <PIPELINE_NAME> \\
  --repository <REPO_NAME> \\
  --repository-type tfsgit \\
  --branch main \\
  --yml-path azure-pipelines.yml \\
  --skip-first-run

Delete

删除

bash
PIPELINE_ID=$(az pipelines list --organization "https://dev.azure.com/${org}" --project "$project" --query "[?name=='<PIPELINE_NAME>'].id" -o tsv)
az pipelines delete --id $PIPELINE_ID --organization "https://dev.azure.com/${org}" --project "$project" --yes

bash
PIPELINE_ID=$(az pipelines list --organization "https://dev.azure.com/${org}" --project "$project" --query "[?name=='<PIPELINE_NAME>'].id" -o tsv)
az pipelines delete --id $PIPELINE_ID --organization "https://dev.azure.com/${org}" --project "$project" --yes

Pipeline Runs (Builds)

Pipeline Runs(Builds)

Run Pipeline

运行 Pipeline

bash
az pipelines run --organization "https://dev.azure.com/${org}" --project "$project" --name <PIPELINE_NAME>
bash
az pipelines run --organization "https://dev.azure.com/${org}" --project "$project" --name <PIPELINE_NAME>

Run and Get Run ID

运行并获取 Run ID

bash
RUN_ID=$(az pipelines run --organization "https://dev.azure.com/${org}" --project "$project" --name <PIPELINE_NAME> --query id -o tsv)
echo "Run ID: $RUN_ID"
bash
RUN_ID=$(az pipelines run --organization "https://dev.azure.com/${org}" --project "$project" --name <PIPELINE_NAME> --query id -o tsv)
echo "Run ID: $RUN_ID"

Run with Variables

使用变量运行

bash
az pipelines run --organization "https://dev.azure.com/${org}" --project "$project" --name <PIPELINE_NAME> --variables "VAR1=value1" "VAR2=value2"
bash
az pipelines run --organization "https://dev.azure.com/${org}" --project "$project" --name <PIPELINE_NAME> --variables "VAR1=value1" "VAR2=value2"

List Recent Runs

列出最近的运行

bash
az pipelines runs list --organization "https://dev.azure.com/${org}" --project "$project" --top 10 --query "[].{ID:id,Pipeline:definition.name,Status:status,Result:result,StartTime:startTime}" -o table
bash
az pipelines runs list --organization "https://dev.azure.com/${org}" --project "$project" --top 10 --query "[].{ID:id,Pipeline:definition.name,Status:status,Result:result,StartTime:startTime}" -o table

List Runs for Specific Pipeline

列出特定 Pipeline 的运行

bash
PIPELINE_ID=$(az pipelines list --organization "https://dev.azure.com/${org}" --project "$project" --query "[?name=='<PIPELINE_NAME>'].id" -o tsv)
az pipelines runs list --organization "https://dev.azure.com/${org}" --project "$project" --pipeline-ids $PIPELINE_ID --query "[].{ID:id,Status:status,Result:result}" -o table
bash
PIPELINE_ID=$(az pipelines list --organization "https://dev.azure.com/${org}" --project "$project" --query "[?name=='<PIPELINE_NAME>'].id" -o tsv)
az pipelines runs list --organization "https://dev.azure.com/${org}" --project "$project" --pipeline-ids $PIPELINE_ID --query "[].{ID:id,Status:status,Result:result}" -o table

Show Run Status

显示运行状态

bash
az pipelines runs show --organization "https://dev.azure.com/${org}" --project "$project" --id <RUN_ID> --query "{Status:status,Result:result}" -o json
bash
az pipelines runs show --organization "https://dev.azure.com/${org}" --project "$project" --id <RUN_ID> --query "{Status:status,Result:result}" -o json

Watch Run Until Complete

监控运行直至完成

bash
RUN_ID=<RUN_ID>
while true; do
  STATUS=$(az pipelines runs show --organization "https://dev.azure.com/${org}" --project "$project" --id $RUN_ID --query status -o tsv)
  RESULT=$(az pipelines runs show --organization "https://dev.azure.com/${org}" --project "$project" --id $RUN_ID --query result -o tsv)
  echo "Status: $STATUS, Result: ${RESULT:-pending}"
  if [ "$STATUS" == "completed" ]; then break; fi
  sleep 10
done

bash
RUN_ID=<RUN_ID>
while true; do
  STATUS=$(az pipelines runs show --organization "https://dev.azure.com/${org}" --project "$project" --id $RUN_ID --query status -o tsv)
  RESULT=$(az pipelines runs show --organization "https://dev.azure.com/${org}" --project "$project" --id $RUN_ID --query result -o tsv)
  echo "Status: $STATUS, Result: ${RESULT:-pending}"
  if [ "$STATUS" == "completed" ]; then break; fi
  sleep 10
done

Build Logs

构建日志

Get Build Timeline (Stages/Jobs)

获取构建时间线(Stages/Jobs)

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \
  "https://dev.azure.com/${org}/${project}/_apis/build/builds/<RUN_ID>/timeline?api-version=7.1" \
  | jq '.records[] | {name: .name, type: .type, state: .state, result: .result}'
bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \\
  "https://dev.azure.com/${org}/${project}/_apis/build/builds/<RUN_ID>/timeline?api-version=7.1" \\
  | jq '.records[] | {name: .name, type: .type, state: .state, result: .result}'

List Build Logs

列出构建日志

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \
  "https://dev.azure.com/${org}/${project}/_apis/build/builds/<RUN_ID>/logs?api-version=7.1" \
  | jq '.value[] | {id: .id, type: .type, lineCount: .lineCount}'
bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \\
  "https://dev.azure.com/${org}/${project}/_apis/build/builds/<RUN_ID>/logs?api-version=7.1" \\
  | jq '.value[] | {id: .id, type: .type, lineCount: .lineCount}'

Download Specific Log

下载指定日志

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \
  "https://dev.azure.com/${org}/${project}/_apis/build/builds/<RUN_ID>/logs/<LOG_ID>?api-version=7.1"
bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \\
  "https://dev.azure.com/${org}/${project}/_apis/build/builds/<RUN_ID>/logs/<LOG_ID>?api-version=7.1"

Get Failed Step Logs

获取失败步骤日志

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \
  "https://dev.azure.com/${org}/${project}/_apis/build/builds/<RUN_ID>/timeline?api-version=7.1" \
  | jq '.records[] | select(.result == "failed") | {name: .name, log: .log.url}'

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \\
  "https://dev.azure.com/${org}/${project}/_apis/build/builds/<RUN_ID>/timeline?api-version=7.1" \\
  | jq '.records[] | select(.result == "failed") | {name: .name, log: .log.url}'

Git Operations (REST API)

Git 操作(REST API)

For programmatic Git workflows (branches, commits, pushes) without a local clone.
用于在无本地克隆的情况下执行程序化 Git 工作流(分支、提交、推送)。

Get Repository by Name

按名称获取存储库

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>?api-version=7.0" \
  | jq '{id: .id, name: .name, defaultBranch: .defaultBranch}'
bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \\
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>?api-version=7.0" \\
  | jq '{id: .id, name: .name, defaultBranch: .defaultBranch}'

Get Branch Refs

获取分支引用

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/refs?filter=heads/main&api-version=7.0" \
  | jq '.value[] | {name: .name, objectId: .objectId}'
bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \\
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/refs?filter=heads/main&api-version=7.0" \\
  | jq '.value[] | {name: .name, objectId: .objectId}'

Get Main Branch Commit SHA

获取主分支 Commit SHA

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/refs?filter=heads/main&api-version=7.0" \
  | jq -r '.value[0].objectId'
bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \\
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/refs?filter=heads/main&api-version=7.0" \\
  | jq -r '.value[0].objectId'

Create Branch from Main

从 main 创建分支

bash
MAIN_SHA=$(curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/refs?filter=heads/main&api-version=7.0" \
  | jq -r '.value[0].objectId')

curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X POST \
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/refs?api-version=7.0" \
  -H "Content-Type: application/json" \
  -d '[{"name": "refs/heads/<BRANCH_NAME>", "oldObjectId": "0000000000000000000000000000000000000000", "newObjectId": "'${MAIN_SHA}'"}]'
bash
MAIN_SHA=$(curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \\
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/refs?filter=heads/main&api-version=7.0" \\
  | jq -r '.value[0].objectId')

curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X POST \\
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/refs?api-version=7.0" \\
  -H "Content-Type: application/json" \\
  -d '[{"name": "refs/heads/<BRANCH_NAME>", "oldObjectId": "0000000000000000000000000000000000000000", "newObjectId": "'${MAIN_SHA}'"}]'

Delete Branch

删除分支

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X POST \
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/refs?api-version=7.0" \
  -H "Content-Type: application/json" \
  -d '[{"name": "refs/heads/<BRANCH_NAME>", "oldObjectId": "<LAST_COMMIT_SHA>", "newObjectId": "0000000000000000000000000000000000000000"}]'
bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X POST \\
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/refs?api-version=7.0" \\
  -H "Content-Type: application/json" \\
  -d '[{"name": "refs/heads/<BRANCH_NAME>", "oldObjectId": "<LAST_COMMIT_SHA>", "newObjectId": "0000000000000000000000000000000000000000"}]'

Push a Commit (Add/Edit Files)

推送提交(添加/编辑文件)

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X POST \
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/pushes?api-version=7.0" \
  -H "Content-Type: application/json" \
  -d '{
    "refUpdates": [{"name": "refs/heads/<BRANCH_NAME>", "oldObjectId": "<BASE_COMMIT_SHA>"}],
    "commits": [{
      "comment": "Commit message here",
      "changes": [
        {
          "changeType": "edit",
          "item": {"path": "/path/to/file"},
          "newContent": {"content": "file content here", "contentType": "rawtext"}
        }
      ]
    }]
  }'
bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X POST \\
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/pushes?api-version=7.0" \\
  -H "Content-Type: application/json" \\
  -d '{
    "refUpdates": [{"name": "refs/heads/<BRANCH_NAME>", "oldObjectId": "<BASE_COMMIT_SHA>"}],
    "commits": [{
      "comment": "Commit message here",
      "changes": [
        {
          "changeType": "edit",
          "item": {"path": "/path/to/file"},
          "newContent": {"content": "file content here", "contentType": "rawtext"}
        }
      ]
    }]
  }'

Push Initial Commit (New Repository)

推送初始提交(新存储库)

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X POST \
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/pushes?api-version=7.0" \
  -H "Content-Type: application/json" \
  -d '{
    "refUpdates": [{"name": "refs/heads/main", "oldObjectId": "0000000000000000000000000000000000000000"}],
    "commits": [{
      "comment": "Initial commit",
      "changes": [
        {
          "changeType": "add",
          "item": {"path": "/README.md"},
          "newContent": {"content": "# Repo Title", "contentType": "rawtext"}
        }
      ]
    }]
  }'
bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X POST \\
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/pushes?api-version=7.0" \\
  -H "Content-Type: application/json" \\
  -d '{
    "refUpdates": [{"name": "refs/heads/main", "oldObjectId": "0000000000000000000000000000000000000000"}],
    "commits": [{
      "comment": "Initial commit",
      "changes": [
        {
          "changeType": "add",
          "item": {"path": "/README.md"},
          "newContent": {"content": "# Repo Title", "contentType": "rawtext"}
        }
      ]
    }]
  }'

Push with Base64-Encoded Content

推送 Base64 编码内容

bash
CONTENT_B64=$(echo -n "file contents here" | base64)
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X POST \
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/pushes?api-version=7.0" \
  -H "Content-Type: application/json" \
  -d '{
    "refUpdates": [{"name": "refs/heads/<BRANCH>", "oldObjectId": "<SHA>"}],
    "commits": [{
      "comment": "Add file",
      "changes": [{
        "changeType": "add",
        "item": {"path": "/file.txt"},
        "newContent": {"content": "'${CONTENT_B64}'", "contentType": "base64encoded"}
      }]
    }]
  }'

bash
CONTENT_B64=$(echo -n "file contents here" | base64)
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X POST \\
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/pushes?api-version=7.0" \\
  -H "Content-Type: application/json" \\
  -d '{
    "refUpdates": [{"name": "refs/heads/<BRANCH>", "oldObjectId": "<SHA>"}],
    "commits": [{
      "comment": "Add file",
      "changes": [{
        "changeType": "add",
        "item": {"path": "/file.txt"},
        "newContent": {"content": "'${CONTENT_B64}'", "contentType": "base64encoded"}
      }]
    }]
  }'

Pull Requests (REST API)

Pull Requests(REST API)

Alternative to
az repos pr
commands when more control is needed.
当需要更多控制时,可替代
az repos pr
命令。

Create

创建

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X POST \
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/pullrequests?api-version=7.0" \
  -H "Content-Type: application/json" \
  -d '{
    "sourceRefName": "refs/heads/<SOURCE_BRANCH>",
    "targetRefName": "refs/heads/main",
    "title": "PR Title",
    "description": "PR description"
  }' | jq '{pullRequestId: .pullRequestId, status: .status}'
bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X POST \\
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/pullrequests?api-version=7.0" \\
  -H "Content-Type: application/json" \\
  -d '{
    "sourceRefName": "refs/heads/<SOURCE_BRANCH>",
    "targetRefName": "refs/heads/main",
    "title": "PR Title",
    "description": "PR description"
  }' | jq '{pullRequestId: .pullRequestId, status: .status}'

Get Details

获取详细信息

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/pullRequests/<PR_ID>?api-version=7.0" \
  | jq '{id: .pullRequestId, title: .title, status: .status, sourceRefName: .sourceRefName}'
bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \\
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/pullRequests/<PR_ID>?api-version=7.0" \\
  | jq '{id: .pullRequestId, title: .title, status: .status, sourceRefName: .sourceRefName}'

List

列出

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/pullrequests?api-version=7.0" \
  | jq '.value[] | {id: .pullRequestId, title: .title, status: .status}'
bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \\
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/pullrequests?api-version=7.0" \\
  | jq '.value[] | {id: .pullRequestId, title: .title, status: .status}'

Abandon

放弃

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X PATCH \
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/pullRequests/<PR_ID>?api-version=7.0" \
  -H "Content-Type: application/json" \
  -d '{"status": "abandoned"}'
bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X PATCH \\
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/pullRequests/<PR_ID>?api-version=7.0" \\
  -H "Content-Type: application/json" \\
  -d '{"status": "abandoned"}'

Complete (Merge)

完成(合并)

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X PATCH \
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/pullRequests/<PR_ID>?api-version=7.0" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "completed",
    "lastMergeSourceCommit": {"commitId": "<LAST_COMMIT_SHA>"},
    "completionOptions": {"deleteSourceBranch": true, "mergeStrategy": "squash"}
  }'

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X PATCH \\
  "https://dev.azure.com/${org}/${project}/_apis/git/repositories/<REPO_NAME>/pullRequests/<PR_ID>?api-version=7.0" \\
  -H "Content-Type: application/json" \\
  -d '{
    "status": "completed",
    "lastMergeSourceCommit": {"commitId": "<LAST_COMMIT_SHA>"},
    "completionOptions": {"deleteSourceBranch": true, "mergeStrategy": "squash"}
  }'

Code Search (REST API)

代码搜索(REST API)

Search code across repositories. Uses the
almsearch.dev.azure.com
host, not
dev.azure.com
.
跨存储库搜索代码。使用
almsearch.dev.azure.com
主机,而不是
dev.azure.com
。

Search in Project

在项目中搜索

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X POST \
  "https://almsearch.dev.azure.com/${org}/${project}/_apis/search/codesearchresults?api-version=7.1" \
  -H "Content-Type: application/json" \
  -d '{"searchText":"<TEXT>","$top":25}' \
  | jq '{count: .count, results: [.results[] | {repo: .repository.name, path: .path}]}'
bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X POST \\
  "https://almsearch.dev.azure.com/${org}/${project}/_apis/search/codesearchresults?api-version=7.1" \\
  -H "Content-Type: application/json" \\
  -d '{"searchText":"<TEXT>","$top":25}' \\
  | jq '{count: .count, results: [.results[] | {repo: .repository.name, path: .path}]}'

Search Across Org with Filters

使用过滤器跨组织搜索

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X POST \
  "https://almsearch.dev.azure.com/${org}/_apis/search/codesearchresults?api-version=7.1" \
  -H "Content-Type: application/json" \
  -d '{
    "searchText":"<TEXT>",
    "filters":{"Project":["<PROJECT>"],"Repository":["<REPO>"],"Branch":["main"],"Path":["/src"]},
    "$top":25
  }' \
  | jq '.results[] | {project: .project.name, repo: .repository.name, path: .path}'
Available filter keys:
Project
,
Repository
,
Branch
,
Path
,
CodeElement
(e.g.
["def","class"]
).
bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X POST \\
  "https://almsearch.dev.azure.com/${org}/_apis/search/codesearchresults?api-version=7.1" \\
  -H "Content-Type: application/json" \\
  -d '{
    "searchText":"<TEXT>",
    "filters":{"Project":["<PROJECT>"],"Repository":["<REPO>"],"Branch":["main"],"Path":["/src"]},
    "$top":25
  }' \\
  | jq '.results[] | {project: .project.name, repo: .repository.name, path: .path}'
可用过滤器键:
Project
、
Repository
、
Branch
、
Path
、
CodeElement
(例如
["def","class"]
)。

Search Operators

搜索运算符

The
searchText
field accepts ADO search syntax:
  • ext:go quiver-bolt
    -- file extension filter
  • file:Makefile quiver-bolt
    -- filename filter
  • def:MyFunction
    -- function/method definitions
  • "exact phrase"
    -- exact match
  • foo AND bar
    ,
    foo OR bar
    ,
    foo NOT bar
    -- boolean

searchText
字段接受 ADO 搜索语法:
  • ext:go quiver-bolt
    —— 文件扩展名过滤
  • file:Makefile quiver-bolt
    —— 文件名过滤
  • def:MyFunction
    —— 函数/方法定义
  • "exact phrase"
    —— 精确匹配
  • foo AND bar
    、
    foo OR bar
    、
    foo NOT bar
    —— 布尔运算

Webhooks (REST API)

Webhooks(REST API)

List Service Hooks

列出 Service Hooks

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \
  "https://dev.azure.com/${org}/_apis/hooks/subscriptions?api-version=7.0" \
  | jq '.value[] | {id: .id, eventType: .eventType, consumerActionId: .consumerActionId, publisherInputs: .publisherInputs}'
bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" \\
  "https://dev.azure.com/${org}/_apis/hooks/subscriptions?api-version=7.0" \\
  | jq '.value[] | {id: .id, eventType: .eventType, consumerActionId: .consumerActionId, publisherInputs: .publisherInputs}'

Create Webhook for PR Events

为 PR 事件创建 Webhook

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X POST \
  "https://dev.azure.com/${org}/_apis/hooks/subscriptions?api-version=7.0" \
  -H "Content-Type: application/json" \
  -d '{
    "publisherId": "tfs",
    "eventType": "git.pullrequest.created",
    "resourceVersion": "1.0",
    "consumerId": "webHooks",
    "consumerActionId": "httpRequest",
    "publisherInputs": {
      "projectId": "<PROJECT_ID>",
      "repository": "<REPO_ID>"
    },
    "consumerInputs": {
      "url": "<WEBHOOK_URL>"
    }
  }'
bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X POST \\
  "https://dev.azure.com/${org}/_apis/hooks/subscriptions?api-version=7.0" \\
  -H "Content-Type: application/json" \\
  -d '{
    "publisherId": "tfs",
    "eventType": "git.pullrequest.created",
    "resourceVersion": "1.0",
    "consumerId": "webHooks",
    "consumerActionId": "httpRequest",
    "publisherInputs": {
      "projectId": "<PROJECT_ID>",
      "repository": "<REPO_ID>"
    },
    "consumerInputs": {
      "url": "<WEBHOOK_URL>"
    }
  }'

Delete Webhook

删除 Webhook

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X DELETE \
  "https://dev.azure.com/${org}/_apis/hooks/subscriptions/<SUBSCRIPTION_ID>?api-version=7.0"

bash
curl -s -u ":${AZURE_DEVOPS_EXT_PAT}" -X DELETE \\
  "https://dev.azure.com/${org}/_apis/hooks/subscriptions/<SUBSCRIPTION_ID>?api-version=7.0"

Diagnostics

诊断

Check ADO Infrastructure Health

检查 ADO 基础设施运行状况

bash
echo "=== Service Connections ==="
az devops service-endpoint list --organization "https://dev.azure.com/${org}" --project "$project" --query "[].{Name:name,Type:type}" -o table

echo ""
echo "=== Agent Pools ==="
az pipelines pool list --organization "https://dev.azure.com/${org}" --query "[].{Name:name,Size:size,IsHosted:isHosted}" -o table

echo ""
echo "=== Queues ==="
az pipelines queue list --organization "https://dev.azure.com/${org}" --project "$project" --query "[].{Name:name,QueueID:id}" -o table
bash
echo "=== Service Connections ==="
az devops service-endpoint list --organization "https://dev.azure.com/${org}" --project "$project" --query "[].{Name:name,Type:type}" -o table

echo ""
echo "=== Agent Pools ==="
az pipelines pool list --organization "https://dev.azure.com/${org}" --query "[].{Name:name,Size:size,IsHosted:isHosted}" -o table

echo ""
echo "=== Queues ==="
az pipelines queue list --organization "https://dev.azure.com/${org}" --project "$project" --query "[].{Name:name,QueueID:id}" -o table

Check Agents in a Pool

检查 Pool 中的 Agent

bash
POOL_ID=$(az pipelines pool list --organization "https://dev.azure.com/${org}" --query "[?name=='<POOL_NAME>'].id" -o tsv)
if [ -n "$POOL_ID" ]; then
  az pipelines agent list --organization "https://dev.azure.com/${org}" --pool-id $POOL_ID --query "[].{Name:name,Status:status}" -o table
fi
bash
POOL_ID=$(az pipelines pool list --organization "https://dev.azure.com/${org}" --query "[?name=='<POOL_NAME>'].id" -o tsv)
if [ -n "$POOL_ID" ]; then
  az pipelines agent list --organization "https://dev.azure.com/${org}" --pool-id $POOL_ID --query "[].{Name:name,Status:status}" -o table
fi

Wait for Agents to Come Online

等待 Agent 上线

bash
POOL_ID=$(az pipelines pool list --organization "https://dev.azure.com/${org}" --query "[?name=='<POOL_NAME>'].id" -o tsv)
MAX_WAIT=300
ELAPSED=0
while [ $ELAPSED -lt $MAX_WAIT ]; do
  ONLINE=$(az pipelines agent list --organization "https://dev.azure.com/${org}" --pool-id $POOL_ID --query "[?status=='online']" -o tsv | wc -l)
  if [ "$ONLINE" -gt 0 ]; then
    echo "Found $ONLINE online agent(s)"
    break
  fi
  echo "Waiting for agents... ($ELAPSED/${MAX_WAIT}s)"
  sleep 10
  ELAPSED=$((ELAPSED + 10))
done

bash
POOL_ID=$(az pipelines pool list --organization "https://dev.azure.com/${org}" --query "[?name=='<POOL_NAME>'].id" -o tsv)
MAX_WAIT=300
ELAPSED=0
while [ $ELAPSED -lt $MAX_WAIT ]; do
  ONLINE=$(az pipelines agent list --organization "https://dev.azure.com/${org}" --pool-id $POOL_ID --query "[?status=='online']" -o tsv | wc -l)
  if [ "$ONLINE" -gt 0 ]; then
    echo "Found $ONLINE online agent(s)"
    break
  fi
  echo "Waiting for agents... ($ELAPSED/${MAX_WAIT}s)"
  sleep 10
  ELAPSED=$((ELAPSED + 10))
done

Key Concepts

核心概念

Pool vs Queue

Pool 与 Queue

  • Pools are organization-level (shared across projects)
  • Queues are project-level references to pools
  • Pipeline authorization works on queues, not pools
  • Pools 属于组织级别(跨项目共享)
  • Queues 是对 Pool 的项目级引用
  • Pipeline 授权作用于 queues,而不是 pools

Workload Identity Federation

Workload Identity Federation

Service connections use WIF (OIDC). No secrets stored in ADO. Federated credentials are managed in App Registration.
Service Connections 使用 WIF(OIDC)。ADO 中不会存储 Secret。联合凭据由 App Registration 管理。

REST API vs CLI

REST API 与 CLI

Some operations require REST API (no CLI equivalent):
  • Creating pools with specific settings
  • Authorizing queues for pipelines
  • Querying WIF subjects from service connections
  • Git push operations (branches, commits)
  • PR comment threads
  • Webhooks
有些操作必须使用 REST API(没有等效的 CLI 命令):
  • 使用特定设置创建 Pools
  • 为 Pipelines 授权 Queues
  • 查询 Service Connections 中的 WIF subject
  • Git push 操作(分支、提交)
  • PR 评论线程
  • Webhooks