Skip to content

Instantly share code, notes, and snippets.

@xbalaji
Last active June 10, 2026 06:30
Show Gist options
  • Select an option

  • Save xbalaji/8c8e9cfe1b8f1af12bda082234a1193e to your computer and use it in GitHub Desktop.

Select an option

Save xbalaji/8c8e9cfe1b8f1af12bda082234a1193e to your computer and use it in GitHub Desktop.
create_github_repo.sh
#!/bin/bash
# ============================
# Script: create_github_repo.sh
# Purpose: Create a GitHub repo under an org by mirroring all branches
# from a template repo, clone via SSH, update README,
# push changes, assign team permissions, and list collaborators.
# ============================
# Defaults
ORG="xlabsinc"
VISIBILITY="private"
TEAM_TO_ADD="xbalaji-accounts" # default team slug
TEAM_PERMISSION="admin" # default permission for team
# ---------------------------
# Functions
# ---------------------------
usage() {
cat <<EOF
Usage: $0 -r <reponame> [-o <orgname>] [-v <visibility>] [-t <team_slug>] [-p <team_permission>] [-h]
Options:
-r, --repo Repository name (required)
-o, --org GitHub organization (optional, default: $ORG)
-v, --visibility private or public (optional, default: private)
-t, --team GitHub team slug to grant permission (optional, default: $TEAM_TO_ADD)
-p, --permission Team permission: pull, push, admin, maintain, triage (optional, default: $TEAM_PERMISSION)
-h, --help Display this help message
Examples:
$0 -r myrepo
$0 -r myrepo -v public
$0 -r myrepo -o myorg -t dev-team -p maintain
EOF
exit 1
}
check_command() {
command -v "$1" >/dev/null 2>&1
if [[ $? -eq 0 ]]; then
echo "Command '$1' is available."
else
echo "Error: '$1' is not installed. Please install it first."
exit 1
fi
}
# ---------------------------
# Parse arguments
# ---------------------------
ARGS=$(getopt -o r:o:v:t:p:h --long repo:,org:,visibility:,team:,permission:,help -n "$0" -- "$@")
if [[ $? -ne 0 ]]; then usage; fi
eval set -- "$ARGS"
while true; do
case "$1" in
-r|--repo) REPO="$2"; shift 2 ;;
-o|--org) ORG="$2"; shift 2 ;;
-v|--visibility) VISIBILITY="$2"; shift 2 ;;
-t|--team) TEAM_TO_ADD="$2"; shift 2 ;;
-p|--permission) TEAM_PERMISSION="$2"; shift 2 ;;
-h|--help) usage ;;
--) shift; break ;;
*) echo "Invalid option: $1"; usage ;;
esac
done
# Validate required arguments
if [[ -z "$REPO" ]]; then
echo "Error: Repository name is required."
usage
fi
if [[ "$VISIBILITY" != "private" && "$VISIBILITY" != "public" ]]; then
echo "Error: visibility must be 'private' or 'public'"
usage
fi
# ---------------------------
# Check prerequisites
# ---------------------------
check_command git
check_command gh
# ---------------------------
# Check GitHub CLI login
# ---------------------------
echo "Checking GitHub CLI login..."
if ! gh auth status >/dev/null 2>&1; then
TOKEN_FILE="$PWD/token.txt"
if [[ -f "$TOKEN_FILE" ]]; then
echo "Logging in using token file at $TOKEN_FILE..."
echo "Command: gh auth login --with-token <<<\$(head -1 $TOKEN_FILE)"
gh auth login --with-token <<<"$(head -1 "$TOKEN_FILE")"
else
echo "Error: Not logged in to GitHub CLI and token file not found at $TOKEN_FILE"
echo "Example: gh auth login --with-token <<<\$(head -1 $PWD/token.txt)"
exit 1
fi
else
CURRENT_USER=$(gh api user --jq '.login' 2>/dev/null)
if [[ -n "$CURRENT_USER" ]]; then
echo "Logged in as $CURRENT_USER"
else
echo "Error: Unable to determine logged in user."
exit 1
fi
fi
# ---------------------------
# Template repo
# ---------------------------
TEMPLATE_SSH="git@github-${ORG}:${ORG}/template.git"
echo "Template repository SSH URL: $TEMPLATE_SSH"
# ---------------------------
# Create the new repository
# ---------------------------
echo "Creating repository '$REPO' under org '$ORG' with visibility '$VISIBILITY'..."
echo "Command: gh repo create $ORG/$REPO --$VISIBILITY"
gh repo create "$ORG/$REPO" --"$VISIBILITY"
# ---------------------------
# New repository SSH URL
# ---------------------------
NEW_REPO_SSH="git@github-${ORG}:${ORG}/${REPO}.git"
# ---------------------------
# Mirror clone + push
# ---------------------------
TMP_DIR=$(mktemp -d)
echo "Mirroring all branches and tags from template..."
echo "Command: git clone --mirror $TEMPLATE_SSH $TMP_DIR"
git clone --mirror "$TEMPLATE_SSH" "$TMP_DIR"
cd "$TMP_DIR" || exit
echo "Command: git push --mirror $NEW_REPO_SSH"
git push --mirror "$NEW_REPO_SSH"
cd ..
rm -rf "$TMP_DIR"
# ---------------------------
# Clone the new repo for updates
# ---------------------------
echo "Cloning the new repository locally for updates: $NEW_REPO_SSH"
git clone "$NEW_REPO_SSH"
cd "$REPO" || exit
# ---------------------------
# Checkout default branch
# ---------------------------
git fetch origin
DEFAULT_BRANCH=$(git remote show origin | grep "HEAD branch" | awk '{print $NF}')
echo "Default branch: $DEFAULT_BRANCH"
git checkout "$DEFAULT_BRANCH" || git checkout -b main
# ---------------------------
# Update README.md
# ---------------------------
echo -e "\nThis README was updated automatically via create_github_repo.sh script." >> README.md
echo "Command: git add README.md && git commit -m 'Update README.md via script'"
git add README.md
git commit -m "Update README.md via script"
echo "Pushing changes to $DEFAULT_BRANCH..."
git push --set-upstream origin "$DEFAULT_BRANCH"
# ---------------------------
# Optional: Grant a team permission
# ---------------------------
if [[ -n "$TEAM_TO_ADD" ]]; then
echo "Adding team '$TEAM_TO_ADD' with permission '$TEAM_PERMISSION' to repo $ORG/$REPO"
echo "Command: gh api --method=PUT orgs/$ORG/teams/$TEAM_TO_ADD/repos/$ORG/$REPO -f permission=$TEAM_PERMISSION"
gh api --method=PUT "orgs/$ORG/teams/$TEAM_TO_ADD/repos/$ORG/$REPO" -f permission="$TEAM_PERMISSION"
fi
# ---------------------------
# List collaborators
# ---------------------------
echo "Listing collaborators:"
echo "Command: gh api repos/${ORG}/${REPO}/collaborators --jq '.[] | \"\(.login): \(.role_name)\"'"
gh api "repos/${ORG}/${REPO}/collaborators" --jq '.[] | "\(.login): \(.role_name)"'
echo "Repository '$REPO' successfully created under org '$ORG' with all branches mirrored!"
echo "Clone the repo using the command: git clone ${TEMPLATE_SSH}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment