Skip to content

Instantly share code, notes, and snippets.

@baztian
Forked from xalvarez/get_repos.sh
Last active August 19, 2024 16:27
Show Gist options
  • Save baztian/d6a45e7408d1d4bdae67479a2bda73f4 to your computer and use it in GitHub Desktop.
Save baztian/d6a45e7408d1d4bdae67479a2bda73f4 to your computer and use it in GitHub Desktop.
Clone and fork a team's first 100 GitHub repos. Then, add remotes for all potential forks.
#!/usr/bin/env bash
# Clone and fork a team's first 100 GitHub repos. Then, add remotes for all potential forks.
#
# Requires:
# - git: https://git-scm.com/downloads
# - github-cli: https://github.com/cli/cli
# - jq: https://stedolan.github.io/jq/download/
#
# The first time you run this script or use gh for the first time in your system
# you need to authenticate yourself as follows:
# gh auth login
printHelp() {
echo "usage: $(basename "$0") [-f] [-m] <organization> <team> [<teamMemberToIgnore> ...]"
echo " -h Print this help."
echo " -f Create a fork for the repository."
echo " -m Add remote for all team member forks of the repositories."
echo " organization Name of a GitHub organization."
echo " team Name of a GitHub team."
echo " teamMembersToIgnore Whitespace separated list of team members to ignore."
exit 1
}
create_fork=false
add_member_fork_remotes=false
while getopts ":hfm" opt; do
case $opt in
h) printHelp ;;
f) create_fork=true ;;
m) add_member_fork_remotes=true ;;
\?) echo "Unknown option -$OPTARG"; exit 1;;
esac
done
# remove the parsed options from the positional params
shift $(( OPTIND - 1 ))
ORGANIZATION=$1
TEAM=$2
if [[ -z "$ORGANIZATION" || -z "$TEAM" ]]; then
printHelp
fi
RESPONSE="$(gh api graphql -f query='
query {
viewer {
login
}
organization(login: "'"$ORGANIZATION"'") {
team(slug: "'"$TEAM"'") {
members(first: 100, orderBy: {field: LOGIN, direction: ASC}) {
nodes {
login
}
}
repositories(first: 100, orderBy: {field: NAME, direction: ASC}) {
nodes {
sshUrl
isArchived
}
}
}
}
}
' | jq '.data | { currentUser: .viewer.login, team: .organization.team }')"
# Check if the RESPONSE contains valid data
if [[ "$(jq -r '.team' <<< "${RESPONSE}")" == "null" ]]; then
echo "Error: Invalid team name or organization. Please check your input and try again."
exit 1
fi
CURRENT_USER="$(jq -r '.currentUser' <<< "${RESPONSE}")"
TEAM_MEMBERS="$(jq -r --arg CURRENT_USER "$CURRENT_USER" '.team.members.nodes[].login | select(. != $CURRENT_USER)' <<< "${RESPONSE}")"
REPOSITORIES="$(jq -r '.team.repositories.nodes[] | select(.isArchived==false) | .sshUrl' <<< "${RESPONSE}")"
if [[ -n "$3" ]]; then
shift 2
for teamMemberToIgnore
do
TEAM_MEMBERS=("${TEAM_MEMBERS/$teamMemberToIgnore}")
done
fi
function addRemote {
teamMember=$1
repository=$2
forkRepository=${repository/$ORGANIZATION/$teamMember}
echo "Adding remote for fork ${forkRepository}"
git remote add "${teamMember,,}" "${forkRepository}"
}
for repository in ${REPOSITORIES}
do
repositoryName=${repository##*/}
repositoryName=${repositoryName%.git}
if $create_fork; then
if ! gh repo clone "${repository}" -- -o upstream; then
echo "Failed to clone ${repository}"
continue
fi
else
if ! gh repo clone "${repository}"; then
echo "Failed to clone ${repository}"
continue
fi
fi
cd "$repositoryName" || exit
if $create_fork; then
if ! gh repo fork --remote=true; then
echo "Failed to fork ${repository}"
cd ..
continue
fi
fi
if $add_member_fork_remotes; then
for teamMember in ${TEAM_MEMBERS}
do
addRemote "${teamMember}" "${repository}"
done
fi
cd ..
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment