Skip to content

Instantly share code, notes, and snippets.

@anton-yurchenko
Last active December 12, 2021 03:40
Show Gist options
  • Save anton-yurchenko/9efb2fb22a5865a8f0c2ec0ebd554c19 to your computer and use it in GitHub Desktop.
Save anton-yurchenko/9efb2fb22a5865a8f0c2ec0ebd554c19 to your computer and use it in GitHub Desktop.
Mirror repositories to GitHub
#!/usr/bin/env bash
CYAN='\033[0;36m'
RED='\033[0;31m'
NOCOLOR='\033[0m'
function log {
echo -e "${CYAN}INFO${NOCOLOR} $*"
}
function logerror {
echo -e "${RED}ERROR${NOCOLOR} $*"
}
function init {
if [[ -z "${GITHUB_TOKEN}" ]]; then
logerror "missing required environmental variable 'GITHUB_TOKEN'"
exit 1
fi
if [[ -z "${GITHUB_ORG}" ]]; then
logerror "missing required environmental variable 'GITHUB_ORG'"
exit 1
fi
rm -rf ./tmp_content
mkdir ./tmp_content
}
init
for repo in $(cat ./repositories.txt); do
# clean workdir
rm -rf ./tmp_content/*
# validate input
if [[ ! "${repo}" =~ ^(git@.*.git)|(https:\/\/.*.git)$ ]]; then
logerror "invalid repository name, skipping. (expected 'git@<host>:<org>/<repo>.git' or 'https://<host>/<org>/<repo>.git', got '${repo}')"
continue
fi
# create remote repository
repo_name=$(echo ${repo} | awk -F'/' '{print $NF}' | sed -e "s/.git$//")
remote_status=$(curl -IL -H "Authorization: bearer ${GITHUB_TOKEN}" -si https://api.github.com/repos/${GITHUB_ORG}/${repo_name} -o /dev/null -w '%{http_code}\n' -s)
if [[ "${remote_status}" == "200" ]]; then
logerror "repository with the requested name already exists, skipping (${repo})"
continue
elif [[ "${remote_status}" == "404" ]]; then
creation_status=$(curl -X POST -H "Authorization: bearer ${GITHUB_TOKEN}" --data "{\"name\":\"${repo_name}\",\"private\":true}" -si https://api.github.com/orgs/${GITHUB_ORG}/repos -o /dev/null -w '%{http_code}\n' -s)
if [[ "${creation_status}" == "201" ]]; then
log "repository '${repo_name}' created"
else
logerror "error creating a github repository '${repo_name}' (response code: ${creation_status})"
continue
fi
else
logerror "error contacting github api (response code: ${remote_status})"
exit 1
fi
# mirror repository
cd ./tmp_content
log "clonning repository '${repo_name}'..."
git clone --bare ${repo} --quiet || (logerror "something went wrong, skipping" & continue)
cd ${repo_name}.git
log "pushing repository '${repo_name}' to a new location..."
git push --mirror git@github.com:${GITHUB_ORG}/${repo_name}.git --quiet || (logerror "something went wrong, skipping" & continue)
cd ../..
rm -rf ./tmp_content/${repo_name}.git
done
rm -rf ./tmp_content
@anton-yurchenko
Copy link
Author

This script requires the following environmental variables:

  • GITHUB_ORG with an organization name on the destination
  • GITHUB_TOKEN with a developer token on a destination organization (create)

In addition to that, a repositories.txt file is expected to be present in a directory of the script and hold a valid git clone URL per line. For example:

git@github.com:<src-org>/<repo-a>.git
git@github.com:<src-org>/<repo-b>.git
https://github.com/<src-org>/<repo-c>.git

Please note that repositories will be created during execution. The reason for that is that guarantees that no repo will be overwritten.

Last but not least, the executor should be able to clone all the required repositories from the source.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment