Skip to content

Instantly share code, notes, and snippets.

@dominikwilkowski
Created June 29, 2025 21:38
Show Gist options
  • Save dominikwilkowski/dff479a7303f3ff3d4146ee9c920d479 to your computer and use it in GitHub Desktop.
Save dominikwilkowski/dff479a7303f3ff3d4146ee9c920d479 to your computer and use it in GitHub Desktop.
Add lables to all GitHub repos in an org
#!/bin/bash
# ==============================================================================
# CONFIGURATION - Edit these values
# ==============================================================================
ORG_NAME="your-org-name"
LABEL_NAME="needs-review"
LABEL_COLOR="FF0000"
LABEL_DESCRIPTION="PRs that need review"
# ==============================================================================
# SCRIPT - No need to edit below this line
# ==============================================================================
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
COLORRESET='\033[0m'
# Default dry run to false
DRY_RUN=false
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
-n|--dry-run)
DRY_RUN=true
shift
;;
-h|--help)
echo "Usage: $0 [options]"
echo ""
echo "Options:"
echo " -n, --dry-run Show what would be done without making changes"
echo " -h, --help Show this help message"
echo ""
echo "Configuration is set in the script file itself."
exit 0
;;
*)
echo -e "${RED}Unknown option: $1${COLORRESET}"
echo "Use -h or --help for usage information"
exit 1
;;
esac
done
# Check if gh is installed
if ! command -v gh &> /dev/null; then
echo -e "${RED}Error: GitHub CLI (gh) is not installed${COLORRESET}"
echo ""
echo "Install it with Homebrew:"
echo " brew install gh"
echo ""
echo "Then authenticate:"
echo " gh auth login"
exit 1
fi
# Check if authenticated
if ! gh auth status &> /dev/null; then
echo -e "${RED}Error: Not authenticated with GitHub CLI${COLORRESET}"
echo ""
echo "Please run:"
echo " gh auth login"
exit 1
fi
# Validate configuration
if [ "$ORG_NAME" = "your-org-name" ] || [ -z "$ORG_NAME" ]; then
echo -e "${RED}Error: Please set ORG_NAME in the script configuration${COLORRESET}"
exit 1
fi
if [ -z "$LABEL_NAME" ]; then
echo -e "${RED}Error: Please set LABEL_NAME in the script configuration${COLORRESET}"
exit 1
fi
# Display configuration
echo -e "${YELLOW}=== Configuration ===${COLORRESET}"
echo "Organization: $ORG_NAME"
echo "Label Name: $LABEL_NAME"
echo "Label Color: #$LABEL_COLOR"
echo "Description: ${LABEL_DESCRIPTION:-'(none)'}"
echo ""
if [ "$DRY_RUN" = true ]; then
echo -e "${YELLOW}πŸ” DRY RUN MODE - No changes will be made${COLORRESET}"
echo ""
fi
# Confirm before proceeding (unless dry run)
if [ "$DRY_RUN" = false ]; then
echo -e "${YELLOW}This will add the label to ALL repositories in $ORG_NAME${COLORRESET}"
read -p "Continue? (y/N) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
echo "Cancelled."
exit 0
fi
echo ""
fi
# Get all repositories in the organization
echo -e "${YELLOW}Fetching repositories for $ORG_NAME...${COLORRESET}"
REPOS=$(gh repo list "$ORG_NAME" --limit 1000 --json name -q '.[].name' 2>&1)
if [ $? -ne 0 ]; then
echo -e "${RED}Error fetching repositories: $REPOS${COLORRESET}"
exit 1
fi
# Check if we got any repos
if [ -z "$REPOS" ]; then
echo -e "${RED}No repositories found for organization: $ORG_NAME${COLORRESET}"
exit 1
fi
# Count total repositories
TOTAL=$(echo "$REPOS" | wc -l | tr -d ' ')
echo -e "Found ${GREEN}$TOTAL${COLORRESET} repositories"
echo ""
# Counters
SUCCESS=0
EXISTS=0
FAILED=0
ARCHIVED=0
CURRENT=0
# Process each repository
for REPO in $REPOS; do
CURRENT=$((CURRENT + 1))
printf "[%3d/%3d] %-50s " "$CURRENT" "$TOTAL" "$REPO"
if [ "$DRY_RUN" = true ]; then
if gh label list --repo "$ORG_NAME/$REPO" --limit 1000 2>/dev/null | grep -q "^$LABEL_NAME"; then
echo -e "${YELLOW}β†’ Would skip (already exists)${COLORRESET}"
EXISTS=$((EXISTS + 1))
else
echo -e "${GREEN}βœ“ Would add label${COLORRESET}"
SUCCESS=$((SUCCESS + 1))
fi
else
if [ -n "$LABEL_DESCRIPTION" ]; then
OUTPUT=$(gh label create "$LABEL_NAME" \
--repo "$ORG_NAME/$REPO" \
--color "$LABEL_COLOR" \
--description "$LABEL_DESCRIPTION" \
2>&1)
else
OUTPUT=$(gh label create "$LABEL_NAME" \
--repo "$ORG_NAME/$REPO" \
--color "$LABEL_COLOR" \
2>&1)
fi
if [ $? -eq 0 ]; then
echo -e "${GREEN}βœ“ Added${NC}"
SUCCESS=$((SUCCESS + 1))
else
if echo "$OUTPUT" | grep -q "already exists"; then
echo -e "${YELLOW}β†’ Exists${NC}"
EXISTS=$((EXISTS + 1))
elif echo "$OUTPUT" | grep -q "Repository was archived so is read-only"; then
echo -e "${RED}βœ— Archived${NC}"
ARCHIVED=$((ARCHIVED + 1))
else
echo -e "${RED}βœ— Failed${NC}"
FAILED=$((FAILED + 1))
# echo " Error: $OUTPUT"
fi
fi
fi
done
# Summary
echo ""
echo -e "${YELLOW}=== Summary ===${COLORRESET}"
echo "Total repositories: $TOTAL"
if [ "$DRY_RUN" = true ]; then
echo -e "${GREEN}Would add label to: $SUCCESS repos${COLORRESET}"
echo -e "${YELLOW}Would skip (exists): $EXISTS repos${COLORRESET}"
if [ $ARCHIVED -gt 0 ]; then
echo -e "${RED}Would skip (archived): $ARCHIVED repos${NC}"
fi
else
echo -e "${GREEN}Successfully added: $SUCCESS${COLORRESET}"
echo -e "${YELLOW}Already existed: $EXISTS${COLORRESET}"
if [ $ARCHIVED -gt 0 ]; then
echo -e "${RED}Archived (read-only): $ARCHIVED${NC}"
fi
if [ $FAILED -gt 0 ]; then
echo -e "${RED}Failed: $FAILED${COLORRESET}"
fi
fi
echo ""
echo "Done!"
# Exit with error if any failed (in non-dry-run mode)
if [ "$DRY_RUN" = false ] && [ $FAILED -gt 0 ]; then
exit 1
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment