Skip to content

Instantly share code, notes, and snippets.

@franklioxygen
Created March 21, 2025 03:02
Show Gist options
  • Save franklioxygen/d13238e76ddf5436338ac45bec123acc to your computer and use it in GitHub Desktop.
Save franklioxygen/d13238e76ddf5436338ac45bec123acc to your computer and use it in GitHub Desktop.
This script automatically mirrors your GitHub starred repositories to a Gitea instance. Features include:
#!/bin/bash
#########################################################################
# GitHub to Gitea Starred Repository Mirror
#
# This script automatically mirrors your GitHub starred repositories to
# a Gitea instance. Features include:
#
# - Fetches all repositories you've starred on GitHub
# - Checks if repositories already exist in your Gitea instance
# - Creates mirror repositories on Gitea for each starred GitHub repo
# - Sets up automatic mirror synchronization (via Gitea's mirroring feature)
# - Handles pagination for users with many starred repositories
# - Preserves repository metadata (descriptions, etc.)
# - Skip existing repositories to avoid duplicates
#
# Requirements:
# - GitHub Personal Access Token with appropriate permissions
# - Gitea Access Token with repo creation rights
# - curl, jq installed on your system
#########################################################################
# Configuration
GITHUB_TOKEN="GITHUB_PAT"
GITEA_TOKEN="GITEA_TOKEN"
GITEA_URL="GITEA_URL"
GITEA_USER="GITEA_USER"
GITHUB_USER="GITHUB_USER"
TEMP_DIR="/tmp/github_mirror"
# Create temp directory if it doesn't exist
mkdir -p "$TEMP_DIR"
# Fetch all existing repositories from Gitea
echo "Fetching existing Gitea repositories..."
existing_repos=$(curl -s -H "Authorization: token $GITEA_TOKEN" "$GITEA_URL/api/v1/user/repos" | grep -o '"name":"[^"]*' | cut -d'"' -f4)
# Get list of starred repositories from GitHub
echo "Fetching starred repositories from GitHub..."
page=1
starred_repos=()
while true; do
starred_page=$(curl -s -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/users/$GITHUB_USER/starred?per_page=100&page=$page")
# Check if we received empty response
if [ "$(echo "$starred_page" | jq '. | length')" = "0" ]; then
break
fi
# Extract repo details and add to array
while read -r repo; do
repo_name=$(echo "$repo" | jq -r '.name')
repo_url=$(echo "$repo" | jq -r '.clone_url')
repo_description=$(echo "$repo" | jq -r '.description // ""')
repo_owner=$(echo "$repo" | jq -r '.owner.login')
starred_repos+=("$repo_name|$repo_url|$repo_description|$repo_owner")
done < <(echo "$starred_page" | jq -c '.[]')
page=$((page + 1))
done
echo "Found ${#starred_repos[@]} starred repositories on GitHub"
# Process each starred repository
for repo_info in "${starred_repos[@]}"; do
IFS='|' read -r name url description owner <<< "$repo_info"
# Skip if repo already exists in Gitea
if echo "$existing_repos" | grep -q "^$name$"; then
echo "Skipping $name: already exists in Gitea"
continue
fi
echo "Processing $owner/$name..."
# Create mirror repo on Gitea using migration API
create_response=$(curl -s -X POST \
-H "Content-Type: application/json" \
-H "Authorization: token $GITEA_TOKEN" \
-d "{
\"clone_addr\": \"$url\",
\"repo_name\": \"$name\",
\"description\": \"Mirror of $owner/$name: $description\",
\"mirror\": true,
\"private\": false,
\"auth_username\": \"$GITHUB_USER\",
\"auth_token\": \"$GITHUB_TOKEN\"
}" \
"$GITEA_URL/api/v1/repos/migrate")
gitea_repo_url=$(echo "$create_response" | jq -r '.clone_url')
if [ -z "$gitea_repo_url" ] || [ "$gitea_repo_url" = "null" ]; then
echo "Error creating Gitea mirror for $name"
echo "$create_response"
continue
fi
echo "Successfully set up mirroring for $owner/$name to Gitea"
done
# No need for temporary cloning with this approach
echo "Mirroring process completed!"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment