Skip to content

Commit 32f9c65

Browse files
committed
Add a workflow for kicking of component releases.
1 parent f1fd71f commit 32f9c65

File tree

3 files changed

+390
-0
lines changed

3 files changed

+390
-0
lines changed
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
name: Prepare for a release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
component:
7+
type: choice
8+
options:
9+
- OpenTelemetry.Exporter.Geneva
10+
- OpenTelemetry.Exporter.InfluxDB
11+
- OpenTelemetry.Exporter.Instana
12+
- OpenTelemetry.Exporter.OneCollector
13+
- OpenTelemetry.Exporter.Stackdriver
14+
- OpenTelemetry.Extensions
15+
- OpenTelemetry.Extensions.AWS
16+
- OpenTelemetry.Extensions.Enrichment
17+
- OpenTelemetry.Instrumentation.AspNet
18+
- OpenTelemetry.Instrumentation.AspNet.TelemetryHttpModule
19+
- OpenTelemetry.Instrumentation.AspNetCore
20+
- OpenTelemetry.Instrumentation.AWS
21+
- OpenTelemetry.Instrumentation.AWSLambda
22+
- OpenTelemetry.Instrumentation.Cassandra
23+
- OpenTelemetry.Instrumentation.ElasticsearchClient
24+
- OpenTelemetry.Instrumentation.EntityFrameworkCore
25+
- OpenTelemetry.Instrumentation.EventCounters
26+
- OpenTelemetry.Instrumentation.GrpcCore
27+
- OpenTelemetry.Instrumentation.GrpcNetClient
28+
- OpenTelemetry.Instrumentation.Hangfire
29+
- OpenTelemetry.Instrumentation.Http
30+
- OpenTelemetry.Instrumentation.MassTransit
31+
- OpenTelemetry.Instrumentation.MySqlData
32+
- OpenTelemetry.Instrumentation.Owin
33+
- OpenTelemetry.Instrumentation.Process
34+
- OpenTelemetry.Instrumentation.Quartz
35+
- OpenTelemetry.Instrumentation.Runtime
36+
- OpenTelemetry.Instrumentation.SqlClient
37+
- OpenTelemetry.Instrumentation.StackExchangeRedis
38+
- OpenTelemetry.Instrumentation.Wcf
39+
- OpenTelemetry.PersistentStorage.Abstractions
40+
- OpenTelemetry.PersistentStorage.FileSystem
41+
- OpenTelemetry.Resources.AWS
42+
- OpenTelemetry.Resources.Azure
43+
- OpenTelemetry.Resources.Container
44+
- OpenTelemetry.Resources.Gcp
45+
- OpenTelemetry.Resources.Host
46+
- OpenTelemetry.Resources.Process
47+
- OpenTelemetry.Resources.ProcessRuntime
48+
- OpenTelemetry.Sampler.AWS
49+
- OpenTelemetry.SemanticConventions
50+
description: 'Release component'
51+
required: true
52+
version:
53+
type: string
54+
description: 'Release version'
55+
required: true
56+
57+
pull_request:
58+
types:
59+
- closed
60+
61+
issue_comment:
62+
types:
63+
- created
64+
65+
permissions:
66+
contents: write
67+
pull-requests: write
68+
69+
jobs:
70+
prepare-release-pr:
71+
if: github.event_name == 'workflow_dispatch'
72+
73+
runs-on: windows-latest
74+
75+
steps:
76+
- name: check out code
77+
uses: actions/checkout@v4
78+
79+
- name: Create GitHub Pull Request to prepare release
80+
shell: pwsh
81+
run: |
82+
Import-Module .\build\scripts\prepare-release.psm1
83+
84+
CreatePullRequestToUpdateChangelogsAndPublicApis `
85+
-component '${{ inputs.component }}' `
86+
-version '${{ inputs.version }}' `
87+
-targetBranch '${{ github.ref_name }}'
88+
env:
89+
GH_TOKEN: ${{ github.token }}
90+
91+
lock-pr-and-post-notice-to-create-release-tag:
92+
if: |
93+
github.event_name == 'pull_request'
94+
&& github.event.action == 'closed'
95+
&& github.event.pull_request.user.login == 'github-actions[bot]'
96+
&& github.event.pull_request.merged == true
97+
&& startsWith(github.event.pull_request.title, '[repo] Prepare release ')
98+
99+
runs-on: windows-latest
100+
101+
steps:
102+
- name: check out code
103+
uses: actions/checkout@v4
104+
105+
- name: Lock GitHub Pull Request to prepare release
106+
shell: pwsh
107+
run: |
108+
Import-Module .\build\scripts\prepare-release.psm1
109+
110+
LockPullRequestAndPostNoticeToCreateReleaseTag `
111+
-pullRequestNumber '${{ github.event.pull_request.number }}'
112+
env:
113+
GH_TOKEN: ${{ github.token }}
114+
115+
create-release-tag-unlock-pr-post-notice:
116+
if: |
117+
github.event_name == 'issue_comment'
118+
&& github.event.issue.pull_request
119+
&& github.event.issue.locked == true
120+
&& contains(github.event.comment.body, '/CreateReleaseTag')
121+
&& startsWith(github.event.issue.title, '[repo] Prepare release ')
122+
&& github.event.issue.pull_request.merged_at
123+
124+
runs-on: windows-latest
125+
126+
outputs:
127+
tag: ${{ steps.create-tag.outputs.tag }}
128+
129+
steps:
130+
- name: check out code
131+
uses: actions/checkout@v4
132+
with:
133+
# Note: By default GitHub only fetches 1 commit which fails the git tag operation below
134+
fetch-depth: 0
135+
136+
- name: Create release tag
137+
id: create-tag
138+
shell: pwsh
139+
run: |
140+
Import-Module .\build\scripts\prepare-release.psm1
141+
142+
$tag = ''
143+
144+
CreateReleaseTag `
145+
-pullRequestNumber '${{ github.event.issue.number }}' `
146+
-actionRunId '${{ github.run_id }}' `
147+
-tag ([ref]$tag)
148+
149+
echo "tag=$tag" >> $env:GITHUB_OUTPUT
150+
env:
151+
GH_TOKEN: ${{ github.token }}
152+
153+
invoke-package-workflow:
154+
needs: create-release-tag-unlock-pr-post-notice
155+
uses: ./.github/workflows/publish-packages.yml
156+
with:
157+
tag: ${{ needs.create-release-tag-unlock-pr-post-notice.outputs.tag }}
158+
159+
post-packages-ready-notice:
160+
needs:
161+
- create-release-tag-unlock-pr-post-notice
162+
- invoke-package-workflow
163+
runs-on: windows-latest
164+
steps:
165+
- name: check out code
166+
uses: actions/checkout@v4
167+
168+
- name: Post notice when packages are ready
169+
shell: pwsh
170+
run: |
171+
Import-Module .\build\scripts\prepare-release.psm1
172+
173+
PostPackagesReadyNotice `
174+
-pullRequestNumber '${{ github.event.issue.number }}' `
175+
-tag '${{ needs.create-release-tag-unlock-pr-post-notice.outputs.tag }}' `
176+
-packagesUrl '${{ needs.invoke-package-workflow.outputs.artifact-url }}'
177+
env:
178+
GH_TOKEN: ${{ github.token }}

build/scripts/prepare-release.psm1

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
$gitHubBotUserName="github-actions[bot]"
2+
$gitHubBotEmail="41898282+github-actions[bot]@users.noreply.github.com"
3+
4+
$repoViewResponse = gh repo view --json nameWithOwner | ConvertFrom-Json
5+
6+
$gitRepository = $repoViewResponse.nameWithOwner
7+
8+
function CreatePullRequestToUpdateChangelogsAndPublicApis {
9+
param(
10+
[Parameter(Mandatory=$true)][string]$component,
11+
[Parameter(Mandatory=$true)][string]$version,
12+
[Parameter()][string]$gitUserName=$gitHubBotUserName,
13+
[Parameter()][string]$gitUserEmail=$gitHubBotEmail,
14+
[Parameter()][string]$targetBranch="main"
15+
)
16+
17+
$projectContent = Get-Content -Path src/$component/$component.csproj
18+
19+
$match = [regex]::Match($projectContent, '<MinVerTagPrefix>(.*)<\/MinVerTagPrefix>')
20+
if ($match.Success -eq $false)
21+
{
22+
throw 'Could not parse MinVerTagPrefix from project file'
23+
}
24+
25+
$minVerTagPrefix = $match.Groups[1].Value
26+
$tag="${minVerTagPrefix}${version}"
27+
$branch="release/prepare-${tag}-release"
28+
29+
git config user.name $gitUserName
30+
git config user.email $gitUserEmail
31+
32+
git switch --create $branch 2>&1 | % ToString
33+
if ($LASTEXITCODE -gt 0)
34+
{
35+
throw 'git switch failure'
36+
}
37+
38+
$body =
39+
@"
40+
Note: This PR was opened automatically by the [prepare release workflow](https://github.com/$gitRepository/actions/workflows/prepare-release.yml).
41+
42+
## Changes
43+
44+
* CHANGELOG files updated for projects being released.
45+
"@
46+
47+
# Update CHANGELOGs
48+
& ./build/scripts/update-changelogs.ps1 -minVerTagPrefix $minVerTagPrefix -version $version
49+
50+
# Update publicApi files for stable releases
51+
if ($version -notlike "*-alpha*" -and $version -notlike "*-beta*" -and $version -notlike "*-rc*")
52+
{
53+
& ./build/scripts/finalize-publicapi.ps1 -minVerTagPrefix $minVerTagPrefix
54+
55+
$body += "`r`n* Public API files updated for projects being released (only performed for stable releases)."
56+
}
57+
58+
git commit -a -m "Prepare repo to release $tag." 2>&1 | % ToString
59+
if ($LASTEXITCODE -gt 0)
60+
{
61+
throw 'git commit failure'
62+
}
63+
64+
git push -u origin $branch 2>&1 | % ToString
65+
if ($LASTEXITCODE -gt 0)
66+
{
67+
throw 'git push failure'
68+
}
69+
70+
gh pr create `
71+
--title "[repo] Prepare release $tag" `
72+
--body $body `
73+
--base $targetBranch `
74+
--head $branch `
75+
--label infra
76+
}
77+
78+
Export-ModuleMember -Function CreatePullRequestToUpdateChangelogsAndPublicApis
79+
80+
function LockPullRequestAndPostNoticeToCreateReleaseTag {
81+
param(
82+
[Parameter(Mandatory=$true)][string]$pullRequestNumber,
83+
[Parameter()][string]$gitUserName=$gitHubBotUserName,
84+
[Parameter()][string]$gitUserEmail=$gitHubBotEmail
85+
)
86+
87+
git config user.name $gitUserName
88+
git config user.email $gitUserEmail
89+
90+
$prViewResponse = gh pr view $pullRequestNumber --json mergeCommit,author,title | ConvertFrom-Json
91+
92+
if ($prViewResponse.author.is_bot -eq $false -or $prViewResponse.author.login -ne 'app/github-actions')
93+
{
94+
throw 'PR author was unexpected'
95+
}
96+
97+
$match = [regex]::Match($prViewResponse.title, '^\[repo\] Prepare release (.*)$')
98+
if ($match.Success -eq $false)
99+
{
100+
throw 'Could not parse tag from PR title'
101+
}
102+
103+
$tag = $match.Groups[1].Value
104+
105+
$commit = $prViewResponse.mergeCommit.oid
106+
if ([string]::IsNullOrEmpty($commit) -eq $true)
107+
{
108+
throw 'Could not find merge commit'
109+
}
110+
111+
$body =
112+
@"
113+
I noticed this PR was merged.
114+
115+
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.
116+
"@
117+
118+
gh pr comment $pullRequestNumber --body $body
119+
120+
gh pr lock $pullRequestNumber
121+
}
122+
123+
Export-ModuleMember -Function LockPullRequestAndPostNoticeToCreateReleaseTag
124+
125+
function CreateReleaseTag {
126+
param(
127+
[Parameter(Mandatory=$true)][string]$pullRequestNumber,
128+
[Parameter(Mandatory=$true)][string]$actionRunId,
129+
[Parameter()][string]$gitUserName=$gitHubBotUserName,
130+
[Parameter()][string]$gitUserEmail=$gitHubBotEmail,
131+
[Parameter()][ref]$tag
132+
)
133+
134+
git config user.name $gitUserName
135+
git config user.email $gitUserEmail
136+
137+
$prViewResponse = gh pr view $pullRequestNumber --json mergeCommit,author,title | ConvertFrom-Json
138+
139+
if ($prViewResponse.author.is_bot -eq $false -or $prViewResponse.author.login -ne 'app/github-actions')
140+
{
141+
throw 'PR author was unexpected'
142+
}
143+
144+
$match = [regex]::Match($prViewResponse.title, '^\[repo\] Prepare release (.*)$')
145+
if ($match.Success -eq $false)
146+
{
147+
throw 'Could not parse tag from PR title'
148+
}
149+
150+
$tagValue = $match.Groups[1].Value
151+
152+
$commit = $prViewResponse.mergeCommit.oid
153+
if ([string]::IsNullOrEmpty($commit) -eq $true)
154+
{
155+
throw 'Could not find merge commit'
156+
}
157+
158+
git tag -a $tagValue -m "$tagValue" $commit 2>&1 | % ToString
159+
if ($LASTEXITCODE -gt 0)
160+
{
161+
throw 'git tag failure'
162+
}
163+
164+
git push origin $tagValue 2>&1 | % ToString
165+
if ($LASTEXITCODE -gt 0)
166+
{
167+
throw 'git push failure'
168+
}
169+
170+
gh pr unlock $pullRequestNumber
171+
172+
$body =
173+
@"
174+
I just pushed the [$tagValue](https://github.com/$gitRepository/releases/tag/$tagValue) tag.
175+
176+
The [package workflow](https://github.com/$gitRepository/actions/runs/$actionRunId) should begin momentarily.
177+
"@
178+
179+
gh pr comment $pullRequestNumber --body $body
180+
181+
$tag.value = $tagValue
182+
}
183+
184+
Export-ModuleMember -Function CreateReleaseTag
185+
186+
function PostPackagesReadyNotice {
187+
param(
188+
[Parameter(Mandatory=$true)][string]$pullRequestNumber,
189+
[Parameter(Mandatory=$true)][string]$tag,
190+
[Parameter(Mandatory=$true)][string]$packagesUrl
191+
)
192+
193+
$body =
194+
@"
195+
The packages for [$tag](https://github.com/$gitRepository/releases/tag/$tag) are now available: $packagesUrl.
196+
197+
Have a nice day!
198+
"@
199+
200+
gh pr comment $pullRequestNumber --body $body
201+
}
202+
203+
Export-ModuleMember -Function PostPackagesReadyNotice

0 commit comments

Comments
 (0)