-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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