No description
  • Python 98.7%
  • Shell 1.3%
Find a file
2026-07-16 15:10:46 +02:00
examples first working version 2026-07-16 15:06:58 +02:00
src/forgejo_repo_tools first working version 2026-07-16 15:06:58 +02:00
tests first working version 2026-07-16 15:06:58 +02:00
.gitignore first working version 2026-07-16 15:06:58 +02:00
install.sh Use uv tool install instead of pip for installation 2026-07-16 15:10:46 +02:00
pyproject.toml first working version 2026-07-16 15:06:58 +02:00
README.md Use uv tool install instead of pip for installation 2026-07-16 15:10:46 +02:00

forgejo-repo-tools

Safe command-line tools for making Forgejo the canonical Git server while optionally replicating public repositories to GitHub, Codeberg, GitLab.com and a configurable GitGud-compatible GitLab host.

The four command names are:

make-private-repo [name]
make-public-repo [name]
push-private
push-public

The preferred Forgejo SSH remote defaults to:

primegit:tarsow/REPOSITORY.git

That assumes this SSH config:

Host primegit
    HostName git.primeforge.net
    User git
    Port 2223
    IdentityFile ~/.ssh/id_ed25519
    IdentitiesOnly yes

Install

From this repository:

./install.sh

Equivalent manual install:

uv tool install --reinstall .
mkdir -p ~/.config/forgejo-repo-tools
chmod 700 ~/.config/forgejo-repo-tools
cp examples/config.toml ~/.config/forgejo-repo-tools/config.toml
cp examples/secrets.toml.example ~/.config/forgejo-repo-tools/secrets.toml
chmod 600 ~/.config/forgejo-repo-tools/secrets.toml

Ensure ~/.local/bin is on PATH for Bash and Zsh.

Configuration

Edit:

~/.config/forgejo-repo-tools/config.toml
~/.config/forgejo-repo-tools/secrets.toml

The config directory must not be group/world accessible. The secrets file must be exactly 0600.

Use examples/config.toml as the non-secret config. Store tokens only in secrets.toml or environment variables:

FRT_FORGEJO_TOKEN
FRT_GITHUB_TOKEN
FRT_CODEBERG_TOKEN
FRT_GITLAB_TOKEN
FRT_GITGUD_TOKEN

Other overrides are available as FRT_<PROVIDER>_<KEY>, for example FRT_GITGUD_URL or FRT_GITHUB_ENABLED.

Command Behavior

make-private-repo [name]:

  • Requires an existing Git repository with at least one commit.
  • Creates or reuses a private Forgejo repository.
  • Refuses if the Forgejo repository already exists as public.
  • Sets origin to the configured Forgejo remote.
  • Preserves any previous origin as github, codeberg, gitlab, gitgud, or origin-backup.
  • Pushes local branches with git push --all origin and tags with git push --tags origin.
  • Verifies the final Forgejo repository is private and has no public push mirrors.

make-public-repo [name]:

  • Performs the same local Git safety checks.
  • Creates or reuses a public Forgejo repository.
  • Creates empty public repositories on enabled providers.
  • Configures Forgejo push mirrors to enabled providers.
  • Registers Forgejo-generated mirror SSH public keys as write-enabled deploy keys when Forgejo exposes the key through its API.
  • Pushes local branches and tags to Forgejo.
  • Reports Forgejo and each provider separately. Replication is not globally transactional.

push-private:

  • Derives the repository name from origin.
  • Requires origin to exactly match the configured Forgejo remote template.
  • Verifies Forgejo says the repository is private.
  • Refuses if any public push mirror exists.
  • Pushes only to Forgejo.

push-public:

  • Requires exact Forgejo origin.
  • Verifies Forgejo says the repository is public.
  • Verifies all enabled public push mirrors exist.
  • Pushes local branches and tags to Forgejo.
  • Triggers mirror sync when the live Forgejo OpenAPI advertises a sync endpoint; otherwise it reports that periodic sync will handle it.

Safety Decisions

The tools never run git add ., never create commits, never push private repositories to public providers, and never place API tokens in Git remote URLs.

Local pushes use --all and --tags, not git push --mirror. Forgejo server-side push mirrors may force-push depending on Forgejos own mirror implementation; Forgejos documentation warns that push mirrors can overwrite changes on the destination, so external repositories should be treated as replicas.

The tool checks Forgejos live OpenAPI document at:

https://git.primeforge.net/swagger.v1.json

and refuses to guess push-mirror API endpoints that are not advertised.

Token Scopes

Do not paste tokens into chat. Create them in each provider UI and store them locally in ~/.config/forgejo-repo-tools/secrets.toml.

Forgejo:

  • Create at Settings -> Applications -> Generate New Token.
  • Required: read:repository, write:repository.
  • For organization owners, also grant organization access to the selected organization.
  • Forgejos docs describe token scopes and repository/organization access: https://forgejo.org/docs/latest/user/token-scope/

GitHub:

Codeberg:

  • Codeberg is Forgejo-compatible.
  • Required: read:repository, write:repository for the target owner.

GitLab.com:

GitGud:

  • Configure gitgud.url and gitgud.namespace.
  • The tool treats GitGud as GitLab API-compatible and verifies behavior through the configured API host.
  • Use the minimum GitGud token scope equivalent to GitLab api for repository creation and deploy-key administration.

Provider Steps That May Need Manual Work

Forgejo can generate a distinct SSH key for each push mirror. When the push-mirror API response exposes the public key, this tool registers it as a write-enabled deploy key on the destination repository.

If Forgejo 15 on your instance does not expose that public key through the API, the tool reports a provider failure instead of pretending the mirror is complete. In that case:

  1. Open the Forgejo repository.
  2. Go to Settings -> Repository -> Mirror Settings.
  3. Copy the push mirror public key.
  4. Add it as a write-enabled deploy key on the destination provider.
  5. Rerun make-public-repo; it will reuse existing repositories and mirrors.

Migration From the Old Sourced Bash Script

  1. Remove any .bashrc or .zshrc line that sources the old forgejo-repo-tools.sh.
  2. Install this package with ./install.sh.
  3. Put ~/.local/bin on your shell PATH.
  4. Move old shell variables into ~/.config/forgejo-repo-tools/config.toml and secrets.toml.
  5. Run make-private-repo --dry-run or make-public-repo --dry-run inside an existing repository before the first real run.

Existing Forgejo repositories and remotes are reused. If origin points somewhere else, the tool preserves it under a provider-specific backup name before setting Forgejo as canonical origin.

Development and Tests

Run:

PYTHONPATH=src python3 -m unittest discover -s tests
python3 -m compileall src tests

Provider APIs are mocked in tests. The tests create only temporary local Git repositories.

ShellCheck is not required because the implementation is Python. The installer is POSIX shell and intentionally small.

Architecture

  • cli.py maps the four executable names to operations and handles exit codes.
  • config.py loads TOML config, enforces permissions and applies environment overrides.
  • git.py owns local Git checks, origin preservation and local pushes.
  • forgejo.py owns Forgejo repository and push-mirror API behavior, including live OpenAPI endpoint verification.
  • providers.py owns GitHub, Codeberg and GitLab-compatible provider APIs.
  • operations.py composes the safety checks into the four command workflows.