Skip to content

Instantly share code, notes, and snippets.

@tracphil
Forked from Potherca/README.md
Created June 27, 2023 11:28
Show Gist options
  • Save tracphil/94d3780793f7d8f92bb499d58702b395 to your computer and use it in GitHub Desktop.
Save tracphil/94d3780793f7d8f92bb499d58702b395 to your computer and use it in GitHub Desktop.
BASH script to clone all git repository in a Group on GitLab, or Organization on GitHub.

Introduction

Starting at a new employer always mean checking out various git repositories.

As the amount of repositories a company has grows, the time needed to clone all of those repositories also grows.

This script automates this task.

In order for this script to work, a personal access token is needed.

To avoid unexpected behaviour, use Group's ID, rather than its key/name. Informations about Groups can be found in the API at https://gitlab.example.com/api/v4/groups.

Usage

Call bash gitlab-clone-projects.sh <gitlab-domain> <group-name> <gitlab-token>

For full usage details gitlab-clone-projects --help is available:

Usage: git-clone-all-projects-in-gitlab-group.sh [-lh] <gitlab-domain> <group-name> <gitlab-token>

Where:
      - <gitlab-domain> is the domain where gitlab lives (for instance: 'gitlab.com')
      - <group-name> is the name of the group who's repos should be cloned
      - <gitlab-token> is the API access token to make REST API calls with

Options:
  -h|--help      Print this help dialogue and exit
  -L|--list      List the repositories that would be cloned and exit

The repositories will be cloned into a sub-directory under the path from Where
this script has been called. The repository will be cloned into ./${group-name}/${repo-name}

The git executable can be overridden by setting the GIT environmental variable
before calling this script:

       GIT=/usr/local/git-plus git-clone-all-projects-in-gitlab-group.sh <gitlab-domain> <group-name> <gitlab-token>
#!/usr/bin/env bash
# ==============================================================================
# Copyright (C) 2018 Potherca
#
# 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 <http://www.gnu.org/licenses/>.
# ==============================================================================
# There are a few standards this code tries to adhere to, these are listed below.
#
# - Code follows the BASH style-guide described at:
# http://guides.dealerdirect.io/code-styling/bash/
#
# - Variables are named using an adaption of Systems Hungarian explained at:
# http://blog.pother.ca/VariableNamingConvention
#
# ==============================================================================
set -o errexit # Exit script when a command exits with non-zero status.
set -o errtrace # Exit on error inside any functions or sub-shells.
set -o nounset # Exit script on use of an undefined variable.
set -o pipefail # Return exit status of the last command in the pipe that exited with a non-zero exit code
# ==============================================================================
# Git Clone All Projects in Gitlab Group
# ------------------------------------------------------------------------------
## Usage: $0 [-lh] <gitlab-domain> <group-name> <gitlab-token>
##
## Where:
## - <gitlab-domain> is the domain where gitlab lives (for instance: 'gitlab.com')
## - <group-name> is the name of the group who's repos should be cloned
## - <gitlab-token> is the API access token to make REST API calls with
##
## Options:
## -h|--help Print this help dialogue and exit
## -L|--list List the repositories that would be cloned and exit
##
## The repositories will be cloned into a sub-directory under the path from Where
## this script has been called. The repository will be cloned into ./${group-name}/${repo-name}
##
## The git executable can be overridden by setting the GIT environmental variable
## before calling this script:
##
## GIT=/usr/local/git-plus $0 <gitlab-domain> <group-name> <gitlab-token>
# ==============================================================================
: readonly "${GIT:=git}"
usage() {
local sScript sUsage
readonly sScript="$(basename "$0")"
readonly sUsage="$(grep '^##' <"$0" | cut -c4-)"
echo -e "${sUsage//\$0/${sScript}}"
}
gitlab-clone-projects() {
local -a aParameters aRepos
local g_sGitlabDomain g_sGitlabToken g_sGroupName
local bListOnly
local sDirectory sRepo
call-api() {
local -r sSubject="${1?One parameter required: <api-subject>}"
curl --silent --header "PRIVATE-TOKEN: ${g_sGitlabToken}" "https://${g_sGitlabDomain}/api/v4/${sSubject}?per_page=100"
}
fetch-projects() {
call-api "groups/${g_sGroupName}/projects" \
| grep -E -o '"ssh_url_to_repo":"[^"]+"' \
| cut -d '"' -f4
}
bListOnly=false
aParameters=()
for arg in "$@";do
case $arg in
-h|--help )
usage
exit
;;
-l|--list )
readonly bListOnly=true
shift
;;
* )
aParameters+=( "$1" )
shift
;;
esac
done
readonly aParameters
readonly g_sGitlabDomain="${aParameters[0]?Three parameters required: <gitlab-domain> <group-name> <gitlab-token>}"
readonly g_sGroupName="${aParameters[1]?Three parameters required: <gitlab-domain> <group-name> <gitlab-token>}"
readonly g_sGitlabToken="${aParameters[2]?Three parameters required: <gitlab-domain> <group-name> <gitlab-token>}"
readonly sRepos=$(fetch-projects)
for sRepo in ${sRepos[*]}; do
aRepos+=("${sRepo}")
done
echo ' =====> Found ' ${#aRepos[@]} ' repositories'
for sRepo in "${aRepos[@]}"; do
sDirectory="$(echo "${sRepo}" | grep -o -E ':(.*)\.')"
sDirectory="$(realpath --canonicalize-missing --relative-to=./ "${sDirectory:1:-1}")"
if [[ -d "${sDirectory}" ]];then
echo " -----> Skipping '${sRepo}', directory '${sDirectory}' already exists"
elif [[ "${bListOnly}" = 'true' ]];then
echo " -----> Cloning '${sRepo}' into directory '${sDirectory}'"
else
echo -e "\n -----> Cloning '${sRepo}' into directory '${sDirectory}'"
mkdir -p "${sDirectory}"
"${GIT}" --recursive clone "${sRepo}" "${sDirectory}" \
|| {
rm -rf "${sDirectory}"
echo -e "\n ! ERROR !\n Could not clone ${sRepo}"
}
fi
done
}
if [[ "${BASH_SOURCE[0]}" != "$0" ]]; then
export -f gitlab-clone-projects
else
gitlab-clone-projects "${@}"
exit $?
fi
#EOF
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment