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 Task. A Task is written in Python and stored in a file typically named task.py.

from rcmt import Task
from rcmt.action import Own
from rcmt.matcher import RepoName

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

    # Match all repositories of MyOrg.
    task.add_matcher(RepoName("github.com/MyOrg/.+"))
    # Add an action to the task. The action tells rcmt what to do.
    # The Own action creates a file and ensures that its content stays the same.
    task.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 ./task.py

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