Last active
June 11, 2024 06:35
-
-
Save xalvarez/eb57f02c401a264f2ca40ffebcb145e9 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 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 | |
APPLICATION_NAME=$0 | |
ORGANIZATION=$1 | |
TEAM=$2 | |
function printHelp { | |
echo "usage: $APPLICATION_NAME <organization> <team> [<teamMemberToIgnore> ...]" | |
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 | |
} | |
if [[ -z "$2" ]]; 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 }')" | |
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 | |
shift | |
for teamMemberToIgnore; do | |
TEAM_MEMBERS=("${TEAM_MEMBERS/$teamMemberToIgnore/}") | |
done | |
fi | |
function setForkRepoSettings { | |
repositoryName=$1 | |
echo "Updating settings for fork $CURRENT_USER/$repositoryName" | |
gh api --silent -X PATCH "/repos/$CURRENT_USER/$repositoryName" \ | |
-F allow_merge_commit=false \ | |
-F allow_squash_merge=true \ | |
-F allow_rebase_merge=true \ | |
-F delete_branch_on_merge=true \ | |
-F has_wiki=false \ | |
-F has_projects=false | |
gh api --silent -X PUT "/repos/$CURRENT_USER/$repositoryName/actions/permissions" \ | |
-F enabled=false | |
gh api --silent -X PUT "/orgs/$ORGANIZATION/teams/$TEAM/repos/$CURRENT_USER/$repositoryName" \ | |
-F permission=push | |
} | |
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} | |
gh repo clone "${repository}" -- -o upstream | |
cd "$repositoryName" || exit | |
gh repo fork --default-branch-only --remote | |
setForkRepoSettings "${repositoryName}" | |
for teamMember in ${TEAM_MEMBERS}; do | |
addRemote "${teamMember}" "${repository}" | |
done | |
gh repo set-default $ORGANIZATION/$repositoryName | |
cd .. | |
done |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Happy new year @xalvarez 🎆 Please notice my fork of this project which basically adds two options. By default in my fork fork creation and adding remotes for team members has been disabled but can be enabled via flags. Hope you like it. Feel free to merge it back :)