-
Notifications
You must be signed in to change notification settings - Fork 55
Add SDK release kickoff pipeline #677
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,72 @@ | ||
| # Copyright (c) Microsoft Corporation. | ||
| # Licensed under the MIT License. | ||
|
|
||
| # This pipeline automates the SDK release kickoff process. | ||
| # It bumps package versions, generates a changelog update, creates a release branch, | ||
| # and opens a pull request for the release. | ||
|
|
||
| trigger: none | ||
| pr: none | ||
|
|
||
| parameters: | ||
| - name: bumpType | ||
| displayName: 'Version bump type' | ||
| type: string | ||
| default: 'minor' | ||
| values: | ||
| - major | ||
| - minor | ||
| - patch | ||
| - explicit | ||
|
|
||
| - name: explicitVersion | ||
| displayName: 'Explicit version (required if bump type is "explicit", format: X.Y.Z)' | ||
| type: string | ||
| default: '' | ||
|
|
||
| - name: versionSuffix | ||
| displayName: 'Version suffix (e.g., "preview", "rc.1"; leave empty for stable release)' | ||
| type: string | ||
| default: '' | ||
|
|
||
| pool: | ||
| vmImage: 'ubuntu-latest' | ||
|
|
||
| steps: | ||
| - checkout: self | ||
| persistCredentials: true | ||
| fetchDepth: 0 | ||
|
|
||
| - task: UseDotNet@2 | ||
| displayName: 'Install .NET SDK' | ||
| inputs: | ||
| packageType: 'sdk' | ||
| useGlobalJson: true | ||
|
|
||
| - task: UsePythonVersion@0 | ||
| displayName: 'Use Python 3.x' | ||
| inputs: | ||
| versionSpec: '3.x' | ||
|
|
||
| - pwsh: | | ||
| git config user.email "azuredevops@microsoft.com" | ||
| git config user.name "Azure DevOps Pipeline" | ||
| displayName: 'Configure git identity' | ||
|
|
||
| - pwsh: | | ||
| $ErrorActionPreference = 'Stop' | ||
|
|
||
| $params = @{ | ||
| BumpType = '${{ parameters.bumpType }}' | ||
| } | ||
| if ('${{ parameters.explicitVersion }}') { | ||
| $params['ExplicitVersion'] = '${{ parameters.explicitVersion }}' | ||
| } | ||
| if ('${{ parameters.versionSuffix }}') { | ||
| $params['VersionSuffix'] = '${{ parameters.versionSuffix }}' | ||
| } | ||
|
|
||
| & "$(Build.SourcesDirectory)/eng/scripts/Start-Release.ps1" @params | ||
| displayName: 'Run release kickoff' | ||
| env: | ||
| GH_TOKEN: $(GitHubToken) |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,240 @@ | ||||||||||||||||||||||||||||||||||||||
| # Copyright (c) Microsoft Corporation. | ||||||||||||||||||||||||||||||||||||||
| # Licensed under the MIT License. | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| <# | ||||||||||||||||||||||||||||||||||||||
| .SYNOPSIS | ||||||||||||||||||||||||||||||||||||||
| Bumps package versions, generates changelog, creates a release branch, and opens a PR. | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| .DESCRIPTION | ||||||||||||||||||||||||||||||||||||||
| This script automates the SDK release kickoff process: | ||||||||||||||||||||||||||||||||||||||
| 1. Bumps the version in eng/targets/Release.props based on the bump type or explicit version. | ||||||||||||||||||||||||||||||||||||||
| 2. Runs generate_changelog.py to produce a changelog entry. | ||||||||||||||||||||||||||||||||||||||
| 3. Prepends the generated changelog entry to CHANGELOG.md. | ||||||||||||||||||||||||||||||||||||||
| 4. Creates a release branch and pushes it. | ||||||||||||||||||||||||||||||||||||||
| 5. Opens a pull request targeting main. | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| .PARAMETER BumpType | ||||||||||||||||||||||||||||||||||||||
| The type of version bump: 'major', 'minor', 'patch', or 'explicit'. | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| .PARAMETER ExplicitVersion | ||||||||||||||||||||||||||||||||||||||
| The explicit version to set (required when BumpType is 'explicit'). Format: 'X.Y.Z'. | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| .PARAMETER VersionSuffix | ||||||||||||||||||||||||||||||||||||||
| Optional pre-release suffix (e.g., 'preview', 'rc.1'). Leave empty for stable releases. | ||||||||||||||||||||||||||||||||||||||
| #> | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| param( | ||||||||||||||||||||||||||||||||||||||
| [Parameter(Mandatory = $true)] | ||||||||||||||||||||||||||||||||||||||
| [ValidateSet('major', 'minor', 'patch', 'explicit')] | ||||||||||||||||||||||||||||||||||||||
| [string]$BumpType, | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| [Parameter(Mandatory = $false)] | ||||||||||||||||||||||||||||||||||||||
| [string]$ExplicitVersion = '', | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| [Parameter(Mandatory = $false)] | ||||||||||||||||||||||||||||||||||||||
| [string]$VersionSuffix = '' | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Set-StrictMode -Version Latest | ||||||||||||||||||||||||||||||||||||||
| $ErrorActionPreference = 'Stop' | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| $repoRoot = (Resolve-Path "$PSScriptRoot/../..").Path | ||||||||||||||||||||||||||||||||||||||
| $releasePropsPath = Join-Path $repoRoot 'eng/targets/Release.props' | ||||||||||||||||||||||||||||||||||||||
| $changelogPath = Join-Path $repoRoot 'CHANGELOG.md' | ||||||||||||||||||||||||||||||||||||||
| $changelogScript = Join-Path $repoRoot 'generate_changelog.py' | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| function Get-CurrentVersion { | ||||||||||||||||||||||||||||||||||||||
| [xml]$props = Get-Content $releasePropsPath -Raw | ||||||||||||||||||||||||||||||||||||||
| $versionPrefix = $props.Project.PropertyGroup.VersionPrefix | ||||||||||||||||||||||||||||||||||||||
| if (-not $versionPrefix) { | ||||||||||||||||||||||||||||||||||||||
| throw "Could not find VersionPrefix in $releasePropsPath" | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| return $versionPrefix.Trim() | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| function Get-BumpedVersion { | ||||||||||||||||||||||||||||||||||||||
| param( | ||||||||||||||||||||||||||||||||||||||
| [string]$CurrentVersion, | ||||||||||||||||||||||||||||||||||||||
| [string]$BumpType, | ||||||||||||||||||||||||||||||||||||||
| [string]$ExplicitVersion | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| if ($BumpType -eq 'explicit') { | ||||||||||||||||||||||||||||||||||||||
| if (-not $ExplicitVersion) { | ||||||||||||||||||||||||||||||||||||||
| throw "ExplicitVersion is required when BumpType is 'explicit'." | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| if ($ExplicitVersion -notmatch '^\d+\.\d+\.\d+$') { | ||||||||||||||||||||||||||||||||||||||
| throw "ExplicitVersion must be in the format 'X.Y.Z'. Got: '$ExplicitVersion'" | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
| return $ExplicitVersion | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| $parts = $CurrentVersion.Split('.') | ||||||||||||||||||||||||||||||||||||||
| if ($parts.Count -ne 3) { | ||||||||||||||||||||||||||||||||||||||
| throw "Current version '$CurrentVersion' is not in expected X.Y.Z format." | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| [int]$major = $parts[0] | ||||||||||||||||||||||||||||||||||||||
| [int]$minor = $parts[1] | ||||||||||||||||||||||||||||||||||||||
| [int]$patch = $parts[2] | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| switch ($BumpType) { | ||||||||||||||||||||||||||||||||||||||
| 'major' { $major++; $minor = 0; $patch = 0 } | ||||||||||||||||||||||||||||||||||||||
| 'minor' { $minor++; $patch = 0 } | ||||||||||||||||||||||||||||||||||||||
| 'patch' { $patch++ } | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| return "$major.$minor.$patch" | ||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| function Set-Version { | ||||||||||||||||||||||||||||||||||||||
| param( | ||||||||||||||||||||||||||||||||||||||
| [string]$NewVersion, | ||||||||||||||||||||||||||||||||||||||
| [string]$Suffix | ||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| $content = Get-Content $releasePropsPath -Raw | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| # Update VersionPrefix | ||||||||||||||||||||||||||||||||||||||
| $content = $content -replace '<VersionPrefix>[^<]*</VersionPrefix>', "<VersionPrefix>$NewVersion</VersionPrefix>" | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| # Update VersionSuffix | ||||||||||||||||||||||||||||||||||||||
| $content = $content -replace '<VersionSuffix>[^<]*</VersionSuffix>', "<VersionSuffix>$Suffix</VersionSuffix>" | ||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||
| Set-Content -Path $releasePropsPath -Value $content -NoNewline -Encoding UTF8 | ||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+96
to
+104
|
||||||||||||||||||||||||||||||||||||||
| $content = Get-Content $releasePropsPath -Raw | |
| # Update VersionPrefix | |
| $content = $content -replace '<VersionPrefix>[^<]*</VersionPrefix>', "<VersionPrefix>$NewVersion</VersionPrefix>" | |
| # Update VersionSuffix | |
| $content = $content -replace '<VersionSuffix>[^<]*</VersionSuffix>', "<VersionSuffix>$Suffix</VersionSuffix>" | |
| Set-Content -Path $releasePropsPath -Value $content -NoNewline -Encoding UTF8 | |
| [xml]$props = Get-Content $releasePropsPath -Raw | |
| # Update VersionPrefix | |
| $props.Project.PropertyGroup.VersionPrefix = $NewVersion | |
| # Update VersionSuffix | |
| $props.Project.PropertyGroup.VersionSuffix = $Suffix | |
| $props.Save($releasePropsPath) |
YunchuWang marked this conversation as resolved.
Show resolved
Hide resolved
YunchuWang marked this conversation as resolved.
Show resolved
Hide resolved
Copilot
AI
Mar 24, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before switching branches and pulling (git checkout main / git pull), the script should validate that the working tree is clean (e.g., git status --porcelain is empty). Otherwise uncommitted local changes can be carried into the release branch/PR or cause checkout/pull to fail in a confusing way, which is risky for a release kickoff workflow.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
VersionSuffixis used to build the git branch name and tag (and is also written into XML via-replace) but it isn’t validated. Please add input validation to restrict it to a safe SemVer prerelease charset (e.g., alphanumerics plus.and-, no whitespace/quotes/slashes) to avoid invalid branch/tag names or accidental PowerShell/regex replacement quirks with characters like$.