#!/usr/bin/env bash set -euo pipefail set +x # ====== Fill these values before running ====== GITHUB_TOKEN="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" GITEA_TOKEN="1928666b31ab82a12a87a9050c764d0e534e2f21" GH_ORG="ai-camerist" GITEA_OWNER="banlv" GITEA_URL="https://gitea.banlv-ai.com" # Set to true if you want Gitea to keep pulling from GitHub after migration. MIRROR=false MIRROR_INTERVAL="8h" # Migrated repository options. MIGRATE_ISSUES=true MIGRATE_LABELS=true MIGRATE_MILESTONES=true MIGRATE_PULL_REQUESTS=true MIGRATE_RELEASES=true MIGRATE_WIKI=true MIGRATE_LFS=true require_cmd() { if ! command -v "$1" >/dev/null 2>&1; then echo "Missing required command: $1" >&2 exit 1 fi } api_get() { curl -fsSL \ -H "Accept: application/vnd.github+json" \ -H "Authorization: Bearer ${GITHUB_TOKEN}" \ "$1" } gitea_repo_status() { local repo_name="$1" curl -sS -o /dev/null -w "%{http_code}" \ -H "Authorization: token ${GITEA_TOKEN}" \ "${GITEA_URL}/api/v1/repos/${GITEA_OWNER}/${repo_name}" } migrate_repo() { local repo_json="$1" local repo_name clone_url description private status payload repo_name="$(echo "$repo_json" | jq -r '.name')" clone_url="$(echo "$repo_json" | jq -r '.clone_url')" description="$(echo "$repo_json" | jq -r '.description // ""')" private="$(echo "$repo_json" | jq -r '.private')" echo "==> Migrating ${GH_ORG}/${repo_name}" status="$(gitea_repo_status "$repo_name")" if [ "$status" = "200" ]; then echo " Skip existing repository: ${GITEA_OWNER}/${repo_name}" return 0 fi payload="$(jq -n \ --arg clone_addr "$clone_url" \ --arg repo_name "$repo_name" \ --arg repo_owner "$GITEA_OWNER" \ --arg description "$description" \ --arg auth_token "$GITHUB_TOKEN" \ --arg mirror_interval "$MIRROR_INTERVAL" \ --argjson private "$private" \ --argjson mirror "$MIRROR" \ --argjson issues "$MIGRATE_ISSUES" \ --argjson labels "$MIGRATE_LABELS" \ --argjson milestones "$MIGRATE_MILESTONES" \ --argjson pull_requests "$MIGRATE_PULL_REQUESTS" \ --argjson releases "$MIGRATE_RELEASES" \ --argjson wiki "$MIGRATE_WIKI" \ --argjson lfs "$MIGRATE_LFS" \ '{ service: "github", clone_addr: $clone_addr, repo_name: $repo_name, repo_owner: $repo_owner, description: $description, auth_token: $auth_token, private: $private, issues: $issues, labels: $labels, milestones: $milestones, pull_requests: $pull_requests, releases: $releases, wiki: $wiki, lfs: $lfs, mirror: $mirror, mirror_interval: $mirror_interval }')" curl -fsSL -X POST \ -H "Authorization: token ${GITEA_TOKEN}" \ -H "Content-Type: application/json" \ -d "$payload" \ "${GITEA_URL}/api/v1/repos/migrate" >/dev/null echo " Done: ${GITEA_OWNER}/${repo_name}" } main() { require_cmd curl require_cmd jq if [ "$GITHUB_TOKEN" = "ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ]; then echo "Please edit GITHUB_TOKEN in this script first." >&2 exit 1 fi if [ "$GITEA_TOKEN" = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ]; then echo "Please edit GITEA_TOKEN in this script first." >&2 exit 1 fi local page repos_json count total page=1 total=0 while true; do echo "Fetching GitHub repositories page ${page}..." repos_json="$(api_get "https://api.github.com/orgs/${GH_ORG}/repos?type=all&per_page=100&page=${page}&sort=full_name&direction=asc")" count="$(echo "$repos_json" | jq 'length')" if [ "$count" -eq 0 ]; then break fi while IFS= read -r repo; do migrate_repo "$repo" total=$((total + 1)) done < <(echo "$repos_json" | jq -c '.[]') page=$((page + 1)) done echo "All done. Processed repositories: ${total}" } main "$@"