Skip to content

Instantly share code, notes, and snippets.

@xalvarez
Last active June 11, 2024 06:35
Show Gist options
  • Save xalvarez/eb57f02c401a264f2ca40ffebcb145e9 to your computer and use it in GitHub Desktop.
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.
#!/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
@baztian
Copy link

baztian commented Jan 6, 2022

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 :)

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