[READ-ONLY] Mirror of https://github.com/mrgnw/migrate-github-to-codeberg. Rust TUI and shell script for migrating GitHub repositories to Codeberg while preserving GitHub remotes.
0

Configure Feed

Select the types of activity you want to include in your feed.

migrate-github-to-codeberg / migrate_github_to_codeberg.sh
7.1 kB 207 lines
1#!/bin/bash 2# 3# GitHub to Codeberg Migration Script 4# ------------------------------------ 5# 6# Author: Rahul Martim Juliato 7# Email: rahul.juliato@gmail.com 8# License: GPL-3.0 9# Version: 0.1.2 10# 11# This script migrates GitHub repositories to Codeberg. 12# 13# User Configuration: 14# -------------------- 15# GitHub username and personal access token 16# GITHUB_USERNAME="YourGitHubUsername" 17# GITHUB_TOKEN="YourGitHubToken" 18# 19# Codeberg username and personal access token 20# CODEBERG_USERNAME="YourCodebergUsername" 21# CODEBERG_TOKEN="YourCodebergToken" 22# 23# Define the REPOSITORIES array with repository names you want to migrate 24# Leave it blank to migrate all repositories, or create a list of repositories 25# if you want to select specific ones. 26# REPOSITORIES=( 27# "repository1" 28# "repository2" 29# "repository3" 30# ) 31# 32# Custom prefix for description 33# DESCRIPTION_PREFIX="" 34# or something like: 35# DESCRIPTION_PREFIX="[MIRROR] " 36# 37# Usage: 38# ------ 39# 1. Configure the user settings at the beginning of the script. 40# 2. Run the script. 41# 3. Follow the on-screen instructions to proceed with the migration. 42# 43# Note: Make sure to have 'curl' and 'jq' installed. 44# 45# Press ENTER to continue, or C-c to abort. 46# 47# ----------------------------------------------------------- 48 49# USER CONFIGURATION 50#--------------------------------------------------------------------------- 51 52# GitHub username and personal access token 53GITHUB_USERNAME="YourGitHubUsername" 54GITHUB_TOKEN="YourGitHubToken" 55 56# Codeberg username and personal access token 57CODEBERG_USERNAME="YourCodebergUsername" 58CODEBERG_TOKEN="YourCodebergToken" 59 60# Define the REPOSITORIES array with repository names you want to migrate 61# Leave it blank so you migrate ALL repositories. Create a one per line list 62# if you want to select the repositories to migrate. 63 64REPOSITORIES=() 65# REPOSITORIES=( 66# "repository1" 67# "repository2" 68# "repository3" 69# ) 70 71# Define the OWNERS array with specific user names whose repositories you want to migrate 72# Leave it blank so you migrate ALL repositories. Create a one per line list 73# if you want to select the repositories to migrate. 74 75OWNERS=() 76# OWNERS=( 77# "owner1" 78# "owner2" 79# ) 80 81# Custom prefix for description 82DESCRIPTION_PREFIX="" 83# DESCRIPTION_PREFIX="[Secondary] - " 84# DESCRIPTION_PREFIX="Draft: " 85 86# UTILS FUNCTIONS 87#--------------------------------------------------------------------------- 88array_contains() { 89 local array="$1[@]" 90 local seeking=$2 91 local in=1 92 for element in "${!array}"; do 93 if [[ $element == "$seeking" ]]; then 94 in=0 95 break 96 fi 97 done 98 return $in 99} 100 101# PROCESSING 102#--------------------------------------------------------------------------- 103printf "\n ----------------------------------------------" 104printf "\n Welcome to Github to Codeberg Migration Script" 105printf "\n ----------------------------------------------\n" 106printf "\n User on Github : $GITHUB_USERNAME" 107printf "\n User on Codeberg : $CODEBERG_USERNAME" 108printf "\n Using description prefix: $DESCRIPTION_PREFIX" 109if [ ${#OWNERS[@]} -eq 0 ]; then 110 printf "\n Migrating repos owned by: all users" 111else 112 printf "\n Migrating repos owned by: %s" "${OWNERS[@]}" 113fi 114if [ ${#REPOSITORIES[@]} -eq 0 ]; then 115 printf "\n Migrating repo : all" 116else 117 printf "\n Migrating repos : %s" "${REPOSITORIES[@]}" 118fi 119printf "\n" 120printf "\n If you wish to change this, abort and change this script.\n\n" 121printf "\n\n Press ENTER to continue, C-c to abort.\n\n" 122read 123printf ">>> Working...\n" 124 125# NOTE: Github api paginates to max 100 repositories, this calculates how many 126# runs (pages) we're going to do to fetch all user data. 127GITHUB_PAGINATION=100 128github_total_repos=$(curl -s -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/user" | jq '.public_repos + .total_private_repos') 129github_needed_pages=$((($github_total_repos + $GITHUB_PAGINATION - 1) / $GITHUB_PAGINATION)) 130 131# Start Migration to Codeberg 132for ((github_page_counter = 1; github_page_counter <= github_needed_pages; github_page_counter++)); do 133 134 repos=$(curl -s -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/user/repos?per_page=${GITHUB_PAGINATION}&page=${github_page_counter}") 135 136 echo "$repos" | jq -c '.[]' | while read -r row; do 137 repo_name=$(echo "$row" | jq -r '.name') 138 139 # Skips current processing repo if 140 # A) it is not on the wanted list 141 # or B) and you're migrating 'all' 142 if ! array_contains REPOSITORIES "$repo_name" && [ ${#REPOSITORIES[@]} -ne 0 ]; then 143 continue 144 fi 145 146 repo_owner=$(echo "$row" | jq -r '.owner.login') 147 # Skips current processing repo if 148 # A) it is not owned by a targeted user 149 # B) no specific users are targeted 150 if ! array_contains OWNERS "$repo_owner" && [ ${#OWNERS[@]} -ne 0 ]; then 151 continue 152 fi 153 154 repo_clone_url=$(echo "$row" | jq -r '.clone_url') 155 repo_description="$DESCRIPTION_PREFIX$(echo "$row" | jq -r '.description')" 156 repo_is_private=$(echo "$row" | jq -r '.private') 157 158 printf ">>> Migrating: $repo_name ($([ "$repo_is_private" = "true" ] && echo "private" || echo "public"))...\n" 159 160 json_payload=$(jq -n \ 161 --arg auth_username "$GITHUB_USERNAME" \ 162 --arg auth_token "$GITHUB_TOKEN" \ 163 --arg clone_addr "$repo_clone_url" \ 164 --argjson private "$repo_is_private" \ 165 --arg repo_name "$repo_name" \ 166 --arg repo_owner "$CODEBERG_USERNAME" \ 167 --arg description "$repo_description" \ 168 '{ 169 auth_username: $auth_username, 170 auth_token: $auth_token, 171 clone_addr: $clone_addr, 172 private: $private, 173 repo_name: $repo_name, 174 repo_owner: $repo_owner, 175 service: "github", 176 description: $description 177 }') 178 179 response=$(curl -s -w "\n%{http_code}" -X POST -H "Content-Type: application/json" -H "Authorization: token $CODEBERG_TOKEN" -d "$json_payload" "https://codeberg.org/api/v1/repos/migrate") 180 181 response_body=$(echo "$response" | head -n -1) 182 http_status=$(echo "$response" | tail -n 1) 183 184 case $http_status in 185 201) 186 printf " Success!\n" 187 ;; 188 409) 189 printf " Error! Already exists on Codeberg.\n" 190 ;; 191 403) 192 printf "Error! Forbidden.\n" 193 ;; 194 *) 195 error_message=$(echo "$response_body" | jq -r '.message // empty' 2>/dev/null) 196 if [ -n "$error_message" ]; then 197 printf "Error: %s (HTTP %s)\n" "$error_message" "$http_status" 198 else 199 printf "Error: Unknown! %s\n" "$http_status" 200 fi 201 ;; 202 esac 203 204 done 205done 206 207echo ">>> Migration script completed!"