Mainfast

Mainfast Owners

Free, MIT

CODEOWNERS rots quietly: people leave, teams are renamed, paths move, and files end up with no reviewer. On a pull request Mainfast Owners lists the changed files no working code owner covers and lints the PR's own CODEOWNERS edit. Once a week it audits the whole file, dormant owners included.

What it catches

  • unowned-files: changed files whose deciding line has no owner, or only owners who cannot review. The comment suggests lines to add.
  • unknown-user, owner-left-org, owner-no-write: owners who do not exist, left the org, or lack write access.
  • team-not-found, team-no-write, team-wrong-org: teams that do not exist, cannot write to the repo, or belong to another org.
  • rule-without-valid-owner: a line whose owners are all invalid, so its paths are unowned.
  • invalid-line, github-error, too-large: syntax GitHub skips (negation, [ ] ranges, GitLab sections), GitHub's own errors, files over 3 MB.
  • pattern-matches-nothing and shadowed-rule: dead patterns, and lines that never decide a file because later lines win.
  • dormant-owner and dormant-team (weekly audit only): no PR review in 180 days by default.

What you see

A real PR comment from a private test repository, where a PR adds a file no CODEOWNERS rule covers.

PR comment: a changed file with no code owner, with suggested CODEOWNERS lines.

Install

GitHub Actions workflow (no checkout needed)yaml
name: Mainfast Owners
on:
  pull_request:
  schedule:
    - cron: "23 6 * * 1"   # weekly audit
  workflow_dispatch:
permissions:
  contents: read
  pull-requests: write
jobs:
  owners:
    runs-on: ubuntu-latest
    steps:
      - uses: mainfast/owners@v0
        with:
          org-token: ${{ secrets.MAINFAST_OWNERS_ORG_TOKEN }}   # optional
CLIsh
npx mainfast-owners lint --repo .                                   # offline, no token
GITHUB_TOKEN=... npx mainfast-owners audit --github-repo owner/name [--ref main]
GITHUB_TOKEN=... npx mainfast-owners pr --github-repo owner/name --pr 42 [--comment]

Step by step, with what to check after each part: installation manual. Everything else: the README.

Permissions

  • contents: read: CODEOWNERS and .mainfast.yml at the base/default branch and PR head, the git tree, and GitHub's CODEOWNERS errors. Without it the run stops.
  • pull-requests: write: reads the PR's changed files and posts the one sticky comment. With read only there is no comment but the result stands.
  • Optional org-token with Organization permission Members: Read-only (a fine-grained token or a GitHub App). Store it as the MAINFAST_OWNERS_ORG_TOKEN secret.
  • Without the org-token, org membership, team existence and team access are skipped with one note; teams count as valid and users are still checked.
  • GITHUB_TOKEN cannot have any organization permission, so it can never see private org membership or teams.
  • Dormancy uses the search API (30 requests a minute), at most 100 requests per run by default.

Privacy

  • Everything is read through the GitHub API at the base or default branch, never from a checkout. No PR code is fetched or run, so pull_request_target is safe too.
  • For fork PRs and outside authors, owners are checked for public account existence only, and the org-token is never used.
  • This stops a PR author using the comment to probe your org by putting any @user or @org/team into CODEOWNERS.
  • Nothing is sent to a third party; only GitHub API calls with your tokens. With a licence key, only the key and the organisation id go to Polar to check it.
  • File paths, patterns, owners, team slugs and GitHub error text are escaped: no HTML, no links, no @ mentions.

Limits

  • A renamed file is judged by its new path only.
  • Dormancy counts PRs the user reviewed in the window, per GitHub search; review comments without a review do not count. Never checked on PRs.
  • The comment lists the first 50 unowned paths and 100 findings per table; the report output has all.
  • A truncated tree listing (very large repositories) skips dead and shadowed patterns, with a note.
  • Email owners cannot be verified through the API.
  • A PR is judged against the base branch's CODEOWNERS, so a path it newly covers still shows as unowned until the line is merged.

Install Mainfast Owners

Catch CODEOWNERS drift: unowned files, departed owners, missing teams, dead patterns.