30. Май 2024, 00:22

Автоматическая миграция репозиториев из gitlab на свой сервер git

  1. Все совпадения случайны
  2. Действия могут быть деструктивны и выполняются на свой страх и риск

Представим следующее: дружелюбный gitlab.com уведомил нас, что в ближайшее время наши с ним пути разойдутся и нам пора собирать вещички.

Проблема осложняется тем, что репозиториев в нашем аккаунте гитлаба вагон и маленькая тележка.

На наше счастье у нас уже есть свой сервер git с блекджеком и всем остальным на базе selfhosted gitea (но на самом деле реализация сервера не сильно принципиальна). Все, что нам нужно – перенести репозитории со всей историей, ветками и тегами.

Предварительные соглашения

  1. Работать будем по SSH, все ключи добавлены, соединения настроены.

  2. Не будем сильно заморачиваться над красотой наших скриптов, немножко хардкода нам не повредит.

  3. Специфично для gitea: на самом деле в gitea имеется встроенный механизм зеркалирования репозиториев, но будем считать, что мы принципиально не выпускаем в интернет наш сервер.

  4. Специфично для gitea: работать будем локально через API, токен сгенерирован заранее.

  5. Специфично для gitea: на нашем сервере gitea репозитории будут расположены в одной организации в виде плоской структуры, а гитлабовские группы будут преобразованы в префиксы имен репозиториев (не принципиально, но хотелось бы сохранить определенный порядок). Если организации нет и не планируется – рекомендую почитать API gitea и подобрать соответствующие методы.

Примерный план действий

  1. Предварительно создать на нашем сервере gitea пустые репозитории под новыми именами.
  2. Выкачать репозитории на локальную машину под новыми именами.
  3. Загрузить репозитории с локальной машины на сервер gitea.

Реализация

1. Создаем пустые репозитории на сервере gitea

  1. Этот пункт специфичен для gitea, для других реализаций придумывайте сами.
  2. Выполняется на сервере gitea в любом каталоге от любого пользователя. Будем подразумевать /home/user.

1.1. Создаем текстовый файл repos-list.txt, содержащий имена новых репозиториев

Наименования гитлабовских групп являются необязательными префиксами, а имена репозиториев соответствуют гитлабовским.

Формат файла repos-list.txt:

group-1_group-n_reponame_1
...
group-1_group-n_reponame_n

1.2. Создаем два скрипта create-repos.sh и remove-repos.sh

1.2.1. create-repos.sh – создает репозитории по списку из файла repos-list.txt
#!/bin/bash

REPOS_LIST="repos-list.txt"
API_URL="http://localhost:3000/api/v1"
HEADER1="content-type: application/json"
HEADER2="Authorization: token xxxxxxxxxxxxxx_gitea_token_xxxxxxxxxxxxxxxx"
TEAM="team_name"
TEAM_ID="111"

while IFS= read -r LINE; do
  echo "${LINE}"
  METHOD="POST"
  API_STRING="orgs/org_name/repos"
  DATA="{ \"name\": \"${LINE}\" }"
  curl -X "${METHOD}" -H "${HEADER1}" -H "${HEADER2}" -d "${DATA}" "${API_URL}/${API_STRING}"

  echo "Add ${LINE} into ${TEAM}"
  METHOD="PUT"
  API_STRING="teams/${TEAM_ID}/repos/org_name/${LINE}"
  curl -X "${METHOD}" -H "${HEADER1}" -H "${HEADER2}" -d "${DATA}" "${API_URL}/${API_STRING}"
  echo
done < ${REPOS_LIST}

Используя заранее сгенерированный токен (заменить на свой), для организации с именем org_name (заменить на свое) читает из файла repos-list.txt имена репозиториев, создает репозитории с указанными именами и добавляет их в команду team_name (заменить на свое).

TEAM_ID заменить на корректный. Узнать можно с помощью команды:

curl -X 'GET' -H 'accept: application/json' -H "Authorization: token xxxxxxxxxxxxxx_gitea_token_xxxxxxxxxxxxxxxx" 'localhost:3000/api/v1/orgs/org_name/teams/search?q=team_name'
1.2.2. remove-repos.sh – удаляет созданные репозитории, на случай если что-то пойдет не так
#!/bin/bash

REPOS_LIST="repos-list.txt"

API_URL="http://localhost:3000/api/v1"
HEADER1="content-type: application/json"
HEADER2="Authorization: token xxxxxxxxxxxxxx_gitea_token_xxxxxxxxxxxxxxxx"
METHOD="DELETE"

while IFS= read -r LINE; do
  echo "remove ${LINE}"
  API_STRING="repos/org_name/${LINE}"
  curl -X "${METHOD}" -H "${HEADER1}" -H "${HEADER2}" "${API_URL}/${API_STRING}"
done < ${REPOS_LIST}

1.3. Выполняем create-repos.sh для создания репозиториев по списку

$ ./create-repos.sh

2. Выкачиваем репозитории на локальную машину

Все последующие действия универсальны и выполняются на локальной машине от имени текущего пользователя.

2.1. Создаем файл repos.csv со списком репозиториев для миграции следующего формата:

git@gitlab.com:gitlab-account/group-1/group-n/reponame_1.git group-1_group-n_reponame_1
...
git@gitlab.com:gitlab-account/group-1/group-n/reponame_n.git group-1_group-n_reponame_n

Важно: Имена репозиториев должны совпадать с именами из repos-list.txt на сервере.

2.2. Создаем скрипт download_repos.sh для выкачивания репозиториев из gitlab на свою машину

#!/bin/bash

REPOS_LIST="repos.csv"
REPOS_DIR="repos_from_gitlab"

while IFS= read -r LINE; do
  read -a REPO <<< ${LINE}
  echo "Performing repo: ${REPO[1]}.."
  mkdir -p "${REPOS_DIR}/${REPO[1]}"
  cd "${REPOS_DIR}/${REPO[1]}"
  git clone "${REPO[0]}" --mirror ".git"
  git config --local --bool core.bare false
  git reset --hard
  git remote add gitea git@my.giteaserver.ru:org_name/${REPO[1]}.git
  cd ../..
  echo -e "done\n"
done < ${REPOS_LIST}

Скрипт по списку из repos.csv клонирует репозитории из gitlab в каталог repos_from_gitlab на локальной машине вместе со всей историей, ветками и тегами; добавляет в конфиг полученных репозиториев ссылку на наш сервер my.giteaserver.ru (заменить на свое) под именем gitea.

org_name (заменить на свое) должен совпадать с организацией из create-repos.sh.

2.3. Выполняем скрипт download_repos.sh и выкачиваем репозитории на локальную машину

$ ./download_repos.sh

3. Загружаем репозитории на свой сервер git

3.1. Создаем скрипт upload_repos.sh для загрузки репозиториев на свой сервер git

#!/bin/bash

REPOS_DIR="repos_from_gitlab"

for DIR in $(ls ${REPOS_DIR}); do
  echo "Push repo: ${DIR}.."
  cd "${REPOS_DIR}/${DIR}"
  git push gitea --mirror
  cd ../..
  echo -e "done\n"
done

Скрипт загружает все репозитории из каталога repos_from_gitlab на наш сервер git.

3.2. Выполняем скрипт upload_repos.sh и загружаем репозитории на свой сервер

$ ./upload_repos.sh

Готово.

PS

  1. Надеюсь, это кому-то поможет.
  2. Никогда не любил gitlab
comments powered by Disqus

© andrdi.com 2020