From 4c8f251cf13a177fa50b54db2c3b5af41cf65d82 Mon Sep 17 00:00:00 2001 From: YanaXu Date: Fri, 20 Oct 2023 16:15:19 +0800 Subject: [PATCH] Add a github workflow to enforce reviews --- .github/enforce_review_paths.txt | 6 +++ .../workflows/enforce_required_reviewers.yml | 19 +++++++ .../enforce_required_reviewers_check.ps1 | 52 +++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 .github/enforce_review_paths.txt create mode 100644 .github/workflows/enforce_required_reviewers.yml create mode 100644 .github/workflows/script/enforce_required_reviewers_check.ps1 diff --git a/.github/enforce_review_paths.txt b/.github/enforce_review_paths.txt new file mode 100644 index 000000000000..b183e90305c3 --- /dev/null +++ b/.github/enforce_review_paths.txt @@ -0,0 +1,6 @@ +src/Compute/Compute +src/Compute/Compute.AlcWrapper +src/Compute/Compute.Autorest +src/Compute/Compute.Helpers +src/Compute/Compute.Management.Sdk +src/Compute/documentation diff --git a/.github/workflows/enforce_required_reviewers.yml b/.github/workflows/enforce_required_reviewers.yml new file mode 100644 index 000000000000..4d4627fb7cbe --- /dev/null +++ b/.github/workflows/enforce_required_reviewers.yml @@ -0,0 +1,19 @@ +name: Enforce Required Reviewers + +on: + pull_request: + pull_request_review: + +jobs: + Check: + runs-on: ubuntu-latest + steps: + - name: Check Reviewers + shell: pwsh + env: + REPOSITORY: ${{github.repository}} + PR_NO: ${{github.event.number || github.event.pull_request.number}} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + Invoke-WebRequest -Uri "https://raw.githubusercontent.com/${env:REPOSITORY}/main/.github/workflows/script/enforce_required_reviewers_check.ps1" -OutFile "./enforce_required_reviewers_check.ps1" + ./enforce_required_reviewers_check.ps1 \ No newline at end of file diff --git a/.github/workflows/script/enforce_required_reviewers_check.ps1 b/.github/workflows/script/enforce_required_reviewers_check.ps1 new file mode 100644 index 000000000000..669b68bf257c --- /dev/null +++ b/.github/workflows/script/enforce_required_reviewers_check.ps1 @@ -0,0 +1,52 @@ +# set the repository to $env:repository, e.g., $env:repository="Azure/azure-powershell" +# set the PR number to $env:prNo, e.g., $env:prNo=22145 +# set the GITHUB_TOKEN to $env:GITHUB_TOKEN if necessay, e.g., $env:GITHUB_TOKEN="******" + +$prNo = $env:PR_NO +$repository = $env:REPOSITORY +Invoke-WebRequest -Uri "https://raw.githubusercontent.com/$repository/main/.github/enforce_review_paths.txt" -OutFile "./enforce_review_paths.txt" +$enforceReivewPaths = Get-Content ./enforce_review_paths.txt +if ($enforceReivewPaths.Length -eq 0) { + Write-Host "No enforce review paths are configured. Skip it." + return +} + +$updatedFiles = (gh api -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" /repos/$repository/pulls/$prNo/files | ConvertFrom-Json).filename +Write-Host "All updated files in this PR $prNo : " +$updatedFiles + +$updatedEnforcePaths = @() +foreach ($enforceReivewPath in $enforceReivewPaths) { + $updatedEnforcePaths += $updatedFiles | Where-Object {$_.StartsWith($enforceReivewPath)} +} +$updatedEnforcePaths = $updatedEnforcePaths | Sort-Object -Unique +if ($updatedEnforcePaths.Length -eq 0) { + Write-Host "No enforce review paths are updated in this PR. Skip it." + return +} +Invoke-WebRequest -Uri "https://raw.githubusercontent.com/$repository/main/.github/CODEOWNERS" -OutFile "./CODEOWNERS" +$codeOwnerLines = Get-Content ./CODEOWNERS | Where-Object { ($_.trim().Length -gt 1) -and ($_.trim() -notlike "#*") } +$actualReviewers = (gh api -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" /repos/$repository/pulls/$prNo/reviews | ConvertFrom-Json).user.login +$actualReviewers = $actualReviewers ? $actualReviewers : @() # if no reviewers +Write-Host "All reviewers for this PR $prNo : " +$actualReviewers + +foreach ($updatedEnforcePath in $updatedEnforcePaths) { + foreach ($codeOwnerLine in $codeOwnerLines) { + $codeOwnerLineArray = ($codeOwnerLine.trim() -split "[ ]+") + if ($codeOwnerLineArray.Length -le 1) { + continue + } + $codeReivewPath = $codeOwnerLineArray[0] + if ($codeReivewPath.StartsWith('/')) { + $codeReivewPath = $codeReivewPath.Substring(1) + } + if ($updatedEnforcePath.StartsWith($codeReivewPath)) { + $codeReivewOwners = $codeOwnerLineArray[1..$codeOwnerLineArray.Length] | ForEach-Object { $_.Substring(1) } # remove '@' + $reviewerOwners = Compare-Object $codeReivewOwners $actualReviewers -PassThru -IncludeEqual -ExcludeDifferent + if ($reviewerOwners.Length -eq 0) { + throw "error: At least one of the required reviewers '$($codeReivewOwners -join "', '")' must approve the PR" + } + } + } +} \ No newline at end of file