From a8e8d27492ee86201911ed6b901fb129ca2b0e20 Mon Sep 17 00:00:00 2001 From: Zack Pollard Date: Tue, 8 Jul 2025 12:58:12 +0100 Subject: [PATCH] chore: required reviewers --- .github/workflows/required-reviewers.yml | 82 ++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 .github/workflows/required-reviewers.yml diff --git a/.github/workflows/required-reviewers.yml b/.github/workflows/required-reviewers.yml new file mode 100644 index 0000000000..075465b659 --- /dev/null +++ b/.github/workflows/required-reviewers.yml @@ -0,0 +1,82 @@ +name: Required Reviewers Check + +on: + pull_request_review: + types: [submitted] + +jobs: + check-member-review: + runs-on: ubuntu-latest + permissions: + pull-requests: read + contents: read + + steps: + - name: Check for team/admin review + uses: actions/github-script@v7 + with: + script: | + const { owner, repo } = context.repo; + const prNumber = context.payload.pull_request.number; + + console.log(`Checking reviews for PR #${prNumber}`); + + try { + // Fetch the users.json file from immich-app/devtools repository + const { data: usersFile } = await github.rest.repos.getContent({ + owner: 'immich-app', + repo: 'devtools', + path: 'tf/deployment/data/users.json' + }); + + const usersData = JSON.parse(Buffer.from(usersFile.content, 'base64').toString()); + console.log(`Loaded ${usersData.length} users from devtools repo`); + + // Create a map of GitHub IDs to user roles for efficient lookup + const userRoles = new Map(); + for (const user of usersData) { + if (user.github && user.github.id && (user.role === 'team' || user.role === 'admin')) { + userRoles.set(user.github.id, { + username: user.github.username, + role: user.role + }); + } + } + + console.log(`Found ${userRoles.size} team/admin users`); + + // Get all reviews for the pull request + const { data: reviews } = await github.rest.pulls.listReviews({ + owner, + repo, + pull_number: prNumber + }); + + console.log(`Found ${reviews.length} reviews`); + + // Check if any review is from a team/admin member + let hasValidReview = false; + + for (const review of reviews) { + console.log(`Review by ${review.user.login} (ID: ${review.user.id}): state=${review.state}`); + + // Check if the reviewer is a team/admin member and the review is approved + const userInfo = userRoles.get(review.user.id); + if (userInfo && review.state === 'APPROVED') { + console.log(`✅ Found approved review from ${userInfo.role} member: ${review.user.login}`); + hasValidReview = true; + break; + } + } + + if (!hasValidReview) { + console.log('❌ No approved review from team/admin member found'); + core.setFailed('This pull request requires an approved review from a team or admin member'); + } else { + console.log('✅ Required team/admin member review found'); + } + + } catch (error) { + console.error('Error checking reviews:', error); + core.setFailed(`Failed to check reviews: ${error.message}`); + }