Ce projet visait à réaliser la migration des sources hébergées sur Subversion pour les anicennes applications d’APF France handicap vers un outil basé sur GIT comme Atlassian Bitbucket.
Conditions de migration
Afin de réaliser cette migration, un environnement spécifique a été mis en place en utilisant :
- Machine virtuelle contenant Docker
- Conteneur Docker contenant BitBucket
- Conteneur Docker contenant les outils de migration (dont le client Google SDK pour accéder à la machine virtuelle Subversion) dans le but de faire le lien entre la machine virtuelle Subversion et le Conteneur Bitbucket
Environnement de Développement
Conteneur BitBucket
Création de l’instance Bitbucket :
docker volume create --name bitbucketVolume docker run -v bitbucketVolume:/var/atlassian/application-data/bitbucket --name="bitbucket" -d -p 7990:7990 -p 7999:7999 atlassian/bitbucket
Accès à l’instance : http://localhost:7990/
Conteneur GitSVN
Création du conteneur
# Lancement du conteneur Ubuntu
docker run -it --rm ubuntu /bin/bash
Installation GitSVN
apt update
apt-get install -y git-svn
Installation Google Cloud SDK
apt update && apt-get install -y apt-transport-https ca-certificates gnupg curl sudo && echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] http://packages.cloud.google.com/apt cloud-sdk main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list && curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key --keyring /usr/share/keyrings/cloud.google.gpg add - && apt-get update -y && apt-get install google-cloud-cli -y
Paramétrage Google Cloud SDK
Création du fichier de login :
gcloud iam service-accounts keys create key.json --iam-account=nom-prenom@projetgcloud.iam.gserviceaccount.com cat key.json
Récupération du contenu de la clé :
{
"type": "service_account",
"project_id": "123456789",
"private_key_id": "660 KEY 66e",
"private_key": "-----BEGIN PRIVATE KEY----- KEY -----END PRIVATE KEY-----\n",
"client_email": "account-compute@developer.gserviceaccount.com",
"client_id": "123456789",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/123456789-compute%40developer.gserviceaccount.com",
"universe_domain": "googleapis.com"
}
gcloud auth activate-service-account --key-file=/root/key.json --project=projetgcloud
gcloud compute config-ssh --quiet
gcloud compute ssh userssh@server-subversion --zone=europe-zone --command="pwd"
Montage du dossier Subversion
mkdir /mnt/server-subversion
sshfs -o IdentityFile=~/.ssh/google_compute_engine \
userssh@server-subversion.europe-zone.projetgcloud:/home \
/mnt/server-subversion
Utilisation Git-SVN
Créer un répertoire de travail sur le poste local (avec Docker et Docker Compose installés)
Docker
Création d’une image Docker (Fichier Dockerfile) :
FROM ubuntu
ENV LC_ALL C.UTF-8
ARG GIT_USERNAME
ARG GIT_USEREMAIL
# Installation Google Cloud SDK Cli
RUN apt-get update -y && \
apt-get install -y apt-transport-https ca-certificates gnupg curl sudo && \
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] http://packages.cloud.google.com/apt cloud-sdk main" | tee -a /etc/apt/sources.list.d/google-cloud-sdk.list && \
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key --keyring /usr/share/keyrings/cloud.google.gpg add - && \
apt-get update -y && \
apt-get install google-cloud-cli -y
# Installation GitSVN
RUN apt-get update && apt-get install --yes --no-install-recommends \
git \
subversion \
git-svn \
sshfs \
&& rm -rf /var/lib/apt/lists/*
# Paramétrage GCloud SDK
COPY ./key.json /root/key.json
RUN gcloud auth activate-service-account --key-file=/root/key.json --project=projetgcloud
RUN gcloud compute config-ssh --quiet
RUN gcloud compute ssh userssh@server-subversion --zone=europe-zone --command="pwd"
# Paramétrage Git
RUN mkdir /git
RUN git config --global user.name "$GIT_USERNAME"
RUN git config --global user.email "$GIT_USEREMAIL"
COPY ./users-backup.txt /git/users.txt
ENV SVN_AUTHORS="/git/users.txt"
ENV GIT_PATH="/git/projects"
VOLUME /git
# Installation du script de migration
COPY ./migrate.sh /usr/bin/svn2git
# Variables d'environnements
ENV SVN_BRANCHES="branches"
ENV SVN_TAGS="tags"
ENV SVN_TRUNK="trunk"
ENV SVN_BASE="svn+ssh://userssh@server-subversion.europe-zone.projetgcloud:/home/developer/svn/subversion/"
ENV GIT_PROJECT_NAME=""
ENV GIT_URL=""
WORKDIR /git
Script
Création du script de migration (Fichier migration.sh) :
#!/bin/bash
#STYLE_COLOR
RED='\033[0;31m';
LIGHT_GREEN='\e[1;32m';
NC='\033[0m' # No Color
echo "Liste des projets :"
function select_project () {
projects=()
for line in $(gcloud compute ssh userssh@server-subversion --command "ls -a ~/svn/subversion/"); do
if [ "$line" != "." ] && [ "$line" != ".." ] ; then
num=$((num+1))
echo "[$num] $line"
# projects[$num]="$line"
# projects+=( "ROMAIN" )
# projects+=( "$line" "ROMAIN" )
projects+=( "$line" )
fi
done
printf "Sélectionner un projet : "
read GIT_PROJECT
GIT_PROJECT_NAME="${projects[($GIT_PROJECT-1)]}"
GIT_URL="$GIT_URL$GIT_PROJECT_NAME"
SVN_BASE="$SVN_BASE$GIT_PROJECT_NAME"
}
if [ "$GIT_PROJECT_NAME" == "" ]; then
select_project
fi
echo "PROJET : $GIT_PROJECT_NAME"
echo "URL GIT : $GIT_URL"
echo "URL SVN : $SVN_BASE"
# Branchs Configuration
SVN_BRANCHES_URL=$SVN_BASE/$SVN_BRANCHES
SVN_TAGS_URL=$SVN_BASE/$SVN_TAGS
SVN_TRUNK_URL=$SVN_BASE/$SVN_TRUNK
GIT_PATH=$GIT_PATH/$GIT_PROJECT_NAME
# START
echo -e "${LIGHT_GREEN} [LOG] Starting migration of ${NC}" $SVN_TRUNK
echo -e "${LIGHT_GREEN} [LOG] Using: ${NC}" $(git --version)
echo -e "${LIGHT_GREEN} [LOG] Using: ${NC}" $(svn --version | grep svn,)
# ETAPE 1 : Directories
echo
echo -e "${LIGHT_GREEN} [LOG] Step 01/08 Create Directories ${NC}" $GIT_PATH
echo -e "${LIGHT_GREEN} [LOG] Create $GIT_PATH directory ${NC}"
if [ -d "$GIT_PATH" ]; then rm -Rf $GIT_PATH; fi
mkdir -p $GIT_PATH
cd $GIT_PATH
# ETAPE 2 : Authors
echo
echo -e "${LIGHT_GREEN} [LOG] Step 02/08 Getting authors ${NC}"
if [ ! -s "${SVN_AUTHORS}" ]; then
echo -e "${LIGHT_GREEN} [LOG] Create $SVN_AUTHORS file from SVN Repository ${NC}"
svn log -q $SVN_BASE | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2"@"$EMAIL">"}' | sort -u >> $SVN_AUTHORS
else
echo -e "${LIGHT_GREEN} [LOG] Use $SVN_AUTHORS file ${NC}"
fi
# ETAPE 3 : GitSVN Clone
echo
echo -e "${LIGHT_GREEN} [RUN] Step 03/08"
echo 'git svn clone --authors-file='$SVN_AUTHORS' --trunk='$SVN_TRUNK' --branches='$SVN_BRANCHES' --tags='$SVN_TAGS $SVN_BASE $GIT_PATH
echo -e "${NC}"
git svn clone --authors-file=$SVN_AUTHORS --trunk=$SVN_TRUNK --branches=$SVN_BRANCHES --tags=$SVN_TAGS $SVN_BASE $GIT_PATH
echo
echo -e "${LIGHT_GREEN} [LOG] Step 04/08 Getting first revision ${NC}"
FIRST_REVISION=$( svn log -r 1:HEAD --limit 1 $SVN_BASE | awk -F '|' '/^r/ {sub("^ ", "", $1); sub(" $", "", $1); print $1}' )
echo
echo -e "${LIGHT_GREEN} [RUN] Step 05/08 ${NC}"
echo 'git svn fetch -'$FIRST_REVISION':HEAD'
git svn fetch -$FIRST_REVISION:HEAD
echo
echo -e "${LIGHT_GREEN} [RUN] Step 06/08 ${NC}"
echo 'git remote add origin '$GIT_URL
echo -e "${LIGHT_GREEN} [LOG] SKIP (Use local git) ${NC}"
git remote add origin $GIT_URL
echo
echo -e "${LIGHT_GREEN} [RUN] Step 07/08 ${NC}"
echo 'svn ls '$SVN_BRANCHES_URL
for BRANCH in $(svn ls $SVN_BRANCHES_URL); do
echo git branch ${SVN_BRANCH%/} remotes/svn/${SVN_BRANCH%/}
git branch ${SVN_BRANCH%/} remotes/svn/${SVN_BRANCH%/}
done
git for-each-ref --format="%(refname:short) %(objectname)" refs/remotes/origin/tags | grep -v "@" | cut -d / -f 3- |
while read ref
do
echo git tag -a $ref -m 'import tag from svn'
git tag -a $ref -m 'import tag from svn'
done
git for-each-ref --format="%(refname:short)" refs/remotes/origin/tags | cut -d / -f 1- |
while read ref
do
git branch -rd $ref
done
echo
echo -e "${LIGHT_GREEN} [RUN] Step 08/08 [RUN] git push ${NC}"
echo -e "${LIGHT_GREEN} [LOG] SKIP (Use local git) ${NC}"
git push origin --all --force
git push origin --tags
echo 'Sucessufull.'
Mapping des utilisateurs
Création d’un fichier de mapping des utilisateurs extrait des dépôts actuels Subversion (Fichier users-backup.txt) :
user_git1 = user_subversion1
user_git2 = user_subversion2
Authentification Google Cloud
Création d’un fichier de clé pour l’authentification (Fichier key.json) :
- Aller sur la console d’administration Google Cloud (en étant authentifié avec les accès au projet apf_developpement) : https://console.cloud.google.com/home/dashboard
- Aller sur le menu de gestion des comptes de service : https://console.cloud.google.com/iam-admin/serviceaccounts
- Sélectionner un compte ou en créer un pour l’accès
- Créer une nouvelle clé pour ce compte
- Créer la clé au format JSON
- La clé est téléchargée sur le navigateur
- Copier le fichier dans le répertoire de travail et la renommer key.json
Utilisation du script
Variables (exemple d’utilisation) :
- Projet Subversion à migrer :
apf_projet
1 - URL Git de destination pour la migration :
http://bitbucket:7990/scm/aw/
apf_projet
1.git - Volume local pour les projets GIT :
./git_new
- Nom de l’utilisateur GIT :
Romain BANAT
- Email de l’utilisateur GIT :
romain.banat@email.apf
Construction de l’image Docker
Lancer la commande :
docker image build -t svn2git:latest --build-arg="GIT_USERNAME=Romain BANAT" --build-arg="GIT_USEREMAIL=romain.banat@email.apf" .
Utilisation avec un fichier .env
Créer un fichier .env dans le répertoire de travail :
SVN_BASE="svn+ssh://userssh@server-subversion.europe-zone.projetgcloud/home/developer/svn/subversion/apf_projet1"
GIT_PROJECT_NAME="apf_projet1"
GIT_URL="http://bitbucket:7990/scm/aw/apf_projet1.git"
Lancer la commande :
docker run --rm -ti --env-file=./.env ` --mount type=bind,source="$(pwd)/users-backup.txt",target="/git/users.txt",readonly ` --volume="$(pwd)/git_new:/git/projects" ` svn2git svn2git
Utilisation avec sélection du projet (sans fichier .env)
Lancer la commande :
docker run --rm -ti ` --env GIT_URL="http://bitbucket:7990/scm/aw/" ` --mount type=bind,source="$(pwd)/users-backup.txt",target="/git/users.txt",readonly ` --volume="$(pwd)/git_new:/git/projects" ` svn2git svn2git
Instructions :
- Saisir le numéro correspondant au projet Subversion (Exemple pour apf_projet1: [1])
- Les variables deviennent :
- SVN_BASE= »svn+ssh://developer@instance-archive.europe-west1-b.apf-developpement/home/developer/svn/subversion/apf_projet1«
- GIT_PROJECT_NAME= »apf_projet1«
- GIT_URL= »http://bitbucket:7990/scm/aw/apf_projet1.git »
Environnement de test
Dans l’archive se trouve un fichier docker-compose.yml qui permet de lancer une instance Bitbucket pour pousser le dépôt GIT distant.
Pour le lancer il suffit de lancer la commande :
docker-compose up -d
Il faut ensuite se connecter à l’interface d’administration (création d’un accès à la version d’évaluation avec le compte Atlassian) : http://localhost:7990/
Il faut ensuite créer un projet puis un dépôt. Pour accéder à ce dépôt depuis le conteneur docker, il faut modifier la commande d’exécution en ajoutant le paramètre --link bitbucket:bitbucket
comme suit :
docker run --rm -ti --link bitbucket:bitbucket ` --env GIT_URL="http://bitbucket:7990/scm/aw/" ` --mount type=bind,source="$(pwd)/users-backup.txt",target="/git/users.txt",readonly ` --mount type=bind,source="$(pwd)/migrate.sh",target="/usr/bin/svn2git" ` --volume="$(pwd)/git_new:/git/projects" ` svn2git svn2git