[repo] NuGet push release automation (#5675)

This commit is contained in:
Mikel Blanchard 2024-06-07 11:12:22 -07:00 committed by GitHub
parent 90871e01cb
commit 84cd83ad53
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 214 additions and 60 deletions

View File

@ -7,21 +7,69 @@ on:
required: true
description: 'Release tag'
type: string
release:
types: [published]
types:
- published
issue_comment:
types:
- created
jobs:
automation:
uses: ./.github/workflows/automation.yml
secrets: inherit
post-release:
push-packages-and-publish-release:
runs-on: ubuntu-latest
needs: automation
if: |
github.event_name == 'issue_comment'
&& github.event.issue.pull_request
&& github.event.issue.locked == true
&& github.event.comment.user.login != needs.automation.outputs.username
&& contains(github.event.comment.body, '/PushPackages')
&& startsWith(github.event.issue.title, '[repo] Prepare release ')
&& github.event.issue.pull_request.merged_at
&& needs.automation.outputs.enabled
env:
GH_TOKEN: ${{ secrets[needs.automation.outputs.token-secret-name] }}
steps:
- name: check out code
uses: actions/checkout@v4
with:
token: ${{ secrets[needs.automation.outputs.token-secret-name] }}
ref: ${{ github.event.repository.default_branch }}
- name: Push packages and publish release
shell: pwsh
env:
NUGET_TOKEN: ${{ secrets.NUGET_TOKEN }}
run: |
Import-Module .\build\scripts\post-release.psm1
PushPackagesPublishReleaseUnlockAndPostNoticeOnPrepareReleasePullRequest `
-gitRepository '${{ github.repository }}' `
-pullRequestNumber '${{ github.event.issue.number }}' `
-botUserName '${{ needs.automation.outputs.username }}' `
-commentUserName '${{ github.event.comment.user.login }}' `
-artifactDownloadPath '${{ github.workspace }}/artifacts' `
-pushToNuget '${{ secrets.NUGET_TOKEN != '' }}'
post-release-published:
runs-on: ubuntu-latest
needs:
- automation
if: needs.automation.outputs.enabled
if: |
needs.automation.outputs.enabled
&& (github.event_name == 'release' || github.event_name == 'workflow_dispatch')
env:
GH_TOKEN: ${{ secrets[needs.automation.outputs.token-secret-name] }}

View File

@ -89,7 +89,7 @@ jobs:
-pullRequestNumber '${{ github.event.pull_request.number }}' `
-botUserName '${{ needs.automation.outputs.username }}'
create-release-tag-unlock-pr-post-notice:
create-release-tag-pr-post-notice:
runs-on: ubuntu-latest
needs: automation
@ -127,3 +127,4 @@ jobs:
-botUserName '${{ needs.automation.outputs.username }}' `
-gitUserName '${{ needs.automation.outputs.username }}' `
-gitUserEmail '${{ needs.automation.outputs.email }}'

View File

@ -53,7 +53,7 @@ jobs:
uses: actions/upload-artifact@v4
with:
name: ${{ github.ref_name }}-packages
path: '**/bin/**/*.*nupkg'
path: 'src/**/*.*nupkg'
- name: Publish MyGet
env:
@ -61,7 +61,7 @@ jobs:
if: env.MYGET_TOKEN_EXISTS == 'true' # Skip MyGet publish if run on a fork without the secret
run: |
nuget setApiKey ${{ secrets.MYGET_TOKEN }} -Source https://www.myget.org/F/opentelemetry/api/v2/package
nuget push **/bin/**/*.nupkg -Source https://www.myget.org/F/opentelemetry/api/v2/package
nuget push src/**/*.nupkg -Source https://www.myget.org/F/opentelemetry/api/v2/package
post-build:
runs-on: ubuntu-latest

View File

@ -1,6 +1,7 @@
# Release process
**Only for Maintainers.**
**Note: Approvers (collaborators) can perform much of the release process but
Maintainers (admins) are needed to merge PRs and for the push to NuGet.**
1. Decide the component(s) and tag name (version name) to be released. We use
[MinVer](https://github.com/adamralph/minver) to do versioning, which
@ -40,15 +41,13 @@
* `OpenTelemetry.Shims.OpenTracing` - Defined by spec (stable but
incomplete implementation)
* As of the `1.9.0` release cycle instrumentation packages and core
unstable packages always depend on the stable versions of core
packages. Before releasing a non-core component ensure the
`OTelLatestStableVer` property in `Directory.Packages.props` has been
updated to the latest stable core version.
* As of the `1.9.0` release cycle core unstable packages always depend on
the stable versions of core packages. Before releasing a non-core
component ensure the `OTelLatestStableVer` property in
`Directory.Packages.props` has been updated to the latest stable core
version.
2. Prepare for release
Run the [Prepare for a
2. Run the [Prepare for a
release](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/prepare-release.yml)
workflow. Specify the `tag-prefix` and the `version` for the release. Make
sure to run the workflow on the branch being released. This is typically
@ -91,11 +90,10 @@
comment and lock the PR. Post a comment with "/CreateReleaseTag" in the
body. This will tell the [Prepare for a
release](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/prepare-release.yml)
workflow to push the tag for the merge commit of the PR and to call the
[Build, pack, and publish to
workflow to push the tag for the merge commit of the PR which will trigger
the [Build, pack, and publish to
MyGet](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/publish-packages-1.0.yml)
workflow. Once packages are available a comment will be posted on the PR
opened in step 2 with a link to the artifacts.
workflow.
<details>
<summary>Instructions for pushing tags manually</summary>
@ -127,51 +125,76 @@
5. :stop_sign: Wait for the [Build, pack, and publish to
MyGet](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/publish-packages-1.0.yml)
workflow to complete.
6. Validate locally everything works using the MyGet packages pushed from the
release. Basic sanity checks :)
7. Download the artifacts from the drop attached to the workflow run. The
artifacts archive (`.zip`) contains all the NuGet packages (`.nupkg`) and
symbols (`.snupkg`) from the build which were pushed to MyGet.
8. Extract the artifacts from the archive (`.zip`) into a local folder.
9. Download latest [nuget.exe](https://www.nuget.org/downloads) into the same
folder from Step 8.
10. Create or regenerate an API key from nuget.org (only maintainers have
access). When creating API keys make sure it is set to expire in 1 day or
less.
11. Run the following commands from PowerShell from local folder used in Step 8:
```powershell
.\nuget.exe setApiKey <actual api key>
get-childitem -Recurse | where {$_.extension -eq ".nupkg"} | foreach ($_) {.\nuget.exe push $_.fullname -Source https://api.nuget.org/v3/index.json}
```
12. Validate that the package(s) are uploaded. Packages are available
immediately to maintainers on nuget.org but aren't publicly visible until
scanning completes. This process usually takes a few minutes.
13. Open the
[Releases](https://github.com/open-telemetry/opentelemetry-dotnet/releases)
page on the GitHub repository. The [Build, pack, and publish to
workflow to complete. When complete a trigger will automatically add a
comment on the PR opened by [Prepare for a
release](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/prepare-release.yml)
workflow in step 2. Use MyGet or download the packages using the provided
link to validate locally everything works. After validation has been
performed have a maintainer post a comment with "/PushPackages" in the body.
This will trigger the [Complete
release](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/prepare-release.yml)
workflow to push the packages to NuGet and publish the draft release created
by the [Build, pack, and publish to
MyGet](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/publish-packages-1.0.yml)
workflow creates a draft release for the tag which was pushed. Edit the
draft Release and click `Publish release`.
workflow. Comments will automatically be added on the PR opened by [Prepare
for a
release](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/prepare-release.yml)
workflow in step 2 as the process is run and the PR will be unlocked.
14. If a new stable version of the core packages was released, a PR should have
<details>
<summary>Instructions for pushing packages to NuGet manually</summary>
1. The [Build, pack, and publish to
MyGet](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/publish-packages-1.0.yml)
workflow pushes the packages to MyGet and attaches them as artifacts on
the workflow run.
2. Validate locally everything works using the packages pushed to MyGet or
downloaded from the drop attached to the workflow run. Basic sanity
checks :)
3. Download the artifacts from the drop attached to the workflow run. The
artifacts archive (`.zip`) contains all the NuGet packages (`.nupkg`) and
symbols (`.snupkg`) from the build which were pushed to MyGet.
4. Extract the artifacts from the archive (`.zip`) into a local folder.
5. Download latest [nuget.exe](https://www.nuget.org/downloads) into the
same folder from step 4.
6. Create or regenerate an API key from nuget.org (only maintainers have
access). When creating API keys make sure it is set to expire in 1 day or
less.
7. Run the following commands from PowerShell from local folder used in step
4:
```powershell
.\nuget.exe setApiKey <actual api key>
get-childitem -Recurse | where {$_.extension -eq ".nupkg"} | foreach ($_) {.\nuget.exe push $_.fullname -Source https://api.nuget.org/v3/index.json}
```
8. Validate that the package(s) are uploaded. Packages are available
immediately to maintainers on nuget.org but aren't publicly visible until
scanning completes. This process usually takes a few minutes.
9. Open the
[Releases](https://github.com/open-telemetry/opentelemetry-dotnet/releases)
page on the GitHub repository. The [Build, pack, and publish to
MyGet](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/publish-packages-1.0.yml)
workflow creates a draft release for the tag which was pushed. Edit the
draft Release and click `Publish release`.
</details>
6. If a new stable version of the core packages was released, a PR should have
been automatically created by the [Complete
release](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/post-release.yml)
workflow to update the `OTelLatestStableVer` property in
`Directory.Packages.props` to the just released stable version. Merge that
PR once the build passes (this requires the packages be available on NuGet).
15. The [Complete
7. The [Complete
release](https://github.com/open-telemetry/opentelemetry-dotnet/actions/workflows/post-release.yml)
workflow should have invoked the [Core version
update](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/actions/workflows/core-version-update.yml)
@ -180,6 +203,6 @@
repository which opens a PR to update dependencies. Verify this PR was
opened successfully.
16. Post an announcement in the [Slack
8. Post an announcement in the [Slack
channel](https://cloud-native.slack.com/archives/C01N3BC2W7Q). Note any big
or interesting new features as part of the announcement.

View File

@ -137,6 +137,8 @@ function TryPostPackagesReadyNoticeOnPrepareReleasePullRequest {
$body =
@"
The packages for [$tag](https://github.com/$gitRepository/releases/tag/$tag) are now available: $packagesUrl.
Once these packages have been validated have a maintainer post a comment with "/PushPackages" in the body if you would like me to push to NuGet.
"@
$pullRequestNumber = $pr.number
@ -150,6 +152,88 @@ The packages for [$tag](https://github.com/$gitRepository/releases/tag/$tag) are
Export-ModuleMember -Function TryPostPackagesReadyNoticeOnPrepareReleasePullRequest
function PushPackagesPublishReleaseUnlockAndPostNoticeOnPrepareReleasePullRequest {
param(
[Parameter(Mandatory=$true)][string]$gitRepository,
[Parameter(Mandatory=$true)][string]$pullRequestNumber,
[Parameter(Mandatory=$true)][string]$botUserName,
[Parameter(Mandatory=$true)][string]$commentUserName,
[Parameter(Mandatory=$true)][string]$artifactDownloadPath,
[Parameter(Mandatory=$true)][string]$pushToNuget
)
$prViewResponse = gh pr view $pullRequestNumber --json author,title,comments | ConvertFrom-Json
if ($prViewResponse.author.login -ne $botUserName)
{
throw 'PR author was unexpected'
}
$match = [regex]::Match($prViewResponse.title, '^\[repo\] Prepare release (.*)$')
if ($match.Success -eq $false)
{
throw 'Could not parse tag from PR title'
}
$tag = $match.Groups[1].Value
$commentUserPermission = gh api "repos/$gitRepository/collaborators/$commentUserName/permission" | ConvertFrom-Json
if ($commentUserPermission.permission -ne 'admin')
{
gh pr comment $pullRequestNumber `
--body "I'm sorry @$commentUserName but you don't have permission to push packages. Only maintainers can push to NuGet."
return
}
$foundComment = $false
$packagesUrl = ''
foreach ($comment in $prViewResponse.comments)
{
if ($comment.author.login -eq $botUserName -and $comment.body.StartsWith("The packages for [$tag](https://github.com/$gitRepository/releases/tag/$tag) are now available:"))
{
$foundComment = $true
break
}
}
if ($foundComment -eq $false)
{
throw 'Could not find package push comment on pr'
}
gh release download $tag `
-p "$tag-packages.zip" `
-D "$artifactDownloadPath"
Expand-Archive -LiteralPath "$artifactDownloadPath/$tag-packages.zip" -DestinationPath "$artifactDownloadPath\"
if ($pushToNuget -eq 'true')
{
gh pr comment $pullRequestNumber `
--body "I am uploading the packages for ``$tag`` to NuGet and then I will publish the release."
nuget push "$artifactDownloadPath/**/*.nupkg" -Source https://api.nuget.org/v3/index.json -ApiKey "$env.NUGET_TOKEN" -SymbolApiKey "$env.NUGET_TOKEN"
if ($LASTEXITCODE -gt 0)
{
gh pr comment $pullRequestNumber `
--body "Something went wrong uploading the packages for ``$tag`` to NuGet."
throw 'nuget push failure'
}
}
else {
gh pr comment $pullRequestNumber `
--body "I am publishing the release without uploading the packages to NuGet because a token wasn't configured."
}
gh release edit $tag --draft=false
gh pr unlock $pullRequestNumber
}
Export-ModuleMember -Function PushPackagesPublishReleaseUnlockAndPostNoticeOnPrepareReleasePullRequest
function CreateStableVersionUpdatePullRequest {
param(
[Parameter(Mandatory=$true)][string]$gitRepository,

View File

@ -100,7 +100,7 @@ function LockPullRequestAndPostNoticeToCreateReleaseTag {
@"
I noticed this PR was merged.
Post a comment with "/CreateReleaseTag" in the body if you would like me to create the release tag ``$tag`` for [the merge commit](https://github.com/$gitRepository/commit/$commit) and then trigger the package workflow.
Post a comment with "/CreateReleaseTag" in the body if you would like me to create the release tag ``$tag`` for [the merge commit](https://github.com/$gitRepository/commit/$commit) which will trigger the package workflow.
"@
gh pr comment $pullRequestNumber --body $body
@ -161,8 +161,6 @@ function CreateReleaseTagAndPostNoticeOnPullRequest {
throw 'git push failure'
}
gh pr unlock $pullRequestNumber
$body =
@"
I just pushed the [$tag](https://github.com/$gitRepository/releases/tag/$tag) tag.