A Python script to mirror all of your GitHub repositories to your Gitea server, with multiple options.
Repositories created are mirrors of the original repositories, and by default Gitea will automatically fetch them every 8 hours.
Using GitHub APIs and Gitea APIs -- especially the migrate
function.
There are many options to choose from:
- Mirror, or not mirror repos:
- you own
- you forked
- you starred
- you have access to as a collaborator
- you have access to as an organization member
- Whether to remove existing repos in Gitea
- Whether to create new organizations in Gitea if
{username}
in{username}/{repo_name}
doesn't match your GitHub username
Will also mirror your repository description and private status.
- Python3
Add the following content in your Gitea server's gitea/conf/app.ini
file:
[migrations]
ALLOWED_DOMAINS = github.com, *.github.com
All credentials are needed to be configured properly:
Key | Description |
---|---|
GITHUB | |
USERNAME | Your GitHub username |
PAT | Your GitHub personal access token, needed permissions: - repo (Full control of private repositories) If you only want to mirror public repositories, grant the following only: - repo:public_repo |
GITEA | |
USERNAME | Your Gitea username |
HOST | Your Gitea hostname, starts with http:// or https:// |
PAT | Your Gitea personal access token, needed permissions: - repository: Read and Write If you set CREATE_ORG in options.toml to true, you also need to grant:- organization: Read and Write |
You can customize these options for mirroring:
Key | Description |
---|---|
CONFIG | |
CREATE_ORG | Create a new organization in Gitea when the repository username is different from your GitHub username. |
REMOVE_INEXIST_REPO | Remove all repositories in Gitea owned by the user (including those in organizations) that do not exist in GitHub. |
REMOVE_EXISTING_REPO | Remove existing repositories in Gitea. This will only remove the repositories that have the same name as the repositories in GitHub. You may not want to enable this option, since Gitea will automatically fetch the mirror repositories every 8 hours. |
MIRROR_OWNED | Mirror the repositories you own. |
MIRROR_PRIVATE | Mirror private repositories you own. |
MIRROR_FORKED | Mirror the repositories you forked. |
MIRROR_STARRED | Mirror the repositories you starred. |
MIRROR_COLLABORATOR | Mirror the repositories that you have collaborator access. See: https://docs.github.com/zh/rest/repos/repos#list-repositories-for-the-authenticated-user |
MIRROR_ORGANIZATION | Mirror the repositories in organizations that you are a member. |
RULE | |
MODE | whitelist or blacklist to only mirror or skip repositories that match the regex. |
REGEX | Regex list. |
Configure credentials.toml
, and options.toml
.
Clone the repository:
git clone https://github.com/katorlys/github-mirror-gitea
cd github-mirror-gitea
Install the required packages:
pip install -r requirements.txt
Run the script:
python main.py
Make sure you've modified the <>
placeholders and the options before running the following command:
docker run --rm \
-e GITHUB_USERNAME=<GITHUB_USERNAME> \
-e GITHUB_PAT=<GITHUB_PAT> \
-e GITEA_USERNAME=<GITEA_USERNAME> \
-e GITEA_HOST=<GITEA_HOST> \
-e GITEA_PAT=<GITEA_PAT> \
-e CREATE_ORG=true \
-e REMOVE_EXISTING_REPO=false \
-e MIRROR_OWNED=true \
-e MIRROR_PRIVATE=true \
-e MIRROR_FORKED=true \
-e MIRROR_STARRED=false \
-e MIRROR_COLLABORATOR=false \
-e MIRROR_ORGANIZATION=false \
-e RULE_MODE="blacklist" \
-e RULE_REGEX="EpicGames/.*,NVIDIAGameWorks/.*" \
katorlys/github-mirror-gitea:latest
We've created a GitHub Action for this script. Here's an example workflow file:
name: Mirror GitHub to Gitea
on:
workflow_dispatch:
schedule:
- cron: '0 0 * * *'
jobs:
mirror:
runs-on: ubuntu-latest
steps:
- name: GitHub mirror Gitea
uses: katorlys/gitea-mirror-action@v1
with:
GITHUB_USERNAME: ${{ secrets.GH_USERNAME }}
GITHUB_PAT: ${{ secrets.GH_PAT }}
GITEA_HOST: ${{ secrets.GITEA_HOST }}
GITEA_USERNAME: ${{ secrets.GITEA_USERNAME }}
GITEA_PAT: ${{ secrets.GITEA_PAT }}
CREATE_ORG: true
REMOVE_INEXIST_REPO: false
REMOVE_EXISTING_REPO: false
MIRROR_OWNED: true
MIRROR_PRIVATE: true
MIRROR_FORKED: true
MIRROR_STARRED: false
MIRROR_COLLABORATOR: false
MIRROR_ORGANIZATION: false
MODE: 'blacklist'
REGEX: 'EpicGames/.*,NVIDIAGameWorks/.*'
If you prefer to run our Docker image in GitHub Actions, you can use the following workflow file:
name: Mirror Github to Gitea
on:
workflow_dispatch:
schedule:
- cron: 0 0 * * *
jobs:
mirror:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Run Docker container
run: |
docker run --rm \
-e GITHUB_USERNAME=${{ secrets.GH_USERNAME }} \
-e GITHUB_PAT=${{ secrets.GH_PAT }} \
-e GITEA_USERNAME=${{ secrets.GITEA_USERNAME }} \
-e GITEA_HOST=${{ secrets.GITEA_HOST }} \
-e GITEA_PAT=${{ secrets.GITEA_PAT }} \
-e CREATE_ORG=true \
-e REMOVE_EXISTING_REPO=false \
-e MIRROR_OWNED=true \
-e MIRROR_PRIVATE=true \
-e MIRROR_FORKED=true \
-e MIRROR_STARRED=false \
-e MIRROR_COLLABORATOR=false \
-e MIRROR_ORGANIZATION=false \
-e MODE="blacklist" \
-e RULE_REGEX="EpicGames/.*,NVIDIAGameWorks/.*" \
katorlys/github-mirror-gitea:latest
Error message | Solution |
---|---|
403 b'{"message":"token does not have at least one of required scope(s): |
Follow the message's instruction to grant the required permissions to your PAT. |
My repository doesn't exist on Gitea, but the script returns Skip (exists) |
Please don't transfer the mirrored repository to another user or organization on Gitea. |
b'{"message":"Migration failed: clone error: exit status 128 - fatal: unable to access \'https://github.com/username/repo.git/\': Could not resolve host: github.com\\n." |
Make sure your Gitea host can access GitHub. |
Copyright © 2024-present Katorly Lab