reporule

A CLI for standardizing GitHub repository branch rulesets.

Overview

reporule is a command line interface (CLI) with two commands:

  • list: display a list of repos associated with a given GitHub org or user

  • ruleset: apply a pre-defined GitHub branch ruleset:

    • to all repos for a GitHub org or user

    • a single GitHub repo

Setup (one time)

  • Install [uv](https://docs.astral.sh/uv/getting-started/installation/) to manage the Python installs and environment

  • Create a fine-grained personal GitHub token

    1. Follow these GitHub directions for creating a fine-grained personal access token

    2. In the Repository access section, choose All repositories (this will give the token access to the same repository permissions that your personal GitHub account has)

    3. In the Permissions section, expand the Repository permissions section

    4. Find Administration on list set its Access to Read and write

    5. Click Generate token at bottom of the page

    6. Click Generate token again when prompted

  • Save the GitHub token as an environment variable called GITHUB_TOKEN

Using reporule

To use the reporule CLI, you can either install the Python package locally, or use uv’s tool feature to run the CLI without an explicit install.

For brevity, the examples in this readme work for a locally-installed package.

Install locally

If you’re comfortable installing Python packages, you can install reporule from GitHub. The most straightforward way to do this is via uv, which will handle setting up a virtual environment, installing Python (if required), and installing the package and its dependencies.

uv venv
uv pip install git+https://github.com/reichlab/reporule

In this case, CLI commands are prefixed by uv run. For example, to access the main CLI help:

uv run reporule --help

Run CLI without installing the package

If you’d prefer not to install YAPP (Yet Another Python Package), you can use uv’s tool feature to run the reporule CLI transiently (“in the background”) without an explicit install.

In this case, CLI commands are prefixed by uvx git+https://github.com/reichlab/reporule. For example, to access the main CLI help:

uvx git+https://github.com/reichlab/reporule --help

The incantation is a bit unwieldy, but using uvx will run the latest version of the code from GitHub, without you needed to worrying about installs of upgrade.

List repos command

This command lists all public repositories associated with a specific GitHub user or organization. We used a version of this in the past when auditing repositories in the reichlab GitHub org to review potential project to archive, for example.

 uv run reporule list --help

 Usage: reporule list [OPTIONS] ORG


 Display a list of public repositories and their
 selected attributes for a specific GitHub
 organization or user.

 EXAMPLE:
 --------
 reporule list hubverse-org

╭─ Arguments ───────────────────────────────────────────────╮
│ *    org      TEXT  [default: None] [required]            │
╰───────────────────────────────────────────────────────────╯
╭─ Options ─────────────────────────────────────────────────╮
│ --help          Show this message and exit.               │
╰───────────────────────────────────────────────────────────╯

For example, to list all public repositories for the bendystraw GitHub user:

 uv run reporule list bendystraw
Getting public repos for bendystraw...
2025-04-30 21:53:06 [info     ] Repository report complete     count=2
             Public repositories in the bendystraw GitHub organization
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━┓
┃ name                         created_at  archived  fork   gh_id    ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━┩
│ beeradvocate-reviews-waffle  2015-04-05  False     True   33453957 │
│ westernma-syrup              2015-04-05  False     False  33454863 │
└─────────────────────────────┴────────────┴──────────┴───────┴──────────┘

Ruleset command

This command applies a predefined GitHub branch ruleset to a single GitHub repository of to all public repositories within a specific org or user.

 uv run reporule ruleset --help

 Usage: reporule ruleset [OPTIONS] ORG

 Apply a specified ruleset to a single repo or to all eligible
 repos that belong to a GitHub organization or user.
 The default ruleset applied is defined in data/default_branch_protections.json

 Rulesets will not be applied to archived repos, repos listed in
 repos_exceptions.yml, or repos that already have a ruleset of the same name.

 EXAMPLES:
 ----------
 reporule ruleset reichlab --all --dryrun
 reporule ruleset reichlab --repo reichlab.io
 reporule ruleset hubverse-io --all --ruleset hubverse_branch_protections

╭─ Arguments ────────────────────────────────────────────────────────────────────────────────────────────╮
│ *    org      TEXT  GitHub organization or user name. [default: None] [required]                       │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────╯
╭─ Options ──────────────────────────────────────────────────────────────────────────────────────────────╮
│ --all                  Apply ruleset to all org/user repos not on the exception list. Cannot be used   │
│                        with --repo.                                                                    │
│ --repo           TEXT  GitHub repository name. Cannot be used with --all. [default: None]              │
│ --ruleset        TEXT  Ruleset filename to apply (without the .json extension). The file must be in    │
│                        the reporule/data directory.                                                    │
│                        [default: default_branch_protections]                                           │
│ --dryrun               Display repos to update without applying changes.                               │
│ --help                 Show this message and exit.                                                     │
╰────────────────────────────────────────────────────────────────────────────────────────────────────────╯

Criteria for applying a branch

Before applying a branch ruleset to a repo, reporule will ensure that the repo meets the following criteria:

  • is not archived

  • is not on the user/organization’s “exception” list: data/repos_exception.yml

  • does not already have a ruleset with the same name

Dryrun option

The ruleset command has a --dryrun option.

When this option is passed, uv run reporule ruleset will display the list of repositories to be updated without applying any changes.

 uv run reporule ruleset bendystraw --all --dryrun
DRY RUN: Getting list of eligible repositories...

DRY RUN: would apply ruleset default-branch-protections to 2 repositories:
   bendystraw/westernma-syrup
   bendystraw/beeradvocate-reviews-waffle