Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[repo] Release request issue template & automation #2080

Merged
merged 18 commits into from
Sep 20, 2024
Merged
81 changes: 81 additions & 0 deletions .github/ISSUE_TEMPLATE/release_request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
name: Release request
title: "[release request] "
description: Request a release for a component
labels: ["release"]
body:
- type: markdown
attributes:
value: |
Fill out this form to request a release of one of the components in this repository.

- type: dropdown
id: component
attributes:
label: Component
description: Which component does this release request concern?
multiple: false
options:
- OpenTelemetry.Exporter.Geneva
- OpenTelemetry.Exporter.InfluxDB
- OpenTelemetry.Exporter.Instana
- OpenTelemetry.Exporter.OneCollector
- OpenTelemetry.Exporter.Stackdriver
- OpenTelemetry.Extensions
- OpenTelemetry.Extensions.AWS
- OpenTelemetry.Extensions.Enrichment
- OpenTelemetry.Instrumentation.AspNet
- OpenTelemetry.Instrumentation.AspNet.TelemetryHttpModule
- OpenTelemetry.Instrumentation.AspNetCore
- OpenTelemetry.Instrumentation.AWS
- OpenTelemetry.Instrumentation.AWSLambda
- OpenTelemetry.Instrumentation.Cassandra
- OpenTelemetry.Instrumentation.ConfluentKafka
- OpenTelemetry.Instrumentation.ElasticsearchClient
- OpenTelemetry.Instrumentation.EntityFrameworkCore
- OpenTelemetry.Instrumentation.EventCounters
- OpenTelemetry.Instrumentation.GrpcCore
- OpenTelemetry.Instrumentation.GrpcNetClient
- OpenTelemetry.Instrumentation.Hangfire
- OpenTelemetry.Instrumentation.Http
- OpenTelemetry.Instrumentation.MassTransit
- OpenTelemetry.Instrumentation.MySqlData
- OpenTelemetry.Instrumentation.Owin
- OpenTelemetry.Instrumentation.Process
- OpenTelemetry.Instrumentation.Quartz
- OpenTelemetry.Instrumentation.Runtime
- OpenTelemetry.Instrumentation.SqlClient
- OpenTelemetry.Instrumentation.StackExchangeRedis
- OpenTelemetry.Instrumentation.Wcf
- OpenTelemetry.PersistentStorage.Abstractions
- OpenTelemetry.PersistentStorage.FileSystem
- OpenTelemetry.Resources.AWS
- OpenTelemetry.Resources.Azure
- OpenTelemetry.Resources.Container
- OpenTelemetry.Resources.Gcp
- OpenTelemetry.Resources.Host
- OpenTelemetry.Resources.OperatingSystem
- OpenTelemetry.Resources.Process
- OpenTelemetry.Resources.ProcessRuntime
- OpenTelemetry.Sampler.AWS
- OpenTelemetry.SemanticConventions
validations:
required: true

- type: input
attributes:
label: Version
description: |
What is the requested version for the release?
Version must specify [Major].[Minor].[Patch] and may also include prerelease information -[alpha|beta|rc].[Increment].
Examples:
* 1.9.0
* 1.10.0-rc.1
* 0.2.0-alpha.3
* 1.12.0-beta.2
CodeBlanch marked this conversation as resolved.
Show resolved Hide resolved
validations:
required: true

- type: textarea
attributes:
label: Additional context
description: Any additional information you think may be relevant to this release request.
55 changes: 55 additions & 0 deletions .github/workflows/prepare-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,20 @@ on:
type: string
description: 'Release version'
required: true
releaseIssue:
type: string
description: 'Release request issue'
required: false

pull_request:
types:
- closed

issues:
types:
- opened
- edited

issue_comment:
types:
- created
Expand Down Expand Up @@ -95,6 +104,7 @@ jobs:
-component '${{ inputs.component }}' `
-version '${{ inputs.version }}' `
-requestedByUserName '${{ github.event.sender.login }}' `
-releaseIssue '${{ inputs.releaseIssue }}' `
-targetBranch '${{ github.ref_name }}' `
-gitUserName '${{ needs.automation.outputs.username }}' `
-gitUserEmail '${{ needs.automation.outputs.email }}'
Expand Down Expand Up @@ -209,3 +219,48 @@ jobs:
-commentUserName '${{ github.event.comment.user.login }}' `
-gitUserName '${{ needs.automation.outputs.username }}' `
-gitUserEmail '${{ needs.automation.outputs.email }}'

process-release-request-issue:
runs-on: ubuntu-latest

needs: automation

if: |
startsWith(github.event.issue.title, '[release request] ')
&& github.event.issue.pull_request == null
&& needs.automation.outputs.enabled
&& (
(github.event_name == 'issues')
||
(github.event_name == 'issue_comment'
&& github.event.issue.state == 'open'
&& contains(github.event.comment.body, '/PrepareRelease')
&& github.event.comment.user.login != needs.automation.outputs.username)
)

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] }}

- name: Process release request issue being opened or commented
shell: pwsh
run: |
Import-Module .\build\scripts\prepare-release.psm1

TagCodeOwnersOnOrRunWorkflowForRequestReleaseIssue `
-gitRepository '${{ github.repository }}' `
-targetBranch '${{ github.event.repository.default_branch }}' `
-triggeringEventName '${{ github.event_name }}' `
-approvingGroups '@${{ github.repository_owner }}/dotnet-approvers @${{ github.repository_owner }}/dotnet-maintainers' `
-requestedByUserName '${{ github.event.comment.user.login || github.event.sender.login }}' `
-issueNumber '${{ github.event.issue.number }}' `
-issueBody $env:ISSUE_BODY `
-gitUserName '${{ needs.automation.outputs.username }}' `
-gitUserEmail '${{ needs.automation.outputs.email }}'
env:
ISSUE_BODY: ${{ github.event.issue.body }}
161 changes: 160 additions & 1 deletion build/scripts/prepare-release.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ function CreatePullRequestToUpdateChangelogsAndPublicApis {
[Parameter(Mandatory=$true)][string]$component,
[Parameter(Mandatory=$true)][string]$version,
[Parameter(Mandatory=$true)][string]$requestedByUserName,
[Parameter()][string]$releaseIssue,
[Parameter()][string]$targetBranch="main",
[Parameter()][string]$gitUserName,
[Parameter()][string]$gitUserEmail
Expand Down Expand Up @@ -42,10 +43,19 @@ function CreatePullRequestToUpdateChangelogsAndPublicApis {
throw 'git switch failure'
}

if ([string]::IsNullOrEmpty($releaseIssue) -eq $false)
{
$issueText =
@"

Release request: #$releaseIssue
"@
}

$body =
@"
Note: This PR was opened automatically by the [prepare release workflow](https://github.com/$gitRepository/actions/workflows/prepare-release.yml).

$issueText
Requested by: @$requestedByUserName

## Changes
Expand Down Expand Up @@ -304,3 +314,152 @@ Released $(Get-Date -UFormat '%Y-%b-%d')
}

Export-ModuleMember -Function UpdateChangelogReleaseDatesAndPostNoticeOnPullRequest

function TagCodeOwnersOnOrRunWorkflowForRequestReleaseIssue {
param(
[Parameter(Mandatory=$true)][string]$gitRepository,
[Parameter(Mandatory=$true)][string]$triggeringEventName,
[Parameter(Mandatory=$true)][string]$approvingGroups,
[Parameter(Mandatory=$true)][string]$requestedByUserName,
[Parameter(Mandatory=$true)][string]$issueNumber,
[Parameter(Mandatory=$true)][string]$issueBody,
[Parameter()][string]$targetBranch="main",
[Parameter()][string]$gitUserName,
[Parameter()][string]$gitUserEmail
)

$match = [regex]::Match($issueBody, '^[#]+ Component\s*(OpenTelemetry\.(?:.|\w+)+)$', [Text.RegularExpressions.RegexOptions]::Multiline)
if ($match.Success -eq $false)
{
Write-Host 'Component could not be parsed from body'
Return
}

$component = $match.Groups[1].Value.Trim()

$match = [regex]::Match($issueBody, '^[#]+ Version\s*(.*)$', [Text.RegularExpressions.RegexOptions]::Multiline)
if ($match.Success -eq $false)
{
Write-Host 'Version could not be parsed from body'
Return
}

$version = $match.Groups[1].Value.Trim()

$match = [regex]::Match($version, '^(\d+\.\d+\.\d+)(?:-((?:alpha)|(?:beta)|(?:rc))\.(\d+))?$')
if ($match.Success -eq $false)
{
gh issue comment $issueNumber `
--body "The version specified on the release request is invalid. Please create a new release request with a valid version or edit the description and set a valid version."
Return
}

$projectPath = "src/$component/$component.csproj"

if ((Test-Path -Path $projectPath) -eq $false)
{
gh issue comment $issueNumber `
--body "I couldn't find the project file for the requested component. Please create a new release request and select a valid component or edit the description and set a valid component."
Return
}

$projectContent = Get-Content -Path $projectPath

$match = [regex]::Match($projectContent, '<MinVerTagPrefix>(.*)<\/MinVerTagPrefix>')
if ($match.Success -eq $false)
{
gh issue comment $issueNumber `
--body "I couldn't find ``MinVerTagPrefix`` in the project file for the requested component. Please create a new release request and select a valid component or edit the description and set a valid component."
Return
}

$minVerTagPrefix = $match.Groups[1].Value

$projectDirs = Get-ChildItem -Path src/**/*.csproj | Select-String "<MinVerTagPrefix>$minVerTagPrefix</MinVerTagPrefix>" -List | Select Path | Split-Path -Parent

$componentOwnersContent = Get-Content '.github/component_owners.yml' -Raw

$componentOwners = [System.Collections.Generic.HashSet[string]]::new([System.StringComparer]::OrdinalIgnoreCase)

foreach ($projectDir in $projectDirs)
{
$projectName = [System.IO.Path]::GetFileName($projectDir)

$match = [regex]::Match($componentOwnersContent, "src\/$projectName\/:([\w\W\s]*?)src")
if ($match.Success -eq $true)
{
$matches = [regex]::Matches($match.Groups[1].Value, "-\s*(.*)")
foreach ($match in $matches)
{
$owner = $match.Groups[1].Value
$_ = $componentOwners.Add($owner.Trim())
}
}
}

$requestedByUserPermission = gh api "repos/$gitRepository/collaborators/$requestedByUserName/permission" | ConvertFrom-Json

$kickOffWorkflow = $false
$kickOffWorkflowReason = ''

if ($requestedByUserPermission.permission -eq 'admin' -or $requestedByUserPermission.permission -eq 'write')
{
$kickOffWorkflow = $true
$kickOffWorkflowReason = "@$requestedByUserName has collaborator or greater permission"
}
elseif ($componentOwners.Contains($requestedByUserName) -eq $true)
{
$kickOffWorkflow = $true
$kickOffWorkflowReason = "@$requestedByUserName is a component owner"
}

if ($kickOffWorkflow -eq $true)
{
CreatePullRequestToUpdateChangelogsAndPublicApis `
-gitRepository $gitRepository `
-component $component `
-version $version `
-requestedByUserName $requestedByUserName `
-releaseIssue $issueNumber `
-targetBranch $targetBranch `
-gitUserName $gitUserName `
-gitUserEmail $gitUserEmail

gh issue close $issueNumber `
--comment "I executed the prepare release script for ``$component`` version ``$version``` because $kickOffWorkflowReason."

return
}

if ($triggeringEventName -eq 'issues')
{
# Executed when issues are created or edited
$componentOwnerApprovers = ''
if ($componentOwners.Count -gt 0)
{
foreach ($componentOwner in $componentOwners)
{
$componentOwnerApprovers += "@$componentOwner "
}
}

$body =
@"
$componentOwnerApprovers$approvingGroups

Post a comment with "/PrepareRelease" in the body if you would like me to execute the prepare release script for the component and version listed in the description.
"@

gh issue comment $issueNumber --body $body
}
else {
# Executed when issues are commented with the /PrepareRelease command
if ($kickOffWorkflow -eq $false)
{
gh issue comment $issueNumber `
--body "I'm sorry @$requestedByUserName but you don't have permission to execute the prepare release script. Only maintainers, approvers, and/or owners of the component may use the `"/PrepareRelease`" command."
}
}
}

Export-ModuleMember -Function TagCodeOwnersOnOrRunWorkflowForRequestReleaseIssue
1 change: 1 addition & 0 deletions opentelemetry-dotnet-contrib.sln
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ISSUE_TEMPLATE", "ISSUE_TEM
ProjectSection(SolutionItems) = preProject
.github\ISSUE_TEMPLATE\bug_report.yml = .github\ISSUE_TEMPLATE\bug_report.yml
.github\ISSUE_TEMPLATE\feature_request.yml = .github\ISSUE_TEMPLATE\feature_request.yml
.github\ISSUE_TEMPLATE\release_request.yml = .github\ISSUE_TEMPLATE\release_request.yml
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenTelemetry.Instrumentation.ConfluentKafka", "src\OpenTelemetry.Instrumentation.ConfluentKafka\OpenTelemetry.Instrumentation.ConfluentKafka.csproj", "{96341E23-990E-4144-A7E3-9EF0DAFF3232}"
Expand Down
Loading