diff --git a/.vsts-ci/azure-pipelines-release.yml b/.vsts-ci/azure-pipelines-release.yml index 4fe28b4646..e71f8b2555 100644 --- a/.vsts-ci/azure-pipelines-release.yml +++ b/.vsts-ci/azure-pipelines-release.yml @@ -31,8 +31,8 @@ jobs: - job: 'ReleaseBuild' displayName: 'Build release' pool: - name: 'Package ES Standard Build' - demands: DotNetFramework + name: '1ES' + demands: ImageOverride -equals MMS2019 variables: - group: ESRP steps: diff --git a/docs/development.md b/docs/development.md index 914fe5d4bf..25acdd7308 100644 --- a/docs/development.md +++ b/docs/development.md @@ -68,18 +68,11 @@ Import-Module ./tools/ReleaseTools.psm1 Update-Changelog -RepositoryName PowerShellEditorServices -Version Update-Changelog -RepositoryName vscode-powershell -Version # Amend changelog as necessary -Update-Version -RepositoryName PowerShellEditorServices -Update-Version -RepositoryName vscode-powershell -# Push branches to GitHub and ADO -# Open PRs for review # Download and test assets (assert correct PSES is included) -New-DraftRelease -RepositoryName PowerShellEditorServices -New-DraftRelease -RepositoryName vscode-powershell -# Point releases to branches for automatic tagging -# Upload PowerShellEditorServices.zip (for other extensions) -# Upload VSIX and Install-VSCode.ps1 -# Publish draft releases and merge (don't squash!) branches +New-DraftRelease -RepositoryName PowerShellEditorServices -Assets "PowerShellEditorServices.zip" +New-DraftRelease -RepositoryName vscode-powershell -Assets "powershell-YYYY.M.X.vsix", "Install-VSCode.ps1" # Check telemetry for stability before releasing +# Publish draft releases and merge (don't squash!) branches vsce publish --packagePath ./PowerShell-.vsix # Update Install-VSCode.ps1 on gallery Publish-Script -Path ./Install-VSCode.ps1 -NuGetApiKey (Get-Secret "PowerShell Gallery API Key" -AsPlainText) @@ -98,7 +91,7 @@ For PowerShellEditor Services, we simply follow semantic versioning, e.g. generally used directly: it's a library consumed by other projects which themselves use preview releases for beta testing. -For the VS Code PowerShell Extension, our version follows `vYYYY.MM.X`, that is: +For the VS Code PowerShell Extension, our version follows `vYYYY.M.X`, that is: current year, current month, and patch version (not day). This is not semantic versioning because of issues with how the VS Code marketplace and extension hosting API itself uses our version number. This scheme _does not_ mean we @@ -137,7 +130,4 @@ use the same code which includes dependencies). * `Update-Changelog` should verify the version is in the correct format * `Update-Changelog` could be faster by not downloading _every_ PR -* `Update-Changelog` should use exactly two emoji and in the right order -* `Update-Version` could be run by `Update-Changelog` -* The build should emit an appropriately named VSIX instead of us manually renaming it * A `Publish-Binaries` function could be written to push the binaries out diff --git a/tools/ReleaseTools.psm1 b/tools/ReleaseTools.psm1 index e80789c5a1..907be306e8 100644 --- a/tools/ReleaseTools.psm1 +++ b/tools/ReleaseTools.psm1 @@ -37,10 +37,13 @@ function Get-Bullets { 'TylerLeonhardt' ) - $LabelEmoji = @{ + $IssueEmojis = @{ 'Issue-Enhancement' = '✨' 'Issue-Bug' = '🐛' 'Issue-Performance' = '⚡️' + } + + $AreaEmojis = @{ 'Area-Build & Release' = '👷' 'Area-Code Formatting' = '💎' 'Area-Configuration' = '🔧' @@ -81,12 +84,9 @@ function Get-Bullets { process { $PullRequests | ForEach-Object { # Map all the labels to emoji (or use a default). - # NOTE: Whitespacing here is weird. - $emoji = if ($_.labels) { - $LabelEmoji[$_.labels.LabelName] -join "" - } else { - '#️⃣ 🙏' - } + $labels = if ($_.labels) { $_.labels.LabelName } else { "" } + $issueEmoji = $IssueEmojis[$labels] + "#️⃣" | Select-Object -First 1 + $areaEmoji = $AreaEmojis[$labels] + "🙏" | Select-Object -First 1 # Get a linked issue number if it exists (or use the PR). $link = if ($_.body -match $IssueRegex) { @@ -105,7 +105,7 @@ function Get-Bullets { } # Put the bullet point together. - ("-", $emoji, "[$link]($($_.html_url))", "-", "$($_.title).", $thanks -join " ").Trim() + ("-", $issueEmoji, $areaEmoji, "[$link]($($_.html_url))", "-", "$($_.title).", $thanks -join " ").Trim() } } } @@ -139,13 +139,17 @@ function Get-FirstChangelog { Creates and checks out `release/v` if not already on it. #> function Update-Branch { + [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory)] [string]$Version ) - $branch = git branch --show-current - if ($branch -ne "release/v$Version") { - git checkout -b "release/v$Version" + $Branch = git branch --show-current + $NewBranch = "release/v$Version" + if ($Branch -ne $NewBranch) { + if ($PSCmdlet.ShouldProcess($NewBranch, "git checkout -b")) { + git checkout -b $NewBranch + } } } @@ -202,8 +206,7 @@ function Update-Changelog { Where-Object { -not $_.user.UserName.EndsWith("[bot]") } | Where-Object { "Ignore" -notin $_.labels.LabelName } | Where-Object { -not $_.title.StartsWith("[Ignore]") } | - Where-Object { -not $_.title.StartsWith("Update CHANGELOG") } | - Where-Object { -not $_.title.StartsWith("Bump version") } | + Where-Object { -not $_.title.StartsWith("Release ``v") } | Get-Bullets -RepositoryName $RepositoryName $NewSection = switch ($RepositoryName) { @@ -235,12 +238,15 @@ function Update-Changelog { $CurrentChangelog[2..$CurrentChangelog.Length] ) | Set-Content -Encoding utf8NoBOM -Path $ChangelogFile - if ($PSCmdlet.ShouldProcess("$RepositoryName/$ChangelogFile", "git")) { - Update-Branch -Version $Version.Substring(1) # Has "v" prefix + Update-Branch -Version $Version.Substring(1) # Has "v" prefix + + if ($PSCmdlet.ShouldProcess("$RepositoryName/$ChangelogFile", "git commit")) { git add $ChangelogFile git commit -m "Update CHANGELOG for ``$Version``" } + Update-Version -RepositoryName $RepositoryName + Pop-Location } @@ -250,18 +256,18 @@ function Update-Changelog { .DESCRIPTION Note that our Git tags and changelog prefix all versions with `v`. - PowerShellEditorServices: version is `x.y.z-preview.d` + PowerShellEditorServices: version is `X.Y.Z-preview` - PowerShellEditorServices.psd1: - - `ModuleVersion` variable with `'x.y.z'` string, no pre-release info + - `ModuleVersion` variable with `'X.Y.Z'` string, no pre-release info - PowerShellEditorServices.Common.props: - - `VersionPrefix` field with `x.y.z` + - `VersionPrefix` field with `X.Y.Z` - `VersionSuffix` field with pre-release portion excluding hyphen - vscode-powershell: version is `yyyy.mm.x-preview` + vscode-powershell: version is `YYYY.M.X-preview` - package.json: - - `version` field with `"x.y.z"` and no prefix or suffix + - `version` field with `"X.Y.Z"` and no prefix or suffix - `preview` field set to `true` or `false` if version is a preview - `name` field has `-preview` appended similarly - `displayName` field has ` Preview` appended similarly @@ -322,11 +328,62 @@ function Update-Version { } } + Update-Branch -Version $Version + if ($PSCmdlet.ShouldProcess("$RepositoryName/v$Version", "git commit")) { - Update-Branch -Version $Version git commit -m "Bump version to ``v$Version``" + } # TODO: Git reset to unstage + + New-ReleasePR -RepositoryName $RepositoryName + + Pop-Location +} + +<# +.SYNOPSIS + Creates a new draft GitHub PR from the release branch. +.DESCRIPTION + Pushes the release branch to `origin` and then opens a draft PR. +#> +function New-ReleasePR { + [CmdletBinding(SupportsShouldProcess)] + param( + [Parameter(Mandatory)] + [ValidateSet([RepoNames])] + [string]$RepositoryName + ) + # NOTE: This a side effect neccesary for Git operations to work. + Push-Location -Path "$PSScriptRoot/../../$RepositoryName" + + $Version = Get-Version -RepositoryName $RepositoryName + $Branch = "release/v$Version" + + Update-Branch -Version $Version + + if ($PSCmdlet.ShouldProcess("$RepositoryName/$Branch", "git push")) { + Write-Host "Pushing branch ``$Branch``..." + git push origin $Branch } + $LabelParams = @{ + OwnerName = "PowerShell" + RepositoryName = $RepositoryName + Label = "Ignore" + } + + $PRParams = @{ + Head = $Branch + Base = "master" + Draft = $true + Title = "Release ``v$Version``" + Body = "Automated PR for new release!" + WhatIf = $WhatIfPreference + Confirm = $ConfirmPreference + } + + $PR = Get-GitHubLabel @LabelParams | New-GitHubPullRequest @PRParams + Write-Host "Draft PR URL: $($PR.html_url)" + Pop-Location } @@ -339,28 +396,35 @@ function Update-Version { are prefixed with a `v`. Creates a Git tag if it does not already exist. #> function New-DraftRelease { + [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory)] [ValidateSet([RepoNames])] [string]$RepositoryName, - [Parameter(ValueFromPipeline)] + [Parameter()] [string[]]$Assets ) $Version = Get-Version -RepositoryName $RepositoryName $Changelog = (Get-FirstChangelog -RepositoryName $RepositoryName) -join "`n" $ReleaseParams = @{ - Draft = $true # NOTE: We rely on GitHub to create the tag at that branch. - Tag = "v$Version" - Committish = "release/v$Version" - Name = "v$Version" - Body = $ChangeLog - PreRelease = [bool]$Version.PreReleaseLabel - OwnerName = "PowerShell" + Tag = "v$Version" + Committish = "release/v$Version" + Name = "v$Version" + Body = $ChangeLog + Draft = $true + PreRelease = [bool]$Version.PreReleaseLabel + OwnerName = "PowerShell" RepositoryName = $RepositoryName + WhatIf = $WhatIfPreference + Confirm = $ConfirmPreference } $Release = New-GitHubRelease @ReleaseParams - $Assets | New-GitHubReleaseAsset -Release $Release.Id + if ($Release) { + Write-Host "Draft release URL: $($Release.html_url)" + Write-Host "Uploading assets..." + $Assets | New-GitHubReleaseAsset -Release $Release.Id + } }