Declare "Areas" of your repository: logical portions of the codebase defined by file patterns.
Use those areas to:
- Enforce Review Rules: Automatically configure GitHub Repository Rulesets to require team reviews.
- Label Pull Requests: Automatically apply
area:<name>andteam:<slug>labels to PRs based on changed files.
- Supports blocking and request-only reviewers per area, and supports bypass rules for specific teams.
- Additive: Multiple rules can match the same file; all reviewers are added.
- Components first: The semantics is first on the component, not the team. Teams change over time, but components are more stable.
- Co-ownership: Components can have multiple stewards.
- Transparency & discoverability: Components, reviewers, and bypass rules are visible to every team, increasing trust and speeding reviewer discovery.
- Reusability: Shared open tool and
.areaspatterns encourage consistent ownership semantics across repos & teams.
- Create a
.areas/directory in your repository - Add area configuration files (see Configuration)
- Set up the GitHub workflows (see Usage)
Areas are defined as YAML files in the .areas/ directory.
Example:
# .areas/documentation.yaml
file_patterns:
- "docs/**"
- "**/.md"
reviewers:
doc-writer:
minimum_approvals: 1 # Blocking
qa-team:
minimum_approvals: 0 # Request Only (Non-blocking)
review_bypass:
team/docs-admins: always # Team can bypass (by team slug)
docs-admins: always # No prefix defaults to team
role/5: always # Repository role bypass (by role ID)
integration/139346: pull_request # GitHub App bypass (by installation ID)The review_bypass configuration supports different actor types via prefixes:
| Prefix | Description | Identifier |
|---|---|---|
| (none) | GitHub Team (default) | Team slug (e.g., docs-admins) |
team/ |
GitHub Team | Team slug (e.g., team/docs-admins) |
role/ |
Repository Role | Role ID as number (e.g., role/5) |
integration/ |
GitHub App | Installation ID as number (e.g., integration/139346) |
team/ is by slug, because they are ubiquitous and what user expect the most.
role/ and integration/ are "by id", because:
- The Ruleset API expects an ID.
- Roles don't have slugs and I’m not sure how to resolve a role name to an ID
- Integration IDs are difficult to get from the app id. It'd need a
org:readpermission. - It's fairly easy to get those values by exporting a ruleset from the UI.
- They should seldom be modified.
Bypass modes:
always- Can always bypass the rulesetpull_request- Can bypass only for pull requestsexempt- Will not be prompted to bypass
file_patterns is based on Ruby's File.fnmatch with the File::FNM_PATHNAME | File::FNM_DOTMATCH flags, but no other.
See GitHub's documentation and this test for examples
| Input | Description | Required | Default |
|---|---|---|---|
token |
GitHub Token (PAT with administration:write, members:read, contents:read, pull_requests:write, issues:write). |
true |
N/A |
command |
The mode to run: ruleset-sync or label-pr. |
true |
N/A |
working-directory |
Path containing the .areas folder. |
false |
. |
Keeps GitHub Rulesets in sync with your .areas/*.yaml configuration when pushed to main.
# .github/workflows/areas-ruleset-sync.yml
name: Sync Area Rulesets
on:
push:
branches: [main]
paths: ['.areas/**']
permissions:
contents: read # minimum permission to checkout the repo such that .areas can be parsed.
jobs:
label-pr:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
with:
sparse-checkout: .areas # Only needs access to the configuration
- uses: coveooss/areas@v0 # REPLACE ME
with:
token: ${{ secrets.TOKEN }}
command: ruleset-syncRequired permissions:
- Repository: Admin write
- Organization: Members:
read
Under the hood, it uses the update ruleset API, hence the admin permission.
Labels PRs with affected areas and teams.
This is completely optional and is only meant to be helpful to the users.
# .github/workflows/areas-label-pr.yml
name: Label PR with Areas
on:
pull_request:
types: [opened, synchronize]
permissions:
contents: read # minimum permission to checkout the repo such that .areas can be parsed.
jobs:
label-pr:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6
with:
sparse-checkout: .areas # Only needs access to the configuration
- uses: coveooss/areas@v0 # REPLACE ME
with:
token: ${{ secrets.TOKEN }}
command: label-prRequired permissions of the TOKEN:
- Repository: Pull Requests:
write - Organization: Members:
read
Under the hood, it needs to convert the team name to a team ID, hence the Organization Members permission.
See CONTRIBUTING.md for development setup and guidelines.
For AI coding assistants, see AGENTS.md for codebase context.