[repo] NuGet push release automation (#5675)
This commit is contained in:
parent
90871e01cb
commit
84cd83ad53
|
|
@ -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] }}
|
||||
|
|
|
|||
|
|
@ -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 }}'
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in New Issue