rcmt

rcmt (short for Repository Configuration Management Tool) helps aligning configuration files across many repositories. It creates, modifies or deletes files in multiple repositories, then creates a Pull Request that contains the changes for each repository.

Quick start

Let’s say you want to make flake8 compatible with black. To accomplish this, the file .flake8 can be placed into every repository.

The content of the file .flake8 looks like this:

[flake8]
max-line-length = 88
extend-ignore = E203

Having to place this file in every repository, commit the change, create a pull request, wait for a build job to succeed and then merge the pull request is no fun. This is where rcmt can help.

rcmt needs configuration that tells it what to do and to which repositories it should apply changes. This is done via a Run. A Run is written in Python and stored in a file typically named run.py.

from rcmt import Run
from rcmt.matcher import RepoName
from rcmt.package.action import Own

# rcmt uses the name when committing changes.
with Run(name="python-defaults") as run:
    content = """[flake8]
max-line-length = 88
extend-ignore = E203
"""

    # Match all repositories of MyOrg.
    run.add_matcher(RepoName("github.com/MyOrg/.+"))
    # Add an action to the run. The action tells rcmt what to do.
    # The Own action creates a file and ensures that its content stays the same.
    run.add_action(
        Own(
            # The content of the file to write.
            content=content,
            # Path to the target where rcmt writes the content of source.
            # This is relative to the root path of a repository.
            target=".flake8",
        )
    )

Everything is ready. Run rcmt:

rcmt run ./run.py

rcmt will find all matching repositories, check them out locally, apply the package and create a Pull Request for each repository.