Skip to content

Commit 9078ceb

Browse files
[repo] Automate tasks performed when a core release is pushed from main repo (open-telemetry#1819)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 80e1e99 commit 9078ceb

File tree

3 files changed

+290
-2
lines changed

3 files changed

+290
-2
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Core version update
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
tag:
7+
required: true
8+
description: 'Release tag'
9+
type: string
10+
11+
permissions:
12+
contents: write
13+
pull-requests: write
14+
15+
jobs:
16+
core-version-update:
17+
18+
runs-on: windows-latest
19+
20+
steps:
21+
- uses: actions/checkout@v4
22+
with:
23+
# Note: By default GitHub only fetches 1 commit. MinVer needs to find
24+
# the version tag which is typically NOT on the first commit so we
25+
# retrieve them all.
26+
fetch-depth: 0
27+
28+
- name: Setup dotnet
29+
uses: actions/setup-dotnet@v4
30+
31+
- name: Create GitHub Pull Request to update core version in props and update CHANGELOGs in projects
32+
shell: pwsh
33+
run: |
34+
Import-Module .\build\scripts\post-release.psm1
35+
36+
CreateOpenTelemetryCoreLatestVersionUpdatePullRequest `
37+
-tag '${{ inputs.tag }}'
38+
env:
39+
GH_TOKEN: ${{ github.token }}

build/scripts/post-release.psm1

Lines changed: 250 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ function CreateRelease {
2828

2929
$changelogContent = Get-Content -Path "src/$packageName/CHANGELOG.md"
3030

31-
$headingWritten = $false
3231
$started = $false
3332
$content = ""
3433

@@ -181,7 +180,7 @@ function CreatePackageValidationBaselineVersionUpdatePullRequest {
181180

182181
$body =
183182
@"
184-
Note: This PR was opened automatically by the [package workflow](https://github.com/$gitRepository/actions/workflows/Component.Package.yml).
183+
Note: This PR was opened automatically by the [package workflow](https://github.com/$gitRepository/actions/workflows/publish-packages.yml).
185184
186185
Merge once packages are available on NuGet and the build passes.
187186
@@ -199,3 +198,252 @@ Merge once packages are available on NuGet and the build passes.
199198
}
200199

201200
Export-ModuleMember -Function CreatePackageValidationBaselineVersionUpdatePullRequest
201+
202+
function CreateOpenTelemetryCoreLatestVersionUpdatePullRequest {
203+
param(
204+
[Parameter(Mandatory=$true)][string]$tag,
205+
[Parameter()][string]$gitUserName=$gitHubBotUserName,
206+
[Parameter()][string]$gitUserEmail=$gitHubBotEmail,
207+
[Parameter()][string]$targetBranch="main"
208+
)
209+
210+
$match = [regex]::Match($tag, '^(.*?-)(.*)$')
211+
if ($match.Success -eq $false)
212+
{
213+
throw 'Could not parse prefix from tag'
214+
}
215+
216+
$tagPrefix = $match.Groups[1].Value
217+
if ($tagPrefix.StartsWith('core-') -eq $false)
218+
{
219+
Return
220+
}
221+
222+
$projectsAndDependenciesBefore = GetCoreDependenciesForProjects
223+
224+
$version = $match.Groups[2].Value
225+
$isPrerelease = ($version.Contains('-alpha.') -or $version.Contains('-beta.') -or $version.Contains('-rc.'))
226+
227+
$branch="release/post-core-${version}-update"
228+
229+
$propertyName = "OpenTelemetryCoreLatestVersion"
230+
$propertyVersion = "[$version,2.0)"
231+
if ($isPrerelease -eq $true)
232+
{
233+
$propertyName = "OpenTelemetryCoreLatestPrereleaseVersion"
234+
$propertyVersion = "[$version]"
235+
}
236+
237+
(Get-Content build/Common.props) `
238+
-replace "<$propertyName>.*<\/$propertyName>", "<$propertyName>$propertyVersion</$propertyName>" |
239+
Set-Content build/Common.props
240+
241+
$projectsAndDependenciesAfter = GetCoreDependenciesForProjects
242+
243+
$changedProjects = @{}
244+
245+
$projectsAndDependenciesBefore.GetEnumerator() | ForEach-Object {
246+
$projectDir = $_.Key
247+
$projectDependenciesBefore = $_.Value
248+
$projectDependenciesAfter = $projectsAndDependenciesAfter[$projectDir]
249+
250+
$projectDependenciesBefore.GetEnumerator() | ForEach-Object {
251+
$packageName = $_.Key
252+
$packageVersionBefore = $_.Value
253+
if ($projectDependenciesAfter[$packageName] -ne $packageVersionBefore)
254+
{
255+
$changedProjects[$projectDir] = $true
256+
}
257+
}
258+
}
259+
260+
git config user.name $gitUserName
261+
git config user.email $gitUserEmail
262+
263+
git switch --create $branch origin/$targetBranch --no-track 2>&1 | % ToString
264+
if ($LASTEXITCODE -gt 0)
265+
{
266+
throw 'git switch failure'
267+
}
268+
269+
git add build/Common.props 2>&1 | % ToString
270+
if ($LASTEXITCODE -gt 0)
271+
{
272+
throw 'git add failure'
273+
}
274+
275+
git commit -m "Update $propertyName in Common.props to $version." 2>&1 | % ToString
276+
if ($LASTEXITCODE -gt 0)
277+
{
278+
throw 'git commit failure'
279+
}
280+
281+
git push -u origin $branch 2>&1 | % ToString
282+
if ($LASTEXITCODE -gt 0)
283+
{
284+
throw 'git push failure'
285+
}
286+
287+
$body =
288+
@"
289+
Note: This PR was opened automatically by the [core version update workflow](https://github.com/$gitRepository/actions/workflows/core-version-update.yml).
290+
291+
Merge once packages are available on NuGet and the build passes.
292+
293+
## Changes
294+
295+
* Sets ``$propertyName`` in ``Common.props`` to ``$version``.
296+
"@
297+
298+
$createPullRequestResponse = gh pr create `
299+
--title "[repo] Core release $version updates" `
300+
--body $body `
301+
--base $targetBranch `
302+
--head $branch `
303+
--label infra
304+
305+
$match = [regex]::Match($createPullRequestResponse, "\/pull\/(.*)$")
306+
if ($match.Success -eq $false)
307+
{
308+
throw 'Could not parse pull request number from gh pr create response'
309+
}
310+
311+
$pullRequestNumber = $match.Groups[1].Value
312+
313+
if ($changedProjects.Count -eq 0)
314+
{
315+
Return
316+
}
317+
318+
$entry = @"
319+
* Updated OpenTelemetry core component version(s) to ``$version``.
320+
([#$pullRequestNumber](https://github.com/$gitRepository/pull/$pullRequestNumber))
321+
322+
323+
"@
324+
325+
$lastLineBlank = $true
326+
327+
foreach ($projectDir in $changedProjects.Keys)
328+
{
329+
$path = Join-Path -Path $projectDir -ChildPath "CHANGELOG.md"
330+
331+
$changelogContent = Get-Content -Path $path
332+
333+
$started = $false
334+
$isRemoving = $false
335+
$content = ""
336+
337+
foreach ($line in $changelogContent)
338+
{
339+
if ($line -like "## Unreleased" -and $started -ne $true)
340+
{
341+
$started = $true
342+
}
343+
elseif ($line -like "## *" -and $started -eq $true)
344+
{
345+
if ($lastLineBlank -eq $false)
346+
{
347+
$content += "`r`n"
348+
}
349+
$content += $entry
350+
$started = $false
351+
$isRemoving = $false
352+
}
353+
elseif ($line -like '*Update* OpenTelemetry SDK version to*' -and $started -eq $true)
354+
{
355+
$isRemoving = $true
356+
continue
357+
}
358+
359+
if ($line.StartsWith('* '))
360+
{
361+
if ($isRemoving -eq $true)
362+
{
363+
$isRemoving = $false
364+
}
365+
366+
if ($lastLineBlank -eq $false)
367+
{
368+
$content += "`r`n"
369+
}
370+
}
371+
372+
if ($isRemoving -eq $true)
373+
{
374+
continue
375+
}
376+
377+
$content += $line + "`r`n"
378+
379+
$lastLineBlank = [string]::IsNullOrWhitespace($line)
380+
}
381+
382+
if ($started -eq $true)
383+
{
384+
# Note: If we never wrote the entry it means the file ended in the unreleased section
385+
if ($lastLineBlank -eq $false)
386+
{
387+
$content += "`r`n"
388+
}
389+
$content += $entry
390+
}
391+
392+
Set-Content -Path $path -Value $content.TrimEnd()
393+
394+
git add $path 2>&1 | % ToString
395+
if ($LASTEXITCODE -gt 0)
396+
{
397+
throw 'git add failure'
398+
}
399+
}
400+
401+
git commit -m "Update CHANGELOGs for projects using $propertyName." 2>&1 | % ToString
402+
if ($LASTEXITCODE -gt 0)
403+
{
404+
throw 'git commit failure'
405+
}
406+
407+
git push -u origin $branch 2>&1 | % ToString
408+
if ($LASTEXITCODE -gt 0)
409+
{
410+
throw 'git push failure'
411+
}
412+
}
413+
414+
Export-ModuleMember -Function CreateOpenTelemetryCoreLatestVersionUpdatePullRequest
415+
416+
function GetCoreDependenciesForProjects {
417+
$projects = @(Get-ChildItem -Path 'src/*/*.csproj')
418+
419+
$projectsAndDependencies = @{}
420+
421+
foreach ($project in $projects)
422+
{
423+
# Note: dotnet restore may fail if the core packages aren't available yet but that is fine, we just want to generate project.assets.json for these projects.
424+
$output = dotnet restore $project
425+
426+
$projectDir = $project | Split-Path -Parent
427+
428+
$content = (Get-Content "$projectDir/obj/project.assets.json" -Raw)
429+
430+
$projectDependencies = @{}
431+
432+
$matches = [regex]::Matches($content, '"(OpenTelemetry(?:.*))?": {[\S\s]*?"target": "Package",[\S\s]*?"version": "(.*)"[\S\s]*?}')
433+
foreach ($match in $matches)
434+
{
435+
$packageName = $match.Groups[1].Value
436+
$packageVersion = $match.Groups[2].Value
437+
if ($packageName -eq 'OpenTelemetry' -or
438+
$packageName -eq 'OpenTelemetry.Api' -or
439+
$packageName -eq 'OpenTelemetry.Api.ProviderBuilderExtensions' -or
440+
$packageName -eq 'OpenTelemetry.Extensions.Hosting')
441+
{
442+
$projectDependencies[$packageName.ToString()] = $packageVersion.ToString()
443+
}
444+
}
445+
$projectsAndDependencies[$projectDir.ToString()] = $projectDependencies
446+
}
447+
448+
return $projectsAndDependencies
449+
}

opentelemetry-dotnet-contrib.sln

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{
3333
.github\workflows\ci.yml = .github\workflows\ci.yml
3434
.github\workflows\codeql-analysis.yml = .github\workflows\codeql-analysis.yml
3535
.github\workflows\Component.BuildTest.yml = .github\workflows\Component.BuildTest.yml
36+
.github\workflows\core-version-update.yml = .github\workflows\core-version-update.yml
3637
.github\workflows\dotnet-format.yml = .github\workflows\dotnet-format.yml
3738
.github\workflows\integration.yml = .github\workflows\integration.yml
3839
.github\workflows\markdownlint.yml = .github\workflows\markdownlint.yml

0 commit comments

Comments
 (0)