Created
June 29, 2025 21:38
-
-
Save dominikwilkowski/dff479a7303f3ff3d4146ee9c920d479 to your computer and use it in GitHub Desktop.
Add lables to all GitHub repos in an org
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
#!/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