A CLI that distributes shared config files to multiple GitHub repositories as pull requests, using a Kustomize-like base/overlay structure
Project description
ghfanout
Manage shared configuration files (.gitignore, pom.xml, …) in one place, and fan them out to many GitHub repositories as pull requests (or direct pushes). Edit a file once, run one command, and every affected repository gets a PR.
- No
git cloneof target repositories — everything goes through the GitHub Git Data API, so it works with nothing more thanpip install - Kustomize-like base + overlay composition, with Jinja2 templating for per-repository values
- Designed for microservice fleets that cannot be consolidated into a monorepo
Installation
pip install ghfanout # or: uv tool install ghfanout
Requires Python 3.11 or later (tested on 3.11–3.14).
Quick start
# 1. Generate a config repository scaffold (with a working sample)
ghfanout init ./my-config --org myorg
cd my-config
# 2. Compose base + overlay locally and inspect the result (no git operations, no network)
ghfanout build example-service # output: dist/example-service/
# 3. Authenticate, preview the diff against the real repository, then deploy
export GHFANOUT_TOKEN=ghp_xxxx
ghfanout deploy example-service --dry-run
ghfanout deploy example-service # opens a PR if there is a diff
How it fits together — base/ holds the content, overlays/ selects who gets it:
ghfanout.yaml # destination host / org
.ghfanoutignore # optional: files under base/ to exclude (.gitignore syntax)
base/
common/ # distributed to every repository
.gitignore
java-service/ # a profile: distributed only to repos that opt in
pom.xml.tmpl # .tmpl = Jinja2 template, rendered per repository
overlays/
user-service/ # directory name = target repository name
manifest.yaml # which profiles / branches this repo receives
api-gateway/
manifest.yaml
Documentation
Full documentation: https://seiya-koji.github.io/ghfanout/
- Getting Started — install → init → build → deploy, end to end
- Configuration — config repository layout,
ghfanout.yaml,manifest.yaml, per-branch overrides - Templates — embedding per-repository values with Jinja2
- Authentication — PAT and GitHub App
- CLI Reference — commands, options, and behavior details
- Development — local setup, tests, lint, and commit conventions
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ghfanout-0.1.0.tar.gz.
File metadata
- Download URL: ghfanout-0.1.0.tar.gz
- Upload date:
- Size: 19.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ec361a0fde8cea3bd4ec608eb25fc0a363fcffe03969eeb122b2442caa735558
|
|
| MD5 |
24b7812ab58e42222604f8b396528bd4
|
|
| BLAKE2b-256 |
efb5fddea85377c365ed3b1a74470ba1a5f8014988b3b75a2e08d702a26cf80c
|
File details
Details for the file ghfanout-0.1.0-py3-none-any.whl.
File metadata
- Download URL: ghfanout-0.1.0-py3-none-any.whl
- Upload date:
- Size: 23.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
40825e0aecc58e1fa22fa3eb1a47e1ae533883d6d62104d4cb1b4776aa54a9c7
|
|
| MD5 |
8ae3e2989ada9b14c0ecd263fc9a033a
|
|
| BLAKE2b-256 |
db94e602342f83b931febf38d263b7de3d074142a2db7b3f5b329012a94ca580
|