Update to .NET 9 #403
Workflow file for this run
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: approve-and-merge | |
on: | |
pull_request: | |
branches: [ main, dotnet-vnext ] | |
env: | |
REVIEWER_LOGIN: ${{ vars.REVIEWER_USER_NAME }} | |
permissions: | |
contents: read | |
jobs: | |
review-pull-request: | |
runs-on: ubuntu-latest | |
if: ${{ github.event.pull_request.user.login == vars.UPDATER_COMMIT_USER_NAME }} | |
steps: | |
- name: Generate GitHub application token | |
id: generate-application-token | |
uses: peter-murray/workflow-application-token-action@dc0413987a085fa17d19df9e47d4677cf81ffef3 # v3.0.0 | |
with: | |
application_id: ${{ secrets.REVIEWER_APPLICATION_ID }} | |
application_private_key: ${{ secrets.REVIEWER_APPLICATION_PRIVATE_KEY }} | |
permissions: "contents:write, pull_requests:write" | |
- name: Install powershell-yaml | |
shell: pwsh | |
run: Install-Module -Name powershell-yaml -Force -MaximumVersion "0.4.7" | |
- name: Check which dependencies were updated | |
id: check-dependencies | |
env: | |
# This list of trusted package prefixes needs to stay in sync with include-nuget-packages in the update-dotnet-sdk workflow. | |
INCLUDE_NUGET_PACKAGES: "Microsoft.AspNetCore.,Microsoft.EntityFrameworkCore.,Microsoft.Extensions.,Microsoft.NET.Test.Sdk" | |
GH_TOKEN: ${{ steps.generate-application-token.outputs.token }} | |
shell: pwsh | |
run: | | |
# Replicate the logic in the dependabot/fetch-metadata action. | |
# See https://github.com/dependabot/fetch-metadata/blob/aea2135c95039f05c64436f1d14638c300e10b2b/src/dependabot/update_metadata.ts#L29-L68. | |
# Query the GitHub API to get the commits in the pull request. | |
$commits = gh api ` | |
/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/commits ` | |
--jq '.[] | { author: .author.login, message: .commit.message }' | ConvertFrom-Json | |
# We should only approve pull requests that only contain commits from | |
# the GitHub user we expected and only commits that contain the metadata | |
# we need to determine what dependencies were updated by the other workflow. | |
$expectedUser = "${{ vars.UPDATER_COMMIT_USER_NAME }}" | |
$onlyDependencyUpdates = $True | |
$onlyChangesFromUser = $True | |
$dependencies = @() | |
foreach ($commit in $commits) { | |
if ($commit.Author -ne $expectedUser) { | |
# Some other commit is in the pull request | |
$onlyChangesFromUser = $False | |
} | |
# Extract the YAML metadata block from the commit message. | |
$match = [Regex]::Match($commit.Message, '(?m)^-{3}\s(?<dependencies>[\S|\s]*?)\s^\.{3}$') | |
if ($match.Success -eq $True) { | |
# Extract the names and update type from each dependency. | |
$metadata = ($match.Value | ConvertFrom-Yaml -Ordered) | |
$updates = $metadata["updated-dependencies"] | |
if ($updates) { | |
foreach ($update in $updates) { | |
$dependencies += @{ | |
Name = $update['dependency-name']; | |
Type = $update['update-type']; | |
} | |
} | |
} | |
} | |
else { | |
# The pull request contains a commit that we didn't expect as the metadata is missing. | |
$onlyDependencyUpdates = $False | |
} | |
} | |
# Did we find at least one dependency? | |
$isPatch = $dependencies.Length -gt 0 | |
$onlyTrusted = $dependencies.Length -gt 0 | |
$trustedPackages = $env:INCLUDE_NUGET_PACKAGES.Split(',') | |
foreach ($dependency in $dependencies) { | |
$isPatch = $isPatch -And $dependency.Type -eq "version-update:semver-patch" | |
$onlyTrusted = $onlyTrusted -And | |
( | |
($dependency.Name -eq "Microsoft.NET.Sdk") -Or | |
(($trustedPackages | Where-Object { $dependency.Name.StartsWith($_) }).Count -gt 0) | |
) | |
} | |
# We only trust the pull request to approve and auto-merge it | |
# if it only contains commits which change the .NET SDK and | |
# Microsoft-published NuGet packages that were made by the GitHub | |
# login we expect to make those changes in the other workflow. | |
$isTrusted = (($onlyTrusted -And $isPatch) -And $onlyChangesFromUser) -And $onlyDependencyUpdates | |
"is-trusted-update=$isTrusted" >> $env:GITHUB_OUTPUT | |
- name: Checkout code | |
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 | |
# As long as it's not already approved, approve the pull request and enable auto-merge. | |
# Our CI tests coupled with required statuses should ensure that the changes compile | |
# and that the application is still functional after the update; any bug that might be | |
# introduced by the update should be caught by the tests. If that happens, the build | |
# workflow will fail and the preconditions for the auto-merge to happen won't be met. | |
- name: Approve pull request and enable auto-merge | |
if: ${{ steps.check-dependencies.outputs.is-trusted-update == 'true' }} | |
env: | |
GH_TOKEN: ${{ steps.generate-application-token.outputs.token }} | |
PR_URL: ${{ github.event.pull_request.html_url }} | |
shell: pwsh | |
run: | | |
$approvals = gh api /repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/reviews | ConvertFrom-Json | |
$approvals = $approvals | Where-Object { $_.user.login -eq $env:REVIEWER_LOGIN } | |
$approvals = $approvals | Where-Object { $_.state -eq "APPROVED" } | |
if ($approvals.Length -eq 0) { | |
gh pr checkout "$env:PR_URL" | |
gh pr review --approve "$env:PR_URL" | |
gh pr merge --auto --squash "$env:PR_URL" | |
} | |
else { | |
Write-Host "PR already approved."; | |
} | |
# If something was present in the pull request that isn't expected, then disable | |
# auto-merge so that a human is required to look at the pull request and make a | |
# decision to merge it or not. This is to prevent the pull request from being merged | |
# automatically if there's an unexpected change introduced. Any existing review | |
# approvals that were made by the bot are also dismissed so human approval is required. | |
- name: Disable auto-merge and dismiss approvals | |
if: ${{ steps.check-dependencies.outputs.is-trusted-update != 'true' }} | |
env: | |
GH_TOKEN: ${{ steps.generate-application-token.outputs.token }} | |
PR_URL: ${{ github.event.pull_request.html_url }} | |
shell: pwsh | |
run: | | |
$approvals = gh api /repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/reviews | ConvertFrom-Json | |
$approvals = $approvals | Where-Object { $_.user.login -eq $env:REVIEWER_LOGIN } | |
$approvals = $approvals | Where-Object { $_.state -eq "APPROVED" } | |
if ($approvals.Length -gt 0) { | |
gh pr checkout "$env:PR_URL" | |
gh pr merge --disable-auto "$env:PR_URL" | |
foreach ($approval in $approvals) { | |
gh api ` | |
--method PUT ` | |
/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/reviews/$($approval.id)/dismissals ` | |
-f message='Cannot approve as other changes have been introduced.' ` | |
-f event='DISMISS' | |
} | |
} | |
else { | |
Write-Host "PR not already approved."; | |
} |