website-scripts/Git/Migrate/github-gitea-migration.sh

159 lines
5.3 KiB
Bash

#!/bin/bash
#clear the screen
clear
echo "This script will mirror a GitHub user's public repositories into gitea and assign them to a specific organiztion within Gitea."
echo "Before starting, you will need to create:"
echo "#1) A token with the appropriate rights (at least write:repository)"
echo "#2) An organization within Gitea to place all mirrored repositories into"
echo "If you enter a GitHub API token, you will be able to mirror non-public projects. This is optional!"
echo ""
echo "This application supports using a config file for user input variables"
#Config file:
CONFIG_FILE="migration_config.conf"
# Migration state file:
STATE_FILE="migration_state.txt"
#Check for config file. If none, ask user for input.
if [[ -f $CONFIG_FILE ]]; then
source $CONFIG_FILE
echo "Config file found! Continuing without asking for user input."
else
echo "Configuration file not found! Using manual input..."
### BEGIN User input ###
echo -n "Enter the GitHub username to migrate: "
read GITHUB_USERNAME
echo -n "Enter your GitHub Access Token (optional&hidden): "
read -s GITHUB_TOKEN
echo
echo -n "Enter your Gitea username: "
read GITEA_USER
echo -n "Enter your Gitea token (input will be hidden): "
read -s GITEA_TOKEN
echo
echo -n "Enter your Gitea URL (default: https://code.flatironnetworks.com): "
read GITEA_URL
GITEA_URL=${GITEA_URL:-https://code.flatironnetworks.com}
echo -n "Enter the Gitea organization to migrate into: "
read GITEA_ORG
### END User input ###
fi
# Check GitHub rate limit
check_rate_limit() {
local headers
local remaining
if [ -z "$GITHUB_TOKEN" ]; then
headers=$(curl -sI "https://api.github.com/users/$USERNAME/repos")
else
headers=$(curl -sI -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/users/$USERNAME/repos")
fi
remaining=$(echo "$headers" | grep X-RateLimit-Remaining: | awk '{print $2}')
# If the rate limit headers are not present, assume we can continue without delay.
if [ -z "$remaining" ]; then
return
fi
while [ "$remaining" -le 5 ]; do
echo "Rate limited by GitHub. Waiting for 10 minutes..."
sleep 600
if [ -z "$GITHUB_TOKEN" ]; then
remaining=$(curl -sI "https://api.github.com/users/$USERNAME/repos" | grep X-RateLimit-Remaining: | awk '{print $2}')
else
remaining=$(curl -sI -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/users/$USERNAME/repos" | grep X-RateLimit-Remaining: | awk '{print $2}')
fi
done
}
# Check if Gitea UID is valid
USER_ID=$(curl -s "$GITEA_URL/api/v1/users/$GITEA_USER" -H "authorization: token $GITEA_TOKEN" | jq '.id')
if [ -z "$USER_ID" ] || [ "$USER_ID" == "null" ]; then
echo "Failed to retrieve UID for $GITEA_USER. Please check your Gitea token and username."
exit 1
fi
# If the state file exists, read the last page processed
if [ -f "$STATE_FILE" ]; then
page=$(cat $STATE_FILE)
else
page=1
fi
# Fetch repositories from GitHub
fetch_github_repos() {
local page=$1
if [ -z "$GITHUB_TOKEN" ]; then
echo $(curl -s "https://api.github.com/users/$USERNAME/repos?per_page=100&page=$page")
else
echo $(curl -s "https://api.github.com/user/repos?visibility=all&per_page=100&page=$page" -H "Authorization: token $GITHUB_TOKEN")
fi
}
#Main script:
while : ; do
check_rate_limit
repos_json=$(fetch_github_repos $page)
repos=$(echo "$repos_json" | jq -r '.[].clone_url')
if [ -z "$GITHUB_TOKEN" ]; then
repos=$(curl -s "https://api.github.com/users/$USERNAME/repos?per_page=100&page=$page" | jq -r '.[].clone_url')
else
repos=$(curl -s "https://api.github.com/users/$USERNAME/repos?per_page=100&page=$page" -H "Authorization: token $GITHUB_TOKEN" | jq -r '.[].clone_url')
fi
if [ -z "$repos" ]; then
echo "Migration complete!"
rm $STATE_FILE
break
fi
for repo_url in $repos; do
repo_name=$(echo $repo_url | awk -F'/' '{print $NF}' | sed 's/.git$//')
# Check if repository is private and modify the clone URL accordingly
github_response=$(curl -s "https://api.github.com/repos/$USERNAME/$repo_name" -H "Authorization: token $GITHUB_TOKEN")
is_private=$(echo "$github_response" | jq '.private')
if [ "$is_private" == "true" ]; then
repo_url="https://$GITHUB_TOKEN@github.com/$USERNAME/$repo_name.git"
fi
echo "Transferring repository: $repo_name..."
response=$(curl -X POST "$GITEA_URL/api/v1/repos/migrate" \
-H "accept: application/json" \
-H "authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"clone_addr": "'$repo_url'",
"mirror": true,
"private": false,
"repo_name": "'$repo_name'",
"uid": '$USER_ID',
"repo_owner": "'$REPO_OWNER'"
}' -w "%{http_code}" -s -o /tmp/gitea_response.txt)
if [ "$response" == "409" ]; then
echo "Repository $repo_name already exists in $REPO_OWNER. Skipping."
elif [ "$response" != "201" ]; then
echo "Error migrating $repo_name. HTTP status: $response"
cat /tmp/gitea_response.txt
fi
done
echo $page > $STATE_FILE
page=$((page + 1))
done