Azure DevOps发布定义API增删模板化Stage的可行性及示例咨询
Absolutely, this requirement is totally feasible! Let’s break this down for you:
Yes, 100%. You can automate adding/removing stages in an Azure DevOps Release Definition via the REST API, and GitHub Actions is an ideal tool to trigger these actions based on pull request and branch events.
Definitely. The key API you’ll use is the Release Definitions - Update endpoint (note: this is different from the "Update Release" endpoint you referenced—we need to modify the definition itself, not individual releases). Recent API versions (like 7.1-preview.3) make this straightforward, as you can patch the definition's environments collection (stages are called "environments" in the API schema).
Here’s how to implement this with GitHub Actions. First, make sure you have a Personal Access Token (PAT) for Azure DevOps with Edit permissions on Release Definitions, stored as a GitHub Secret (e.g., AZURE_DEVOPS_PAT).
1. Add Stage When a PR is Opened
This workflow triggers when a PR is opened against your target branch, and adds a new stage from your template:
name: Add Release Stage on PR on: pull_request: types: [opened] branches: [x] # Your target branch jobs: add-stage: runs-on: ubuntu-latest steps: - name: Set up Azure DevOps token run: | echo "AZURE_DEVOPS_TOKEN=${{ secrets.AZURE_DEVOPS_PAT }}" >> $GITHUB_ENV - name: Create new stage from template run: | # Sanitize branch name to avoid invalid characters in stage name BRANCH_NAME=$(echo "${{ github.head_ref }}" | tr '/' '-') # Calculate next stage rank (add to end of existing stages) NEXT_RANK=$(curl -s -H "Authorization: Bearer ${{ env.AZURE_DEVOPS_TOKEN }}" \ "https://vsrm.dev.azure.com/your-org/your-project/_apis/release/definitions/your-def-id?api-version=7.1-preview.3" \ | jq '.environments | length + 1') curl -X PATCH \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${{ env.AZURE_DEVOPS_TOKEN }}" \ -d '{ "environments": [ { "name": "PR-Stage-'$BRANCH_NAME'", "rank": '$NEXT_RANK', "deployPhases": [ { "deploymentInput": { "parallelExecution": {"parallelExecutionType": "none"}, "skipArtifactsDownload": false, "timeoutInMinutes": 30, "queueId": 123, # Replace with your agent queue ID "demands": [] }, "rank": 1, "phaseType": "agentBasedDeployment", "name": "Agent Job", # Replace with your template tasks or task group reference "workflowTasks": [ { "taskId": "e213ff0f-5d5c-4791-802d-52ea3e7be1f1", "versionSpec": "2.*", "name": "PowerShell", "inputs": {"scriptType": "inline", "script": "Write-Host \"Deploying PR branch: '$BRANCH_NAME'\""} } ] } ] } ] }' \ "https://vsrm.dev.azure.com/your-org/your-project/_apis/release/definitions/your-def-id?api-version=7.1-preview.3"
2. Remove Stage When a Branch is Deleted
This workflow triggers when a branch is deleted, and removes the corresponding stage from the release definition:
name: Remove Release Stage on Branch Delete on: delete: branches: - '*' # Target specific branches if needed jobs: remove-stage: runs-on: ubuntu-latest steps: - name: Set up Azure DevOps token run: | echo "AZURE_DEVOPS_TOKEN=${{ secrets.AZURE_DEVOPS_PAT }}" >> $GITHUB_ENV - name: Remove matching stage run: | # Extract and sanitize branch name from the deleted ref BRANCH_NAME=$(echo "${{ github.event.ref }}" | sed 's/refs\/heads\///' | tr '/' '-') STAGE_NAME="PR-Stage-'$BRANCH_NAME'" # Fetch the release definition to get the stage ID DEFINITION=$(curl -s -H "Authorization: Bearer ${{ env.AZURE_DEVOPS_TOKEN }}" \ "https://vsrm.dev.azure.com/your-org/your-project/_apis/release/definitions/your-def-id?api-version=7.1-preview.3") STAGE_ID=$(echo $DEFINITION | jq -r --arg STAGE_NAME "$STAGE_NAME" '.environments[] | select(.name == $STAGE_NAME) | .id') # Delete the stage if it exists if [ "$STAGE_ID" != "null" ]; then curl -X PATCH \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${{ env.AZURE_DEVOPS_TOKEN }}" \ -d '{ "environments": [ {"id": '$STAGE_ID', "isDeleted": true} ] }' \ "https://vsrm.dev.azure.com/your-org/your-project/_apis/release/definitions/your-def-id?api-version=7.1-preview.3" echo "Stage $STAGE_NAME (ID: $STAGE_ID) removed successfully" else echo "Stage $STAGE_NAME not found—no action taken" fi
- Sanitize Branch Names: Slashes and special characters in branch names can break stage naming rules, so use tools like
trorsedto clean them up. - PAT Permissions: Ensure your AZURE_DEVOPS_PAT has the Release Definitions (Edit) permission in Azure DevOps.
- Template Reuse: To avoid duplicating task code, store your stage template as a JSON file in your repo, then use
jqto inject variables (like branch name) before sending the API request. - API Version: Use a recent preview version (like
7.1-preview.3) for better compatibility and features compared to older versions like 5.1.
内容的提问来源于stack exchange,提问作者Steve Cuthill

