Skip to content

roostorg/mirror

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 

mirror

GitHub Action to mirror a repo to any git forge

Usage

This action mirrors all branches and tags, pruning any that no longer exist in the source.

Warning

Mirrors should be treated as read-only; there is no two-way sync. Issues and pull requests are also not mirrored.

  1. Create a destination: an empty repository on your desired forge(s) (e.g. GitLab, Tangled, Codeberg)

  2. Prepare authentication: either a personal access token (e.g. for GitLab) or SSH key (e.g. for Tangled)

  3. Add this action to your repo: after checking out with fetch-depth: 0, call the action once per destination:

    - uses: actions/checkout@v6
      with:
        repository: your-org/your-repo
        fetch-depth: 0
    
    - name: Mirror to GitLab
      uses: roostorg/mirror@main
      with:
        destination: https://gitlab.com/your-org/your-repo.git
        token: ${{ secrets.GITLAB_TOKEN }}
    
    - name: Mirror to Tangled
      uses: roostorg/mirror@main
      with:
        destination: git@tangled.org:your-handle/your-repo
        ssh_private_key: ${{ secrets.TANGLED_SSH_PRIVATE_KEY }}
        ssh_known_hosts: ${{ secrets.TANGLED_KNOWN_HOSTS }}

See the examples below for specific forge configuration, or see how ROOST uses this.

Inputs

Input Required Default Description
destination yes Remote URL to push to (HTTPS or SSH). Do not embed credentials here.
token for HTTPS OAuth2 or personal access token. Injected into the URL; never echoed.
token_username no oauth2 Username in the HTTPS URL. oauth2 works for GitLab; use the account username for Gitea, Forgejo, and Codeberg.
ssh_private_key for SSH PEM private key (ED25519 or RSA). Written to a temp file with mode 0600 and deleted after the push.
ssh_known_hosts recommended Known-hosts entries for the destination host (see below). If omitted, falls back to ssh-keyscan with a TOFU warning.

Examples

GitLab: HTTPS with OAuth2 token (default token_username of oauth2 is correct):

- uses: roostorg/mirror@main
  with:
    destination: https://gitlab.com/your-org/your-repo.git
    token: ${{ secrets.GITLAB_TOKEN }}

Tangled: SSH with ED25519 key:

- uses: roostorg/mirror@main
  with:
    destination: git@tangled.org:your-handle/your-repo
    ssh_private_key: ${{ secrets.TANGLED_SSH_PRIVATE_KEY }}
    ssh_known_hosts: ${{ secrets.TANGLED_KNOWN_HOSTS }}

Codeberg: HTTPS with a Codeberg username and token:

- uses: roostorg/mirror@main
  with:
    destination: https://codeberg.org/your-username/your-repo.git
    token: ${{ secrets.CODEBERG_TOKEN }}
    token_username: your-username

Gitea / Forgejo: HTTPS with account username and token:

- uses: roostorg/mirror@main
  with:
    destination: https://your-forgejo-instance.example.com/your-username/your-repo.git
    token: ${{ secrets.FORGEJO_TOKEN }}
    token_username: your-username

Getting ssh_known_hosts

Run this once and store the output as a repository secret:

ssh-keyscan -t ed25519,rsa,ecdsa tangled.org

Providing this value means the action verifies the host's identity at push time. Without it, the action falls back to ssh-keyscan on each run, which does not verify host identity (trust-on-first-use).

Security notes

  • Tokens are injected into a shell variable and never echoed; GitHub Actions also masks the raw secret value in all log output.
  • SSH private keys are written to $RUNNER_TEMP (not ~/.ssh) with chmod 600 and deleted immediately after the push.
  • IdentitiesOnly=yes prevents the SSH agent from offering other keys during the push.
  • StrictHostKeyChecking=yes ensures the action hard-fails if the host key doesn't match, rather than silently connecting.
  • Only the git repository (branches, tags, and commits) is mirrored; pull requests and issues are not.
  • Do not mirror private repositories. The action does not check repo visibility.

How ROOST uses this

ROOST maintains a mirror workflow in this repo that runs hourly and on push to main. It checks out each repo in a matrix, then calls this action once for each remote.

To add a ROOST repo to our mirrors:

  1. Create an empty repo of the same name on each forge (e.g. gitlab.com/roostorg)
  2. Add the repo name to the repo matrix in .github/workflows/mirror.yml
  3. Wait up to an hour, or trigger the workflow manually from the Actions tab

About

GitHub Action to mirror a repo to any git forge

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Contributors