Update release processes to support release servicing branches (#1620)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
parent
2ce15f4c8a
commit
4498146a83
1 changed files with 199 additions and 86 deletions
114
.github/skills/prepare-release/SKILL.md
vendored
114
.github/skills/prepare-release/SKILL.md
vendored
|
|
@ -12,22 +12,39 @@ Prepare a new release for the `modelcontextprotocol/csharp-sdk` repository. This
|
|||
|
||||
> **User confirmation required: This skill NEVER pushes a branch or creates a pull request without explicit user confirmation.** The user must review and approve all details before any remote operations occur.
|
||||
|
||||
Use the shared [release branch reference](../shared-resources/release-branches.md) for branch roles, previous-release lookup rules, and release work-branch naming.
|
||||
|
||||
## Process
|
||||
|
||||
Work through each step sequentially. Present findings at each step and get user confirmation before proceeding. Skip any step that has no applicable items.
|
||||
|
||||
### Step 1: Determine Target and Gather PRs
|
||||
### Step 1: Select Source Branch
|
||||
|
||||
List candidate source/base branches via:
|
||||
`gh api repos/{owner}/{repo}/branches --paginate --jq '[.[] | select(.name == "main" or (.name | startswith("release/"))) | .name]'`
|
||||
|
||||
Present the list to the user and ask them to choose the source/base branch. Default selection: `main`.
|
||||
|
||||
The selected branch drives every subsequent step:
|
||||
1. The branch on which the candidate version is read from `src/Directory.Build.props`.
|
||||
2. The "previous release" lookup (constrained to `v{MAJOR}.*` on `release/{MAJOR}.x`).
|
||||
3. The commit range from which PRs are collected.
|
||||
4. The PR base (`--base`) for `gh pr create` at the end of the skill.
|
||||
|
||||
See [release-branches.md](../shared-resources/release-branches.md) for the structured branch rules.
|
||||
|
||||
### Step 2: Determine Target and Gather PRs
|
||||
|
||||
The user may provide:
|
||||
- **A git ref** (commit SHA, branch, or tag) — use as the target commit
|
||||
- **No context** — show the last 5 commits on `main` (noting HEAD) and offer the option to enter a branch or tag name instead
|
||||
- **A git ref** (commit SHA, branch, or tag) — use as the target commit relative to the selected source/base branch
|
||||
- **No context** — show the last 5 commits on the selected source/base branch (noting HEAD) and offer the option to enter a branch or tag name instead
|
||||
|
||||
Once the target is established:
|
||||
1. Determine the previous release tag from `gh release list` (most recent **published** release — exclude drafts with `--exclude-drafts`).
|
||||
2. Get the full list of PRs merged between the previous release tag and the target commit.
|
||||
3. Read `src/Directory.Build.props` **at the target commit**. Extract `<VersionPrefix>` as the **candidate version**.
|
||||
1. Determine the previous release tag from `gh release list` (most recent **published** release — exclude drafts with `--exclude-drafts`). Use the selected source/base branch context: on `release/{MAJOR}.x`, restrict candidates to tags matching `v{MAJOR}.*`; on `main`, use the most recent published release globally.
|
||||
2. Get the full list of PRs merged between the previous release tag and the target commit on the selected branch.
|
||||
3. Read `src/Directory.Build.props` **at the target commit**. Extract `<VersionPrefix>` and `<VersionSuffix>`; the **candidate version** is `{VersionPrefix}` plus `-{VersionSuffix}` when the suffix is present (for example, `2.0.0-preview.1`).
|
||||
|
||||
### Step 2: Categorize and Attribute
|
||||
### Step 3: Categorize and Attribute
|
||||
|
||||
Sort every PR into one of four categories. See [references/categorization.md](references/categorization.md) for detailed guidance.
|
||||
|
||||
|
|
@ -50,53 +67,55 @@ Sort every PR into one of four categories. See [references/categorization.md](re
|
|||
- Omit the co-author parenthetical when there are none
|
||||
- Sort entries within each section by merge date (chronological)
|
||||
|
||||
### Step 3: Breaking Change Audit
|
||||
### Step 4: Breaking Change Audit
|
||||
|
||||
Invoke the **breaking-changes** skill with the commit range from the previous release tag to the target commit. Examine every PR, assess impact, reconcile labels (offering to add/remove labels and comment on PRs), and get user confirmation.
|
||||
|
||||
Use the results (confirmed breaking changes with impact ordering and detail bullets) in the remaining steps.
|
||||
|
||||
### Step 4: Assess Release Version
|
||||
### Step 5: Assess Release Version
|
||||
|
||||
Using the categorized PRs from Step 2 and confirmed breaking changes from Step 3, assess the appropriate [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html) release level. Follow the [SemVer assessment guide](../bump-version/references/semver-assessment.md) (owned by the **bump-version** skill) for the full assessment criteria.
|
||||
Using the categorized PRs from Step 3 and confirmed breaking changes from Step 4, assess the appropriate [Semantic Versioning 2.0.0](https://semver.org/spec/v2.0.0.html) release level. Follow the [SemVer assessment guide](../bump-version/references/semver-assessment.md) (owned by the **bump-version** skill) for the full assessment criteria.
|
||||
|
||||
1. **Classify the release level**:
|
||||
- **MAJOR** — if any confirmed breaking changes are present (API or behavioral), excluding changes to `[Experimental]` APIs
|
||||
- **MINOR** — if no breaking changes but new public APIs, features, or obsoletion warnings are introduced
|
||||
- **PATCH** — otherwise
|
||||
2. **Compute the recommended version** from the previous release tag:
|
||||
2. **Compute the recommended version** from the previous release tag and branch context:
|
||||
- Increment the appropriate component (MAJOR resets MINOR.PATCH to 0; MINOR resets PATCH to 0)
|
||||
- For prerelease candidates such as `preview.N` or `rc.N`, the recommendation may simply increment the trailing integer per the assessment guide
|
||||
3. **Compare against the candidate version** from `src/Directory.Build.props`. Flag any discrepancy:
|
||||
- **Under-versioned**: The candidate is lower than the recommended level. This is a concern that should be resolved.
|
||||
- **Over-versioned**: The candidate is higher than strictly required. This is acceptable under SemVer but worth noting.
|
||||
4. **Present the assessment** with a summary table showing the previous release, change classification, recommended level, recommended version, and any discrepancy with the candidate. Include a brief rationale citing the most significant PRs.
|
||||
5. **Get user confirmation** of the release version before proceeding.
|
||||
|
||||
### Step 5: Create Release Branch and Bump Version
|
||||
### Step 6: Create Release Branch and Bump Version
|
||||
|
||||
After the version is confirmed:
|
||||
|
||||
1. Create a local branch named `release-{version}` from the target commit (e.g., `release-1.1.0`).
|
||||
1. Create a local branch named `release-{version}` from the target commit (e.g., `release-2.0.0-preview.1`, `release-1.3.1`).
|
||||
2. Update `src/Directory.Build.props`:
|
||||
- Set `<VersionPrefix>` to the confirmed version
|
||||
- Update `<PackageValidationBaselineVersion>` if the MAJOR version has changed (set to the previous release version)
|
||||
- Set `<VersionPrefix>` to the confirmed stable component
|
||||
- Set `<VersionSuffix>` for prerelease versions, or clear it for stable versions; add the element if it is missing
|
||||
- Update `<PackageValidationBaselineVersion>` when appropriate. For the `2.0.0-preview` series, baseline is `1.3.0` (latest shipped 1.x). For subsequent stable releases, baseline is the previous shipped version of the same MAJOR or the latest stable from the previous MAJOR.
|
||||
3. Build the solution to verify the version change compiles: `dotnet build`
|
||||
|
||||
This step creates local changes only — nothing is committed or pushed yet.
|
||||
|
||||
### Step 6: Run API Compatibility Check
|
||||
### Step 7: Run API Compatibility Check
|
||||
|
||||
Run API compatibility validation against the baseline version. Follow [references/apicompat-apidiff.md](references/apicompat-apidiff.md) for the full procedure.
|
||||
|
||||
1. Run `dotnet pack` to trigger package validation against `PackageValidationBaselineVersion`
|
||||
2. Capture the ApiCompat output (compatibility issues, warnings, suppressions)
|
||||
3. If there are unexpected compatibility breaks:
|
||||
- Cross-reference with the breaking change audit from Step 3
|
||||
- Cross-reference with the breaking change audit from Step 4
|
||||
- Present any unaccounted breaks to the user
|
||||
- If breaks are intentional, add appropriate entries to `CompatibilitySuppressions.xml` in the affected project directory
|
||||
4. Record the ApiCompat results for inclusion in the PR description
|
||||
|
||||
### Step 7: Generate API Diff Report
|
||||
### Step 8: Generate API Diff Report
|
||||
|
||||
Generate a human-readable diff of the public API surface between the previous release and the new version. Follow [references/apicompat-apidiff.md](references/apicompat-apidiff.md) for the full procedure, including how to install the `Microsoft.DotNet.ApiDiff.Tool` from the .NET transport feed.
|
||||
|
||||
|
|
@ -107,7 +126,7 @@ Generate a human-readable diff of the public API surface between the previous re
|
|||
|
||||
> **If the ApiDiff tool cannot be installed or fails to produce output, STOP and inform the user.** Present the error and ask how to proceed. Do not fall back to a manual summary — the user must decide whether to troubleshoot, skip the API diff, or abort.
|
||||
|
||||
### Step 8: Review and Update Documentation
|
||||
### Step 9: Review and Update Documentation
|
||||
|
||||
Review repository documentation for changes needed to compensate for or adapt to this release:
|
||||
|
||||
|
|
@ -118,12 +137,12 @@ Review repository documentation for changes needed to compensate for or adapt to
|
|||
|
||||
Stage all documentation changes for inclusion in the release commit.
|
||||
|
||||
### Step 9: Draft Release Notes
|
||||
### Step 10: Draft Release Notes
|
||||
|
||||
Compose the release notes that will appear in the PR description and serve as the foundation for the **publish-release** skill. This is a draft — the final release notes will be refreshed when the GitHub release is created.
|
||||
|
||||
1. **Preamble** — Draft a short paragraph summarizing the release theme. Present it to the user for review and editing. The preamble is **required**.
|
||||
2. **Breaking Changes** — sorted most → least impactful (from Step 3 results). Include the versioning docs link.
|
||||
2. **Breaking Changes** — sorted most → least impactful (from Step 4 results). Include the versioning docs link.
|
||||
3. **What's Changed** — chronological; includes breaking change PRs
|
||||
4. **Documentation Updates** — chronological
|
||||
5. **Test Improvements** — chronological
|
||||
|
|
@ -132,11 +151,11 @@ Compose the release notes that will appear in the PR description and serve as th
|
|||
- New contributors (first contribution in this release)
|
||||
- Issue reporters (cite resolving PRs)
|
||||
- PR reviewers (single bullet, sorted by review count, no count shown)
|
||||
8. **Full Changelog** link
|
||||
8. **Full Changelog** link using the exact tag, including any suffix (for example, `v1.3.1` or `v2.0.0-preview.1`)
|
||||
|
||||
Omit empty sections. Present each section for user review before proceeding.
|
||||
Omit empty sections. Present each section for user review before proceeding. Tag references in templates use `v{version}` exactly, including prerelease suffixes; the Full Changelog link compares the previous tag to the suffixed tag when applicable.
|
||||
|
||||
### Step 10: Commit Changes
|
||||
### Step 11: Commit Changes
|
||||
|
||||
Commit all changes to the `release-{version}` branch:
|
||||
|
||||
|
|
@ -144,39 +163,40 @@ Commit all changes to the `release-{version}` branch:
|
|||
2. Commit with message: `Prepare release v{version}`
|
||||
3. Do **not** push yet
|
||||
|
||||
### Step 11: Present Release Summary
|
||||
### Step 12: Present Release Summary
|
||||
|
||||
Present **all** of the following details to the user for review. The user must confirm every aspect before proceeding to Step 12.
|
||||
Present **all** of the following details to the user for review. The user must confirm every aspect before proceeding to Step 13.
|
||||
|
||||
1. **Version number** with brief rationale for why this SemVer level was selected
|
||||
2. **Branch name** (e.g., `release-1.1.0`)
|
||||
3. **Remote** the branch would be pushed to (show the configured remote, typically `origin`)
|
||||
4. **Files changed** — list every file modified in the commit with a one-line summary of what changed in each:
|
||||
2. **Source/base branch** selected in Step 1
|
||||
3. **Branch name** (e.g., `release-2.0.0-preview.1`, `release-1.3.1`)
|
||||
4. **Remote** the branch would be pushed to (show the configured remote, typically `origin`)
|
||||
5. **Files changed** — list every file modified in the commit with a one-line summary of what changed in each:
|
||||
```
|
||||
src/Directory.Build.props — Version bumped from 1.0.0 to 1.1.0
|
||||
src/Directory.Build.props — Version bumped from 2.0.0-preview.1 to 2.0.0-preview.2
|
||||
src/ModelContextProtocol.Core/CompatibilitySuppressions.xml — Added 2 new suppressions
|
||||
README.md — Updated code sample for new API
|
||||
docs/experimental.md — Added new experimental API reference
|
||||
```
|
||||
5. **Draft release notes** — the complete release notes from Step 9
|
||||
6. **API Compatibility results** — the ApiCompat output from Step 6
|
||||
7. **API Diff report** — the API diff from Step 7
|
||||
8. **Proposed PR title** (e.g., `Release v1.1.0`)
|
||||
9. **Proposed PR description** — the assembled content combining release notes, ApiCompat, and ApiDiff
|
||||
6. **Draft release notes** — the complete release notes from Step 10
|
||||
7. **API Compatibility results** — the ApiCompat output from Step 7
|
||||
8. **API Diff report** — the API diff from Step 8
|
||||
9. **Proposed PR title** (e.g., `Release v2.0.0-preview.1`, `Release v1.3.1`)
|
||||
10. **Proposed PR description** — the assembled content combining release notes, ApiCompat, and ApiDiff
|
||||
|
||||
After presenting all details, explicitly ask the user:
|
||||
> Would you like to push the branch and create the pull request?
|
||||
|
||||
**Do not proceed without explicit "yes" confirmation.**
|
||||
|
||||
### Step 12: Push Branch and Create Pull Request
|
||||
### Step 13: Push Branch and Create Pull Request
|
||||
|
||||
Only after explicit user confirmation in Step 11:
|
||||
Only after explicit user confirmation in Step 12:
|
||||
|
||||
1. Push the `release-{version}` branch to the remote
|
||||
2. Create a pull request:
|
||||
2. Create a pull request with `gh pr create --base {step-1-branch}`:
|
||||
- **Title**: `Release v{version}`
|
||||
- **Base**: default branch (typically `main`)
|
||||
- **Base**: the source/base branch selected in Step 1
|
||||
- **Head**: `release-{version}`
|
||||
- **Description**: The assembled PR description (see PR Description Template below)
|
||||
- **Labels**: Apply appropriate labels (e.g., `release`)
|
||||
|
|
@ -192,18 +212,20 @@ Only after explicit user confirmation in Step 11:
|
|||
- **Single breaking change**: use the same numbered format as multiple
|
||||
- **No user-facing changes**: if all PRs are documentation, tests, or infrastructure, flag that a release may not be warranted and ask the user whether to proceed
|
||||
- **Version discrepancy**: if the candidate version from `Directory.Build.props` doesn't match the SemVer assessment, present the discrepancy and let the user decide the final version
|
||||
- **Proposed MAJOR does not match branch MAJOR**: if the proposed version's MAJOR doesn't match the branch's MAJOR (for example, proposing `2.0.0-preview.2` on `release/1.x`), flag this as a warning and ask the user to confirm. Do not hard-fail. This is informational, not a policy enforcement.
|
||||
- **Prerelease bump**: when the candidate version has a suffix like `preview.N`, the SemVer assessment may simply increment `N` rather than computing MAJOR/MINOR/PATCH. Refer to the SemVer assessment guide's Prereleases section.
|
||||
- **No previous release**: if this is the first release, there is no previous tag; gather all PRs merged to the target
|
||||
- **ApiCompat tooling unavailable**: fall back to `dotnet pack` output; note in the PR description that full ApiCompat was run via package validation only
|
||||
- **API diff tool installation fails**: do not fall back to a manual summary; pause and present the installation error to the user, offering options to troubleshoot, skip the API diff section, or abort the release preparation
|
||||
- **No changelogs in repo**: skip changelog updates; note in the summary
|
||||
- **Branch already exists**: if `release-{version}` already exists locally or remotely, ask the user whether to reuse it, delete and recreate, or choose a different name
|
||||
- **PackageValidationBaselineVersion update**: when bumping MAJOR version, update the baseline to the previous release version; when bumping MINOR or PATCH, keep the existing baseline
|
||||
- **PackageValidationBaselineVersion update**: for the `2.0.0-preview` series, use `1.3.0`; for subsequent stable releases, use the previous shipped version of the same MAJOR or the latest stable from the previous MAJOR
|
||||
- **CompatibilitySuppressions.xml**: when intentional breaks are found, add suppression entries and include the file in the commit; existing suppressions should be preserved
|
||||
- **User declines PR creation**: if the user declines at Step 11, leave the local branch intact so they can review, modify, or push manually
|
||||
- **User declines PR creation**: if the user declines at Step 12, leave the local branch intact so they can review, modify, or push manually
|
||||
|
||||
## PR Description Template
|
||||
|
||||
The PR description combines release notes, ApiCompat, and ApiDiff into a single document. Omit empty sections.
|
||||
The PR description combines release notes, ApiCompat, and ApiDiff into a single document. Omit empty sections. The `{version}` placeholder is the full version and may include a prerelease suffix (for example, `Release v2.0.0-preview.1`).
|
||||
|
||||
```markdown
|
||||
# Release v{version}
|
||||
|
|
@ -241,7 +263,8 @@ Refer to the [C# SDK Versioning](https://csharp.sdk.modelcontextprotocol.io/vers
|
|||
* @user made their first contribution in #PR
|
||||
* @user1 @user2 @user3 reviewed pull requests
|
||||
|
||||
**Full Changelog**: https://github.com/modelcontextprotocol/csharp-sdk/compare/previous-tag...release-{version}
|
||||
**Full Changelog**: https://github.com/modelcontextprotocol/csharp-sdk/compare/{previous-tag}...v{version}
|
||||
<!-- Example: https://github.com/modelcontextprotocol/csharp-sdk/compare/v1.3.0...v2.0.0-preview.1 -->
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -266,7 +289,7 @@ Refer to the [C# SDK Versioning](https://csharp.sdk.modelcontextprotocol.io/vers
|
|||
|
||||
## Release Notes Template
|
||||
|
||||
The release notes section within the PR description uses the same format as the final GitHub release notes (used by the **publish-release** skill). This ensures consistency between the PR and the published release.
|
||||
The release notes section within the PR description uses the same format as the final GitHub release notes (used by the **publish-release** skill). This ensures consistency between the PR and the published release. Tag examples such as `v2.0.0-preview.1` are valid and should be used verbatim when the version has a prerelease suffix.
|
||||
|
||||
Omit empty sections. The preamble is **always required** — it is not inside a section heading.
|
||||
|
||||
|
|
@ -303,5 +326,6 @@ Refer to the [C# SDK Versioning](https://csharp.sdk.modelcontextprotocol.io/vers
|
|||
* @user submitted issue #1234 (resolved by #5678)
|
||||
* @user1 @user2 @user3 reviewed pull requests
|
||||
|
||||
**Full Changelog**: https://github.com/modelcontextprotocol/csharp-sdk/compare/previous-tag...new-tag
|
||||
**Full Changelog**: https://github.com/modelcontextprotocol/csharp-sdk/compare/{previous-tag}...v{version}
|
||||
<!-- Example: https://github.com/modelcontextprotocol/csharp-sdk/compare/v1.3.0...v2.0.0-preview.1 -->
|
||||
```
|
||||
|
|
|
|||
Loading…
Reference in a new issue