Provision a repo across self-hosted GitLab, GitLab.com, and GitHub with push mirroring.
Project description
🐉 Hydra
One source, many mirrors — provision a repo across self-hosted GitLab, GitLab.com, and GitHub in one shot, with push mirroring wired up automatically.
The self-hosted GitLab is the source of truth. Hydra creates the repo on all three hosts, then sets up push mirrors on the self-hosted project so pushes fan out to GitLab.com and GitHub.
⚠️ If you're forking from repo-syncer
The original syncer.py had API tokens committed in plaintext. Revoke them immediately:
- GitHub: https://github.com/settings/tokens
- GitLab.com: https://gitlab.com/-/user_settings/personal_access_tokens
- Your self-hosted GitLab:
<your-host>/-/user_settings/personal_access_tokens
Hydra never writes tokens to the YAML config.
Install
python -m venv venv && source venv/bin/activate
pip install -e .
hydra --version
For development (includes pytest):
pip install -e '.[dev]'
pytest
Onboarding
hydra configure
A four-step wizard walks you through hosts, defaults, and tokens:
- Hosts — self-hosted GitLab, GitLab.com, and GitHub URLs.
- GitHub account — user account or organization.
- Defaults — default group path, default visibility.
- API tokens — choose where to store: OS keyring (recommended), shell-export lines, or skip and set env vars yourself.
The wizard writes non-secret settings to ~/.config/hydra/config.yaml. Tokens go to your OS keyring (macOS Keychain, Linux Secret Service) — never to the YAML.
Token resolution order
For each host, Hydra looks up the token in this order:
- OS keyring (set via
hydra configure, or directly withkeyring set hydra <github|gitlab|self_hosted_gitlab>) - Environment variable:
HYDRA_GITHUB_TOKEN,HYDRA_GITLAB_TOKEN,HYDRA_SELF_HOSTED_GITLAB_TOKEN .envfile in the current working directory (see.env.example)- Interactive prompt (only if attached to a TTY)
Creating repos
Two modes — interactive wizard, or flag-driven for scripting.
Interactive
hydra create
The wizard collects the repo name, description, group, visibility, GitHub destination, and mirror toggle, then shows a review summary. At the end you choose between create now, dry-run, or cancel.
Flags
# Dry-run (no API calls)
hydra create my-repo -d "demo" -g platform/services --dry-run
# Real run (defaults from config.yaml)
hydra create my-repo -d "demo" -g platform/services
# Public repo, under a GitHub org, no mirrors
hydra create my-repo --public --github-org acme --no-mirror
If you omit the name, the wizard launches; with a name you stay in flag mode.
Inspecting mirrors
hydra status my-repo --group platform/services
Shows enabled state, last-sync status, and any errors per mirror.
Commands
| Command | Description |
|---|---|
hydra create [name] |
Create the repo across hosts. Without name, runs the wizard. |
hydra configure |
Onboarding wizard — config + tokens. |
hydra status <name> |
Show the self-hosted project's mirror state. |
hydra config-path |
Print the resolved config-file path. |
Run hydra <cmd> --help for full flags.
Error handling
Hydra translates HTTP failures into actionable messages:
✗ GitLab.com authentication failed (401) while searching for group 'platform/services'
The GitLab.com token was rejected. Rotate it at
https://gitlab.com/-/user_settings/personal_access_tokens
and re-run `hydra configure`, or set HYDRA_GITLAB_TOKEN in your environment.
If a failure happens after some resources have been created, the partial state is reported so you can clean up before retrying:
⚠ Partial progress before the failure:
• self-hosted GitLab repo: https://gitlab.example.com/sandbox/demo
• gitlab.com group: https://gitlab.com/repo-syncer-managed-groups/sandbox-20260508131245
These resources exist now. Delete them manually before retrying,
or use a different repo name.
Config file
Lives at ~/.config/hydra/config.yaml by default. Override with --config <path> or $HYDRA_CONFIG. See config.yaml.example.
Security notes
- Tokens are never written to the YAML config.
- Tokens injected into mirror URLs (
https://oauth2:<token>@host/...) are stored on the self-hosted GitLab'sremote_mirrorstable. Anyone with project admin access can read them back via the GitLab API. Use scoped tokens. - Keep
.envgitignored. It already is in this repo.
Testing
Unit tests cover error translation, slug generation, wizard validators, and credential injection:
pip install -e '.[dev]'
pytest
CI runs the same suite plus a hydra --help smoke test on every push (.gitlab-ci.yml).
Project details
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 hydra_repo_syncer-0.0.1.tar.gz.
File metadata
- Download URL: hydra_repo_syncer-0.0.1.tar.gz
- Upload date:
- Size: 20.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4142c53688b519c18dd2966ee16150c4e3d381a53ec510096565700c265b4337
|
|
| MD5 |
ce4236b94404195242f4859bc9209b22
|
|
| BLAKE2b-256 |
2b06ab4bc71d1921c1ea652ee947dfe8f5d168a9ce80394f1dacadef6b7e4e33
|
File details
Details for the file hydra_repo_syncer-0.0.1-py3-none-any.whl.
File metadata
- Download URL: hydra_repo_syncer-0.0.1-py3-none-any.whl
- Upload date:
- Size: 18.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aff7840a8102d8c25224d1d6347654ba52946cbd319065653d2c38b07cd19933
|
|
| MD5 |
35bf514b16de2d7f42a085713724f6d4
|
|
| BLAKE2b-256 |
bcb004507f9d1fdfa9d59437a9a260e80a92de8e93f80df5a2fb143385b298bb
|