feat(script): add migration script for GitHub organization to Gitea

This commit is contained in:
2026-07-07 12:47:30 +08:00
parent 5b793b825e
commit fd96cdb3d6
+148
View File
@@ -0,0 +1,148 @@
#!/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 "$@"