This Skill is responsible forgetting Pipelines running: triggering, tracking, canceling. Triggering and canceling are both write actions, so always list the contents for the user to confirm first. The Run ID is the build ID; the details of the build result (logs, changes) are left to pipelines-build-summary。
Project selection
-
If the user has provided a project name (for example "Contoso project"), use it directly and do not call the project list API.
-
If not provided, ask the user to provide it once.
-
If still not provided, list the projects for the user to choose:
curl -sS -u ":$AZURE_DEVOPS_PAT" \ "https://dev.azure.com/$AZURE_DEVOPS_ORG/_apis/projects?%24top=500&api-version=7.1" -
Do not continue until the user provides or selects a project.
Pipeline selection
-
When the user has provided a Pipeline name, filter by name to find the ID (
namecan use*wildcards, for exampleCI*; if multiple are found, ask the user to choose one):curl -sS -u ":$AZURE_DEVOPS_PAT" \ "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/build/definitions?name={name}&api-version=7.1" -
If not provided, ask the user to provide it once; if still not provided, list all Pipelines (
value[].id、name、folder) for the user to choose:curl -sS -u ":$AZURE_DEVOPS_PAT" \ "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/pipelines?api-version=7.1" -
Determine the type: get a single Pipeline,
configuration.typeforyamluse rule 1, fordesignerJson(classic) use rule 2:curl -sS -u ":$AZURE_DEVOPS_PAT" \ "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/pipelines/{pipelineId}?api-version=7.1" -
Get the build definition and check whether it can be queued and which variables can be overridden at runtime.
process.typeis2is YAML,1is classic;queueStatusisdisabledcannot be run,pausedwill be queued but will not start, inform the user first;variables.{name}.allowOverrideonly variables that aretruecan be specified at runtime:curl -sS -u ":$AZURE_DEVOPS_PAT" \ "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/build/definitions/{pipelineId}?api-version=7.1"
Connection and authentication
Always use curl to call the Azure DevOps REST API directly; each command carries its own authentication parameters.
- Organization: read the environment variable
AZURE_DEVOPS_ORG(organization name, for examplecontoso). If not set, ask the user once; if the user gives a URL, extract the organization name fromhttps://dev.azure.com/{org}orhttps://{org}.visualstudio.com. - Token: send the PAT with Basic authentication:
-u ":$AZURE_DEVOPS_PAT"; if onlyAZURE_DEVOPS_EXT_PATis set (the variable used by the Azure CLI azure-devops extension), use that instead. When using a Microsoft Entra ID token, switch to-H "Authorization: Bearer $AZURE_DEVOPS_TOKEN". If neither is set, ask the user to setAZURE_DEVOPS_PATin their own terminal and retry, and stop. Read tokens only from environment variables: do not ask the user to paste the token into the conversation, and do not print it or write it to a file. - PAT permission scopes: reading (listing Pipelines, tracking runs) requires Build (Read); triggering,
previewRundry run, and canceling require Build (Read & execute). - Encoding: project and Pipeline names in paths and query strings must be URL-encoded (spaces written as
%20); in query strings,$is written as%24(for example%24top), to avoid shell expansion. - Error: HTTP 401, 403, 203, or the response being an HTML login page means the token is invalid, expired, or lacks sufficient permissions; report it and stop. HTTP 404 means the organization, project, pipeline, or build ID is incorrect. HTTP 400 with
typeKeybeingPipelineValidationExceptionmeans YAML, parameter, or branch validation failed; show the originalmessagetext to the user. - Windows PowerShell: Call
curl.exe(not thecurlalias), write environment variables as$env:AZURE_DEVOPS_PAT; PowerShell does not support<<'EOF'; first write the JSON body to a temporary file, then send it with--data-binary "@body.json".
Rules
1. Run a YAML pipeline (write, dry run first)
-
Organize the run details:
- Branch: Write it as a full ref (
refs/heads/main); when the user does not specify one, use the definedrepository.defaultBranch, and explain this at confirmation. To specify a commit, add the"version": "{commitSha}"。 - parameter(
templateParameters): Names and values are provided by the user. When unsure which parameters exist, look at thetemplateParametersused in recent runs (the runs list in rule 3), or first do a dry run without parameters and infer from thefinalYamland error messages (for example,Unexpected parameter 'x'means the name is wrong; when a required parameter is missing, the message will name it). Do not try to use git or the items API to read the YAML file to infer parameters: the YAML may reference templates or be stored on GitHub. - Variables(
variables): You can only specify variables whoseallowOverrideistrue; variables written only in the YAML cannot be overridden at run time, so tell the user first. Set secret values to"isSecret": true, and do not repeat them in the conversation. - Skipped stages(
stagesToSkip): Use the stage's identifier name, not the display name. You can getGET .../_apis/build/builds/{buildId}/timeline?api-version=7.1from the most recent run's timeline (type) for records whereStageisidentifier。
- Branch: Write it as a full ref (
-
Dry run: Send
"previewRun": true. A dry run does not create a run (the responseidis-1、stateisunknown),finalYamlis the full YAML after template expansion:curl -sS -u ":$AZURE_DEVOPS_PAT" -X POST -H "Content-Type: application/json" \ "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/pipelines/{pipelineId}/runs?api-version=7.1" \ --data-binary @- <<'EOF' { "previewRun": true, "resources": {"repositories": {"self": {"refName": "refs/heads/main"}}}, "templateParameters": {"environment": "dev"}, "variables": {"LogLevel": {"value": "Debug", "isSecret": false}}, "stagesToSkip": [] } EOFWhen the response is HTTP 400, show the error message to the user, fix it, and dry run again.
-
Confirm: List the content about to be sent to the user, and execute only after one confirmation: pipeline name, branch (and commit), each parameter and value, overridden variables (secret values shown as
***), skipped stages, and the list of stages and jobs organized fromfinalYaml(for example, "will deploy to prod"). -
Run: Send the same body as the dry run, only removing
previewRun:curl -sS -u ":$AZURE_DEVOPS_PAT" -X POST -H "Content-Type: application/json" \ "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/pipelines/{pipelineId}/runs?api-version=7.1" \ --data-binary @- <<'EOF' { "resources": {"repositories": {"self": {"refName": "refs/heads/main"}}}, "templateParameters": {"environment": "dev"}, "variables": {"LogLevel": {"value": "Debug", "isSecret": false}}, "stagesToSkip": [] } EOFIn the response,
idis the Run ID (also the build ID),nameis the build number, and_links.web.hrefis the web link. Then track it using rule 3.
Example: "Run MyApp-CD in the Contoso project using the release/2.0 branch, with environment set to staging", "Run MyApp-CI but skip the Deploy stage"
2. Run a classic pipeline (write)
Classic pipelines do not support the Runs API or dry runs; use the Builds API instead. List the pipeline, branch, and variables to the user, and execute only after one confirmation.parameters isJSON string(not an object), containing only allowOverride is true variables:
curl -sS -u ":$AZURE_DEVOPS_PAT" -X POST -H "Content-Type: application/json" \
"https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/build/builds?api-version=7.1" \
-d '{"definition":{"id":101},"sourceBranch":"refs/heads/main","parameters":"{\"BuildConfiguration\":\"Release\"}"}'
Response's id is the build ID,status usually notStarted. Then trace using rule 3.
Example: "Queue a build for the Contoso project Legacy-Build with BuildConfiguration set to Debug"
3. Trace execution to completion
-
Get the run status.
stateisinProgress、cancelingorcompleted; after completionresultissucceeded、failedorcanceled:curl -sS -u ":$AZURE_DEVOPS_PAT" \ "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/pipelines/{pipelineId}/runs/{runId}?api-version=7.1"For classic Pipeline or when the Pipeline ID is unknown, use
GET .../_apis/build/builds/{buildId}?api-version=7.1(status:notStarted、inProgress、cancelling、completed;resultadditionally haspartiallySucceeded)。 -
List the recent runs of a Pipeline (including each run's
templateParameters):GET .../_apis/pipelines/{pipelineId}/runs?api-version=7.1。 -
Check roughly every 30 seconds (between the two queries
sleep 30), and only report the parts whose status changed each time. When the cumulative wait exceeds about 15 minutes, first ask the user whether to keep waiting; if not, provide the web link and stop. -
When it has been stuck in
inProgressfor a long time, fetch the timeline to check whether it is waiting for approval:typeisCheckpoint.ApprovalandstateisinProgress, that is the pending approval; search upward forparentIdtotypeisStageto find out which stage it is. Inform the user and switch topipelines-approvals, do not wait idly. -
At the end:
succeeded: report the elapsed time and link.failedorpartiallySucceeded: switch topipelines-build-summary's "View logs for the failed build", passing in the build ID to find the failed step.canceled: explain who canceled it (the build'slastChangedBy.displayName)。
Example: "Has that run finished yet?", "Please watch run 12345 for me until it finishes"
4. Cancel a running build (write)
-
First use
GET .../_apis/build/builds/{buildId}?api-version=7.1to confirmstatusisnotStartedorinProgress; a completed build cannot be canceled, just explain that. -
List the build number, Pipeline name, branch, requester (
requestedFor.displayName), start time, and current progress for the user, and execute only after one confirmation:curl -sS -u ":$AZURE_DEVOPS_PAT" -X PATCH -H "Content-Type: application/json" \ "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/build/builds/{buildId}?api-version=7.1" \ -d '{"status":"cancelling"}' -
Response's
statuswill becancelling; query again untilstatusiscompletedandresultiscanceled。
Do not provide instructions for deleting builds; when deletion is needed, ask the user to do it themselves on the web page.
Example: "Cancel build 12345 for the Contoso project"
Presenting results
Display times in the user's local time zone (format YYYY/MM/DD HH:MM), and mark UTC when the time zone cannot be determined. The build link format is https://dev.azure.com/{organization}/{project}/_build/results?buildId={runId}; remove refs/heads/。
- Confirmation screen(before execution): list the Pipeline, type (YAML/classic), branch, parameters, variables, and skipped stages in a table; for YAML also attach the
finalYaml-compiled list of stages and jobs. - Triggered: Run ID (clickable link), build number, branch, trigger time.
- Trace progress: current status, elapsed time; when waiting for approval, mark ⏸️ and the stage name.
- Result: ✅ succeeded, ❌ failed, ⚠️ partiallySucceeded, 🚫 canceled, plus elapsed time; when failed, include the suggestion to switch to
pipelines-build-summary.