Smart PR Review Management_ A GitHub Action for Monorepos

Smart PR Review Management_ A GitHub Action for Monorepos

October 06, 2025
24 views
Get tips and best practices from Develeap’s experts in your inbox

#GitHub #GitHubActions #Monorepo #PullRequests

By Rotem Kalman

When a PR in a monorepo touches multiple areas, GitHub gives you a binary choice: keep all approvals or dismiss them all. That breaks review integrity, slows teams down, and lets the wrong approvals stay in place. In this guide I’ll show a GitHub Action that automatically dismisses only the stale approvals from owners of files that actually changed, while keeping valid approvals intact—so your reviews stay fast, fair, and compliant.

Why GitHub’s PR Approvals Break in Monorepos

As a DevOps engineer working with large monorepos, I’ve often encountered a frustrating limitation in GitHub’s PR review system. When new commits are pushed to a PR, GitHub only offers two options:

  1. keep all approvals
  2. dismiss all approvals. This binary choice becomes particularly problematic in monorepos where multiple teams own different parts of the codebase

https://github.com/RotemK1/auto-unapprove

The Monorepo Scenario: Multiple Teams, One PR

Let me illustrate this with a real scenario from our monorepo:

Repository Structure:
/repo
  /team-a/  # Owned by Team A
    /frontend/
    /api/
  /team-b/  # Owned by Team B
    /backend/
    /database/
  /team-c/  # Owned by Team C
    /infrastructure/
    /deployment/

When a PR touches multiple areas, we need approvals from different teams. For example:

  1. A developer changes files in both frontend and backend
  2. Team A approves the frontend changes
  3. Team B approves the backend changes
  4. The developer pushes new commits that only affect frontend files

At this point, GitHub gives us two options:

  • Keep all approvals (including Team A’s – even though their files changed and their previous approval became stale.
  • Dismiss all approvals (including Team B’s, even though their area wasn’t affected)

Neither option is ideal. The first option might allow code owners to approve their own changes, while the second option forces us to re-request approvals from teams whose code wasn’t even touched.

Round Robin ≠ Ownership: Where Assignments Fall Short

GitHub’s Round Robin feature automatically assigns reviewers to pull requests, rotating through team members to ensure fair distribution of review work. However, it doesn’t consider code ownership or handle stale reviews when new commits are pushed.

Our action complements Round Robin by:

  • Ensuring code owners can’t approve their own changes
  • Handling stale reviews when new commits are pushed
  • Maintaining review integrity while Round Robin handles fair distribution

Together, Round Robin and our action create a robust review process:

  • Round Robin: Fair distribution of review work
  • Our Action: Code quality through proper review separation

The Solution: Auto-Unapprove Reviews by Actual Ownership

To solve this, I developed a GitHub Action called “Auto Unapprove Reviews” that provides granular control over review dismissals. Here’s how it works:

The action follows a simple but effective flow:

  1. Get PR information
  2. Check changed files
  3. Check team ownership
  4. Analyze review status
  5. Take appropriate action

Key Features

  1. Smart Dismissal
  • Only dismisses approvals from code owners of changed files
  • Preserves valid approvals from other teams
  • Handles team-based ownership via CODEOWNERS
  1. Team Support
  • Works with GitHub teams
  • Supports hierarchical CODEOWNERS rules
  • Validates team memberships
  1. Performance Optimized
  • Parallel API calls
  • Efficient team checking
  • Smart caching

Real-World Impact

Since implementing this action, we’ve seen:

  • Reduced review cycles (from 3-4 to 1-2 per PR)
  • Better code quality through enforced review separation
  • Improved team productivity
  • Clearer ownership boundaries

How to Add the Action to Your Pipeline

name: Auto Unapprove

on:
  pull_request:
    types: [synchronize]

jobs:
  auto-unapprove:
    runs-on: ubuntu-latest
    env:
      ACTIONS_STEP_DEBUG: ${{ secrets.ACTIONS_STEP_DEBUG }}
    # Need to create github app and allow him access to - 
    steps:
      - uses: actions/create-github-app-token@v1
        id: app-token
        with:
          app-id: ${{ vars.REVIEWS_APP_ID }}
          private-key: ${{ secrets.REVIEWS_APP_PRIVATE_KEY }}

      - name: Dismiss Stale Reviews
        uses: RotemK1/auto-unapprove@main
        with:
          github-token: ${{ steps.app-token.outputs.token }}
          pr-number: ${{ github.event.number }}
          dry-run: 'false'
          target-branch: ${{ github.event.pull_request.base.ref }}
          team-start-with: '@your-org/'   

https://github.com/RotemK1/auto-unapprove

What the Action Prints (Example)

Here’s a real-world example of how the action works:

🚀 Smart Review Dismissal
   Repository: myorg/myrepo
   PR: #123
   Mode: 🧪 DRY RUN

📁 All changed files in PR (3):
   📝 src/gui/components/Button.tsx
   📝 src/gui/styles/theme.css  
   📝 src/gui/utils/helpers.ts

🎯 Target branch: main
👑 Parsed 15 CODEOWNERS rules

🎯 DISMISSAL ANALYSIS:
   🕐 Checking commits after jane-smith's approval (2025-06-04T12:49:59.000Z)...
     📅 Commit 55a4fc5 at 2025-06-04T12:53:44Z
       🎯 Modified owned files: src/gui/components/Button.tsx
   
   🚫 DISMISS @jane-smith
      📁 Files: src/gui/components/Button.tsx, src/gui/styles/theme.css, src/gui/utils/helpers.ts
      👑 Owner Via: @myorg/frontend-team
      💡 Reason: Approval became stale - commits modified owned files
   
   ✅ KEEP @bob-jones
      📄 Not owner of changed files

📊 EXECUTION PLAN:
   • Changed files: 3
   • Total approvals: 2
   • Dismissals needed: 1
   • Approvals preserved: 1

This example shows:

  • Clear identification of changed files
  • Detailed analysis of review status
  • Smart dismissal of stale approvals
  • Preservation of valid approvals
  • Comprehensive execution plan

Best Practices for CODEOWNERS and Teams

  1. CODEOWNERS Setup
  • Keep CODEOWNERS file up to date
  • Use team-based ownership
  • Document ownership boundaries
  1. Team Organization
  • Use GitHub teams for code ownership
  • Keep team membership current
  • Clear team responsibilities
  1. Round Robin Configuration
  • Set up Round Robin for each team
  • Ensure team size is appropriate for review load
  • Monitor review distribution
  • Adjust team membership based on review capacity
  1. Workflow Integration
  • Run on PR synchronization
  • Add status checks
  • Monitor action logs

Conclusion

This GitHub Action solves a real pain point in GitHub’s review system by providing granular control over review dismissals. It ensures:

  • Code owners can’t approve their own changes
  • Teams only need to re-review changes in their area
  • The review process remains efficient and effective

The action works seamlessly with GitHub’s Round Robin review assignment, creating a robust review process where:

  • Round Robin ensures fair distribution of review work
  • Our action maintains code quality through proper review separation
  • Together they provide a complete solution for monorepo review management

The action is open-source and available on GitHub. Feel free to try it out and contribute to its development. Whether you’re working in a small team or a large monorepo, this action can help streamline your review process while maintaining high code quality standards.

Skip to content