#!/bin/bash # My GiLab Backup (mygb) is a script for backup my GitLab's groups and projects # Copyright (C) 2021 Christophe Chaudier # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <https://www.gnu.org/licenses/>. # -- Constant readonly USAGE=' mygb.sh <command> [options] Command : init : create the configuration file export : export from GitLab import : import to GitLab Options : -h : print help -c path/to/conf : read one config file -p path/to/projet : export the projet -g path/to/group : export the group and is subgroups and projects -a : export all my group and subgroup ' readonly WAITING_TIME=5 # -- Vars config_file='.mygb_config' export_all=false # -- Functions _exit() { cr=${1} echo "End with code ${cr}" exit "${cr}" } _fail() { msg="${*}" echo "ERROR : ${msg}" _exit 1 } _succed() { msg="${*}" echo "Succed : ${msg:-no message}" _exit 0 } _help() { echo -e "${USAGE}" _fail "Bad usage" } _load_config() { echo "Loading ${config_file} ..." if [[ -e ${config_file} ]]; then # shellcheck disable=SC1090 source ${config_file} else echo "There is no config file!" echo "Use : mygb.sh init" _fail "File ${config_file} doesn't exist" fi } _create_config() { if [[ ! -e ${config_file} ]]; then echo "There is no file!" echo "What is the GitLab URL :" read -r gitlab_url echo "What is the GitLab API token :" read -rs gitlab_api_token echo "gitlab_url=\"${gitlab_url}\"" >${config_file} echo "gitlab_api_token=\"${gitlab_api_token}\"" >>${config_file} echo "The file ${config_file} was created with this content." echo "Please add the line below on your .gitignore" echo "${config_file}" else _fail "You already have a config file !" fi _succed "Config Created" } _api() { action=${1} path=${2} curl_args=${3} # shellcheck disable=2086 curl --request "${action}" -s \ --header "PRIVATE-TOKEN: ${gitlab_api_token}" \ ${curl_args} \ "${gitlab_url}api/v4/${path}" } _get_projects() { _api GET "projects?simple=true&owned=true" | jq '.[].path_with_namespace' } _get_project_info() { _api GET "projects/${project_url_encoded}" | jq } # ---[ Export Project ]--- _schedule_project_export() { _api POST "projects/${project_url_encoded}/export" | jq | grep --silent "202 Accepted" \ || _fail "Can't schedule export for project [${project}]" } _project_export_status() { _api GET "projects/${project_url_encoded}/export" | jq -r '.export_status' } _wait_export_finished() { while [[ "$(_project_export_status)" != "finished" ]]; do echo "Waiting end of export ..." sleep ${WAITING_TIME} done } _download_project_export() { export_filename="$(date +"%Y%m%d_%H%M")_project_${project/\//-}_export.tar.gz" _api GET "projects/${project_url_encoded}/export/download" "-o ${export_filename}" echo "The project was exported :" ls -l "${export_filename}" } _export_project() { if [[ -n ${project} ]]; then echo -e "\nExporting project : [${project}]..." _schedule_project_export _wait_export_finished _download_project_export fi } # ---[ Export Group ]--- _schedule_group_export() { _api POST "groups/${group_url_encoded}/export" | jq | grep --silent "202 Accepted" \ || _fail "Can't schedule export for group [${group}]" } _group_export_status() { _api GET "groups/${group_url_encoded}/export/download" | jq -r '.message' | grep 404 \ || echo finished } _wait_group_finished() { while [[ "$(_group_export_status)" != "finished" ]]; do echo "Waiting end of export ..." sleep ${WAITING_TIME} done } _download_group_export() { export_filename="$(date +"%Y%m%d_%H%M")_group_${group/\//-}_export.tar.gz" _api GET "group/${group_url_encoded}/export/download" "-o ${export_filename}" echo "The group was exported :" ls -l "${export_filename}" } _export_group() { if [[ -n ${group} ]]; then echo -e "\nExporting group : [${group}]..." _schedule_group_export _wait_group_finished _download_group_export fi } _export() { _load_config _export_project _export_group _succed "Export done" } _import() { _load_config _succed "Export done" } main() { echo "My GitLab Backup" action=${1} shift while getopts c:p:g:ah flag; do # shellcheck disable=SC2034 case "${flag}" in c) config_file=${OPTARG} ;; p) project=${OPTARG} ;; g) group=${OPTARG} ;; a) export_all=true ;; h | *) _help ;; esac done project_url_encoded="${project/\//%2F}" group_url_encoded="${group/\//%2F}" case "${action}" in init) _create_config ;; export) _export ;; import) _import ;; *) _help ;; esac _succed } main "$@"