|
| 1 | +# Release Plan Auto-Generation |
| 2 | + |
| 3 | +This document explains how release plans are automatically discovered or created by the `eng/tools/release-plan` tool and the `eng/pipelines/release-plan.yml` pipeline. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +The release-plan pipeline is a post-merge automation for specification updates. |
| 8 | + |
| 9 | +High-level lifecycle: |
| 10 | + |
| 11 | +1. A spec PR merges into `main` in `Azure/azure-rest-api-specs` or `Azure/azure-rest-api-specs-pr`. |
| 12 | +2. The pipeline is triggered by changes under `specification/**`. |
| 13 | +3. Stage (`ReleasePlanCreation`) runs and resolves the commit SHA to analyze. |
| 14 | +4. The tool tries to map the commit to an associated PR and inspects TypeSpec changes. |
| 15 | +5. The tool first attempts to find an existing release plan. |
| 16 | +6. The tool creates a release plan only when creation is allowed by label policy and if a release plan does not exists. |
| 17 | +7. The pipeline always emits a JSON result artifact for downstream stages/jobs. |
| 18 | + |
| 19 | +From pipeline execution perspective, the release-plan tool operates in this order: |
| 20 | + |
| 21 | +1. Resolve associated PR from commit SHA (if any). |
| 22 | +2. Detect TypeSpec project and API version from changed spec files. |
| 23 | +3. Check whether the associated PR has the `new-api-version` label. |
| 24 | +4. Find an existing release plan first. |
| 25 | +5. Create a new release plan only when allowed. |
| 26 | +6. Publish JSON output as a pipeline artifact. |
| 27 | + |
| 28 | +## Trigger Model (When This Runs) |
| 29 | + |
| 30 | +Pipeline trigger behavior in `eng/pipelines/release-plan.yml`: |
| 31 | + |
| 32 | +- `trigger.paths.include: specification/**` |
| 33 | +- `pr: none` |
| 34 | + |
| 35 | +Meaning: |
| 36 | + |
| 37 | +- This pipeline does not run as a PR-validation pipeline. |
| 38 | +- It runs on branch updates (CI trigger) when files under `specification/**` change. |
| 39 | +- In the common path, this happens automatically after a spec PR is merged to `main`. |
| 40 | + |
| 41 | +Commit SHA source: |
| 42 | + |
| 43 | +1. Primary: `$(Build.SourceVersion)` |
| 44 | +2. Fallback: repository `HEAD` via `git rev-parse HEAD` when `Build.SourceVersion` is empty |
| 45 | + |
| 46 | +So after a merge to `main`, the pipeline analyzes the latest merged commit (or latest `HEAD` if fallback is needed). |
| 47 | + |
| 48 | +## Inputs |
| 49 | + |
| 50 | +The tool is invoked with: |
| 51 | + |
| 52 | +- `--commit-sha`: commit to analyze |
| 53 | +- `--repo`: repository in `owner/repo` format |
| 54 | +- `--workspace`: local repo path |
| 55 | +- `--azsdk-path`: azsdk CLI path |
| 56 | +- `--output-file`: optional JSON output path for artifact publishing |
| 57 | + |
| 58 | +## How TypeSpec Project Is Determined |
| 59 | + |
| 60 | +Changed files are inspected under `specification/**`. |
| 61 | + |
| 62 | +Project detection logic: |
| 63 | + |
| 64 | +1. Prefer changed `tspconfig.yaml` paths. |
| 65 | +2. Otherwise, walk up from changed files to find nearest `tspconfig.yaml`. |
| 66 | +3. If no project is found: no release plan action. |
| 67 | +4. If multiple projects are found: no automatic create (manual handling required). |
| 68 | + |
| 69 | +## How API Version Is Determined |
| 70 | + |
| 71 | +API version is selected from detected project changes in this order: |
| 72 | + |
| 73 | +1. Version-like strings found in changed file paths (`YYYY-MM-DD` or `YYYY-MM-DD-preview`). |
| 74 | +2. If not found, scan project `main.tsp` for version-like strings. |
| 75 | +3. Sort versions descending and pick the first one. |
| 76 | + |
| 77 | +Sorting rules: |
| 78 | + |
| 79 | +- Newer date wins. |
| 80 | +- For same date, GA wins over `-preview`. |
| 81 | + |
| 82 | +Result: |
| 83 | + |
| 84 | +- Selected value is used as `apiVersion` in release-plan metadata. |
| 85 | +- Preview detection (`-preview`) drives SDK release type and API release type mapping. |
| 86 | + |
| 87 | +## Create vs No-Create Scenarios |
| 88 | + |
| 89 | +### Scenario A: Associated PR has `new-api-version` label |
| 90 | + |
| 91 | +Behavior: |
| 92 | + |
| 93 | +1. Try `release-plan get --pull-request` (if PR URL exists). |
| 94 | +2. Try `release-plan get --typespec-path --api-release-type`. |
| 95 | +3. If still not found, run `release-plan create`. |
| 96 | + |
| 97 | +Outcome: |
| 98 | + |
| 99 | +- Existing plan is returned if found. |
| 100 | +- New plan is created only in this scenario. |
| 101 | + |
| 102 | +### Scenario B: Associated PR does NOT have `new-api-version` label |
| 103 | + |
| 104 | +Behavior: |
| 105 | + |
| 106 | +1. Try `release-plan get --pull-request` (if PR URL exists). |
| 107 | +2. Try `release-plan get --typespec-path --api-release-type`. |
| 108 | +3. Do NOT create a new release plan. |
| 109 | + |
| 110 | +Outcome: |
| 111 | + |
| 112 | +- Existing plan is returned if present. |
| 113 | +- If no existing plan is found, result is `not_found`. |
| 114 | + |
| 115 | +### Scenario C: No PR associated with commit SHA |
| 116 | + |
| 117 | +Behavior: |
| 118 | + |
| 119 | +- Project/version detection falls back to commit-level file changes. |
| 120 | +- PR URL is unavailable. |
| 121 | +- Existing-by-path lookup still runs. |
| 122 | +- Create is not possible without PR URL and is skipped unless a PR is resolved. |
| 123 | + |
| 124 | +Outcome: |
| 125 | + |
| 126 | +- Existing plan may still be returned by path. |
| 127 | +- If none found and create is not allowed, result is `not_found`. |
| 128 | + |
| 129 | +## API Release Type and SDK Release Type |
| 130 | + |
| 131 | +It uses selected API version status and repo name: |
| 132 | + |
| 133 | +- Repo `azure-rest-api-specs-pr` -> API release type: `Private Preview` |
| 134 | +- Repo `azure-rest-api-specs`: |
| 135 | + - preview API version -> `Public Preview` |
| 136 | + - stable API version -> `GA` |
| 137 | + |
| 138 | +SDK release type: |
| 139 | + |
| 140 | +- preview API version -> `preview` |
| 141 | +- stable API version -> `stable` |
| 142 | + |
| 143 | +## PR Comment Behavior |
| 144 | + |
| 145 | +PR comment is posted only when: |
| 146 | + |
| 147 | +- A new release plan is created, and |
| 148 | +- An associated PR number is available. |
| 149 | + |
| 150 | +## Pipeline Artifact Output |
| 151 | + |
| 152 | +The pipeline writes release-plan result JSON to: |
| 153 | + |
| 154 | +- `$(Build.ArtifactStagingDirectory)/release-plan/release-plan.json` |
| 155 | + |
| 156 | +It publishes artifact: |
| 157 | + |
| 158 | +- `release-plan-details` |
| 159 | + |
| 160 | +If no file is generated, pipeline creates a fallback JSON: |
| 161 | + |
| 162 | +- `{"outcome":"not_found","releasePlan":null,"details":{}}` |
| 163 | + |
| 164 | +## Stage Layout |
| 165 | + |
| 166 | +Current pipeline stage: |
| 167 | + |
| 168 | +- Stage 1: `ReleasePlanCreation` |
| 169 | + |
| 170 | +This stage: |
| 171 | + |
| 172 | +- Authenticates npm |
| 173 | +- Logs into GitHub |
| 174 | +- Installs azsdk CLI |
| 175 | +- Runs release-plan tool |
| 176 | +- Publishes release-plan details artifact |
| 177 | + |
| 178 | + |
| 179 | +## Future enhancement |
| 180 | + |
| 181 | +Run SDK generation for the release plan as stage 2 using release plan details identified in stage 1. |
0 commit comments