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 .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.

First, you create a Package. A package is a directory that contains the file manifest.yaml. The manifest describes which Actions to apply to a repository. The directory can contain additional files that some actions need to work.

The basic directory structure of a package looks like this:

.
|____packages
| |____flake8
| | |____.flake8
| | |____manifest.yaml

And the Manifest looks like this:

# This name identifies the package.
# rcmt errors if two packages share the same name.
name: flake8
# Actions tell rcmt what to do and how.
actions:
    # The action to apply. The "own" action lets rcmt
    # take ownership of the file.
    # rcmt resets the file if somebody changes it in a repository.
    own:
      # Path to the source file rcmt should put in a repository.
      # This path is relative to the manifest.yaml file.
      source: .flake8
      # Path to the target where rcmt writes the content of source.
      # This is relative to the root path of a repository.
      target: .flake8

Packages describe what to do, but not to which repositories they apply. rcmt expects a matcher to do this:

# Match all repositories of MyOrg.
match: github.com/MyOrg/+*
# rcmt uses this name when committing changes.
name: python-defaults
# A list of package names to apply to all matching repositories.
# "flake8" is the name set in the manifest.yaml file of the
# flake8 package.
packages: ["flake8"]

Everything is ready. Run rcmt:

rcmt run --packages ./packages ./matcher.yaml

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