more changes

This commit is contained in:
Saravana Dhandapani 2025-06-23 21:59:14 -07:00
parent cfd6bc86c3
commit b0fbf6c391
9 changed files with 810 additions and 83 deletions

239
bytelyst-cli.sh Normal file
View File

@ -0,0 +1,239 @@
#!/bin/bash
# bytelyst-cli.sh: Unified CLI for Bytelyst GitHub DevOps Tools
#
# Usage examples:
# ./bytelyst-cli.sh list-public-repos --user <username>
# ./bytelyst-cli.sh list-private-repos --org <orgname>
# ./bytelyst-cli.sh check-collaborators --input input.json
# ./bytelyst-cli.sh export --type repos --output repos.json
#
# If no arguments are given, an interactive menu is shown.
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
BLUE=$(tput setaf 4)
RESET=$(tput sgr0)
REQUIRED_TOOLS=(jq curl)
# Check for required tools
for tool in "${REQUIRED_TOOLS[@]}"; do
if ! command -v $tool &>/dev/null; then
echo "${RED}❌ Error: Required tool '$tool' is not installed. Please install it and try again.${RESET}"
exit 1
fi
done
# Load .env if present
if [[ -f .env ]]; then
export $(grep -v '^#' .env | xargs)
fi
# Validate GITHUB_TOKEN
if [[ -z "$GITHUB_TOKEN" ]]; then
echo "${RED}❌ Error: GITHUB_TOKEN is not set.\nSet it in your environment (e.g., export GITHUB_TOKEN=... in ~/.zshrc, ~/.bashrc, or .env).${RESET}"
exit 1
fi
usage() {
echo "${BLUE}Bytelyst CLI - Unified GitHub DevOps Tool${RESET}"
echo ""
echo "Usage: $0 <command> [options]"
echo "Commands:"
echo " list-public-repos --user <username>"
echo " list-private-repos --org <orgname>"
echo " check-collaborators --input <input.json>"
echo " export --type <repos|users> --output <file.json>"
echo " remove-user-from-all-repos --user <username> [--input <file.json>]"
echo " help Show this help message"
echo ""
echo "If no command is given, an interactive menu will be shown."
}
list_public_repos() {
local user=""
while [[ $# -gt 0 ]]; do
case $1 in
--user)
user="$2"; shift 2;;
*) shift;;
esac
done
if [[ -z "$user" ]]; then
echo "${RED}❌ Please provide --user <username>.${RESET}"; exit 1
fi
echo "${BLUE}🔍 Fetching all public repositories for user: $user...${RESET}"
local response=$(curl -s -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/users/$user/repos?per_page=100&type=public")
local repos=$(echo "$response" | jq -r '.[].full_name')
if [[ -z "$repos" ]]; then
echo "${YELLOW}🚫 No public repositories found for user.${RESET}"
else
echo "$repos"
fi
}
list_private_repos() {
local org=""
while [[ $# -gt 0 ]]; do
case $1 in
--org)
org="$2"; shift 2;;
*) shift;;
esac
done
if [[ -z "$org" ]]; then
echo "${RED}❌ Please provide --org <orgname>.${RESET}"; exit 1
fi
echo "${BLUE}🔍 Fetching all private repositories for org: $org...${RESET}"
local response=$(curl -s -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/orgs/$org/repos?per_page=100&type=private")
local repos=$(echo "$response" | jq -r '.[].full_name')
if [[ -z "$repos" ]]; then
echo "${YELLOW}🚫 No private repositories found for org.${RESET}"
else
echo "$repos"
fi
}
check_collaborators() {
local input=""
while [[ $# -gt 0 ]]; do
case $1 in
--input)
input="$2"; shift 2;;
*) shift;;
esac
done
if [[ -z "$input" || ! -f "$input" ]]; then
echo "${RED}❌ Please provide --input <input.json> (file must exist).${RESET}"; exit 1
fi
local org=$(jq -r '.org' "$input")
local user=$(jq -r '.user' "$input")
local whitelist=($(jq -r '.whitelist[]' "$input"))
local repos=($(jq -r '.repos[]' "$input"))
if [[ -z "$org" || -z "$user" || ${#whitelist[@]} -eq 0 || ${#repos[@]} -eq 0 ]]; then
echo "${RED}❌ input.json must contain 'org', 'user', 'whitelist', and 'repos'.${RESET}"; exit 1
fi
for repo in "${repos[@]}"; do
echo "${BLUE}🔍 Checking repo: $repo${RESET}"
local collaborators=$(curl -s -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/$org/$repo/collaborators" | jq -r '.[].login')
local non_whitelisted=()
for collab in $collaborators; do
if [[ ! " ${whitelist[@]} " =~ " ${collab} " ]]; then
non_whitelisted+=("$collab")
fi
done
if [[ ${#non_whitelisted[@]} -gt 0 ]]; then
echo "${YELLOW}🚨 Repository: $repo${RESET}"
echo "${RED}❌ Non-Whitelisted Collaborators:${RESET}"
printf '%s\n' "${non_whitelisted[@]}"
for user in "${non_whitelisted[@]}"; do
read -p "Do you want to remove collaborator '$user' from '$repo'? (yes/no): " confirm
if [[ "$confirm" == "yes" ]]; then
response=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/$org/$repo/collaborators/$user")
if [[ "$response" -eq 204 ]]; then
echo "${GREEN}✅ Successfully removed $user from repository $repo.${RESET}"
else
echo "${YELLOW}⚠️ Failed to remove $user from repository $repo (HTTP Status: $response).${RESET}"
fi
else
echo "${YELLOW}🚫 Skipped removal of $user from $repo.${RESET}"
fi
done
echo "--------------------------------------------"
fi
done
}
export_json() {
local type=""; local output=""
while [[ $# -gt 0 ]]; do
case $1 in
--type)
type="$2"; shift 2;;
--output)
output="$2"; shift 2;;
*) shift;;
esac
done
if [[ -z "$type" || -z "$output" ]]; then
echo "${RED}❌ Please provide --type <repos|users> and --output <file.json>.${RESET}"; exit 1
fi
if [[ "$type" == "repos" ]]; then
jq . repos.json > "$output"
echo "${GREEN}✅ Exported repos to $output${RESET}"
elif [[ "$type" == "users" ]]; then
jq . users.json > "$output"
echo "${GREEN}✅ Exported users to $output${RESET}"
else
echo "${RED}❌ Unknown export type: $type${RESET}"
exit 1
fi
}
remove_user_from_all_repos() {
local user=""; local input="github_repos.json"
while [[ $# -gt 0 ]]; do
case $1 in
--user)
user="$2"; shift 2;;
--input)
input="$2"; shift 2;;
*) shift;;
esac
done
if [[ -z "$user" ]]; then
echo "${RED}❌ Please provide --user <username>.${RESET}"; exit 1
fi
if [[ ! -f "$input" ]]; then
echo "${RED}❌ Input file '$input' not found.${RESET}"; exit 1
fi
local org=$(jq -r '.org' "$input")
local repos=($(jq -r '.repos[]' "$input"))
if [[ -z "$org" || ${#repos[@]} -eq 0 ]]; then
echo "${RED}❌ Input file must contain 'org' and 'repos'.${RESET}"; exit 1
fi
for repo in "${repos[@]}"; do
echo "${BLUE}🔗 Removing user '$user' from repo: $repo${RESET}"
response=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/repos/$org/$repo/collaborators/$user")
if [[ "$response" -eq 204 ]]; then
echo "${GREEN}✅ Successfully removed $user from $repo.${RESET}"
elif [[ "$response" -eq 404 ]]; then
echo "${YELLOW}⚠️ $user is not a collaborator on $repo or repo not found.${RESET}"
else
echo "${RED}❌ Failed to remove $user from $repo (HTTP Status: $response).${RESET}"
fi
done
}
interactive_menu() {
echo "${BLUE}Bytelyst CLI Interactive Menu${RESET}"
select opt in "List Public Repos" "List Private Repos" "Check Collaborators" "Export JSON" "Remove User from All Repos" "Exit"; do
case $REPLY in
1) read -p "Enter GitHub username: " user; list_public_repos --user "$user";;
2) read -p "Enter GitHub org: " org; list_private_repos --org "$org";;
3) read -p "Enter path to input.json: " input; check_collaborators --input "$input";;
4) read -p "Export type (repos/users): " type; read -p "Output file: " output; export_json --type "$type" --output "$output";;
5) read -p "Enter GitHub username: " user; remove_user_from_all_repos --user "$user";;
6) exit 0;;
*) echo "Invalid option.";;
esac
done
}
# Main CLI dispatcher
if [[ $# -eq 0 ]]; then
interactive_menu
exit 0
fi
case $1 in
list-public-repos) shift; list_public_repos "$@";;
list-private-repos) shift; list_private_repos "$@";;
check-collaborators) shift; check_collaborators "$@";;
export) shift; export_json "$@";;
remove-user-from-all-repos) shift; remove_user_from_all_repos "$@";;
help|--help|-h) usage;;
*) echo "${RED}Unknown command: $1${RESET}"; usage; exit 1;;
esac

View File

@ -0,0 +1,61 @@
#!/bin/bash
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
BLUE=$(tput setaf 4)
RESET=$(tput sgr0)
usage() {
echo "${BLUE}Usage:${RESET} $0 [--org <org>] [--team <team_slug>]"
echo " --org <org> GitHub organization/account (or will prompt)"
echo " --team <team_slug> Team slug (or will prompt)"
echo ""
echo "GITHUB_TOKEN must be set in your environment."
}
# Parse arguments
ORG=""
TEAM_SLUG=""
while [[ $# -gt 0 ]]; do
case $1 in
--org) ORG="$2"; shift 2;;
--team) TEAM_SLUG="$2"; shift 2;;
-h|--help) usage; exit 0;;
*) echo "${RED}Unknown argument: $1${RESET}"; usage; exit 1;;
esac
done
if [[ -z "$GITHUB_TOKEN" ]]; then
echo "${RED}❌ GITHUB_TOKEN is not set in your environment.${RESET}"
exit 1
fi
# Prompt for org if not provided
if [[ -z "$ORG" ]]; then
read -p "Enter GitHub organization/account: " ORG
fi
# Prompt for team slug if not provided
if [[ -z "$TEAM_SLUG" ]]; then
read -p "Enter team slug: " TEAM_SLUG
fi
read -p "Are you sure you want to delete team '$TEAM_SLUG' from org '$ORG'? (yes/no): " CONFIRM
if [[ "$CONFIRM" != "yes" ]]; then
echo "${YELLOW}Aborted by user.${RESET}"
exit 0
fi
echo "${BLUE}Attempting to delete team '$TEAM_SLUG' from organization '$ORG'...${RESET}"
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE \
-H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/orgs/$ORG/teams/$TEAM_SLUG")
if [[ "$RESPONSE" -eq 204 ]]; then
echo "${GREEN}✅ Successfully deleted team '$TEAM_SLUG' from '$ORG'.${RESET}"
elif [[ "$RESPONSE" -eq 404 ]]; then
echo "${YELLOW}⚠️ Team '$TEAM_SLUG' not found in organization '$ORG'.${RESET}"
else
echo "${RED}❌ Failed to delete team '$TEAM_SLUG' from '$ORG' (HTTP Status: $RESPONSE).${RESET}"
fi

67
github_acc_input.json Normal file
View File

@ -0,0 +1,67 @@
{
"org": "saravanakumardb",
"user": "saravanakumardb",
"whitelist": [
"saravanakumardb",
"saravanange",
"abhinaisai2002",
"akshaj-us",
"saravanakumardb1",
"bytelyst-ai",
"umadev0931"
],
"repos": [
"activetracker",
"bytelyst-minutemaster-web",
"bytelyst-nomgap-web",
"voiceapp",
"SendToEpiCodeNinja",
"ByteListTask",
"devopsdash",
"taskify",
"bytelyst-backend-micro-services",
"bytelyst-chore-rewards-agent-intern-assignment-caren",
"bytelyst-commons-api",
"bytelyst-devops-dashboard-web",
"bytelyst-ds-intern-akhil-Rephrase-Assignment",
"bytelyst-gaslesspad-web",
"bytelyst-github-fastapi",
"bytelyst-micro-service",
"bytelyst-mockr-api",
"bytelyst-mockr-web-aditya",
"bytelyst-nomgap-api",
"bytelyst-note-intelligent-mcp-intern-navneet",
"bytelyst-notelett",
"bytelyst-notelett-api",
"bytelyst-notelett-bolt",
"bytelyst-notes-intern-parth-ios-switft",
"bytelyst-photobox-intern-assignment-sachin",
"bytelyst-quiz-flashcard-gen-web",
"bytelyst-reactnative-intern-parth",
"bytelyst-saas_analytics_yashoratnam_assignment",
"bytelyst-screen-select-web",
"bytelyst-tap-chat-web",
"bytelyst-taskmgmt-api-intern-assignment-Aditya",
"bytelyst-timer-intern-assignment-Akash",
"bytelyst-timer-intern-assignment-zia",
"bytelyst-trigglo-web"
],
"users": [
"Kmann22",
"ADPatel07",
"Aditya108786",
"sandho",
"CarenVictor",
"srinija06",
"malvika112",
"navneet1251",
"ParthSharma05",
"Sachin-kumar-jha",
"Yashoratnam-om",
"pal-boy",
"ziamd117",
"EpiCodeNinja",
"i-ayushh18",
"rougue1"
]
}

49
github_repos.json Normal file
View File

@ -0,0 +1,49 @@
{
"org": "saravanakumardb",
"user": "saravanakumardb",
"whitelist": [
"saravanakumardb",
"saravanange",
"abhinaisai2002",
"akshaj-us",
"saravanakumardb1",
"bytelyst-ai",
"umadev0931"
],
"repos": [
"activetracker",
"bytelyst-minutemaster-web",
"bytelyst-nomgap-web",
"voiceapp",
"SendToEpiCodeNinja",
"ByteListTask",
"devopsdash",
"taskify",
"bytelyst-backend-micro-services",
"bytelyst-chore-rewards-agent-intern-assignment-caren",
"bytelyst-commons-api",
"bytelyst-devops-dashboard-web",
"bytelyst-ds-intern-akhil-Rephrase-Assignment",
"bytelyst-gaslesspad-web",
"bytelyst-github-fastapi",
"bytelyst-micro-service",
"bytelyst-mockr-api",
"bytelyst-mockr-web-aditya",
"bytelyst-nomgap-api",
"bytelyst-note-intelligent-mcp-intern-navneet",
"bytelyst-notelett",
"bytelyst-notelett-api",
"bytelyst-notelett-bolt",
"bytelyst-notes-intern-parth-ios-switft",
"bytelyst-photobox-intern-assignment-sachin",
"bytelyst-quiz-flashcard-gen-web",
"bytelyst-reactnative-intern-parth",
"bytelyst-saas_analytics_yashoratnam_assignment",
"bytelyst-screen-select-web",
"bytelyst-tap-chat-web",
"bytelyst-taskmgmt-api-intern-assignment-Aditya",
"bytelyst-timer-intern-assignment-Akash",
"bytelyst-timer-intern-assignment-zia",
"bytelyst-trigglo-web"
]
}

View File

@ -2,85 +2,118 @@
# Color codes using tput for better terminal compatibility
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
BLUE=$(tput setaf 4)
RESET=$(tput sgr0)
# Usage instructions
usage() {
echo "${BLUE}Usage:${RESET} $0"
echo "Lists all public repositories owned by the authenticated user and their organizations."
echo "\nMake sure GITHUB_TOKEN is set in your environment (with 'public_repo' or 'repo' scope)."
echo "You can set GITHUB_TOKEN in your ~/.zshrc (for Zsh users), ~/.bashrc (for Bash users), or in a .env file in this directory."
echo "\nOptions:"
echo " -h, --help Show this help message and exit."
}
# Check for help flag
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
usage
exit 0
fi
# Check for required tools
for tool in jq curl; do
if ! command -v $tool &>/dev/null; then
echo "${RED}❌ Error: Required tool '$tool' is not installed. Please install it and try again.${RESET}"
exit 1
fi
done
# Load environment variables
GITHUB_TOKEN="${GITHUB_TOKEN:?❌ Error: GITHUB_TOKEN is not set in ~/.zshrc}"
if [[ -f .env ]]; then
export $(grep -v '^#' .env | xargs)
fi
if [[ -z "$GITHUB_TOKEN" ]]; then
echo "${RED}❌ Error: GITHUB_TOKEN is not set.\nSet it in your environment (e.g., export GITHUB_TOKEN=... in ~/.zshrc or ~/.bashrc) or in a .env file.${RESET}"
exit 1
fi
# Function to check for API errors
check_api_error() {
local response="$1"
# First check if it's an object with a message field (error response)
local error_message=$(echo "$response" | jq -r 'if type == "object" and has("message") then .message else empty end')
if [[ -n "$error_message" ]]; then
echo "❌ GitHub API Error: $error_message"
echo "${RED}❌ GitHub API Error: $error_message${RESET}"
return 1
fi
# Then check if it's an array (expected response type)
local is_array=$(echo "$response" | jq -r 'if type == "array" then "true" else "false" end')
if [[ "$is_array" != "true" ]]; then
echo "❌ GitHub API Error: Unexpected response format"
echo "${RED}❌ GitHub API Error: Unexpected response format${RESET}"
return 1
fi
return 0
}
echo "🔍 Fetching all public repositories owned by user..."
# Validate GitHub token before proceeding
VALIDATE=$(curl -s -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/user)
TOKEN_ERROR=$(echo "$VALIDATE" | jq -r '.message // empty')
if [[ -n "$TOKEN_ERROR" ]]; then
echo "${RED}❌ Invalid or unauthorized GITHUB_TOKEN: $TOKEN_ERROR${RESET}"
echo "${YELLOW}👉 Please check your token value and permissions at https://github.com/settings/tokens${RESET}"
echo "${BLUE}💡 Make sure to set your GITHUB_TOKEN in your ~/.zshrc (for Zsh), ~/.bashrc (for Bash), or a .env file in this directory.${RESET}"
exit 1
fi
# Fetch user public repos
echo "${BLUE}🔍 Fetching all public repositories owned by user...${RESET}"
RESPONSE=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/user/repos?per_page=100&type=public")
# Check for API errors
if check_api_error "$RESPONSE"; then
USER_PUBLIC_REPOS=$(echo "$RESPONSE" | jq -r '.[].full_name')
if [[ -z "$USER_PUBLIC_REPOS" ]]; then
echo "❌ No public repositories found for user."
echo "${YELLOW}🚫 No public repositories found for user.${RESET}"
else
printf "${RED}=> 📂 Public Repositories%s${RESET}\n" " (User-Owned)" > /dev/tty
printf "${GREEN}=> 📂 Public Repositories%s${RESET}\n" " (User-Owned)" > /dev/tty
echo "$USER_PUBLIC_REPOS"
echo "--------------------------------------------"
fi
else
echo "❌ Failed to fetch user repositories."
echo "${RED}❌ Failed to fetch user repositories.${RESET}"
fi
echo "🔍 Fetching organizations..."
# Fetch organizations
echo "${BLUE}🔍 Fetching organizations...${RESET}"
RESPONSE=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/user/orgs")
# Check for API errors
if check_api_error "$RESPONSE"; then
ORG_LIST=$(echo "$RESPONSE" | jq -r '.[].login')
if [[ -z "$ORG_LIST" ]]; then
echo "❌ No organizations found for user."
echo "${YELLOW}🚫 No organizations found for user.${RESET}"
exit 0
fi
else
echo "❌ Failed to fetch organizations."
echo "${RED}❌ Failed to fetch organizations.${RESET}"
exit 1
fi
echo "🔍 Fetching all public repositories under organizations..."
# Fetch org public repos
echo "${BLUE}🔍 Fetching all public repositories under organizations...${RESET}"
for ORG in $ORG_LIST; do
RESPONSE=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/orgs/$ORG/repos?per_page=100&type=public")
# Check for API errors
if check_api_error "$RESPONSE"; then
ORG_PUBLIC_REPOS=$(echo "$RESPONSE" | jq -r '.[].full_name')
if [[ -z "$ORG_PUBLIC_REPOS" ]]; then
echo "🚫 No public repositories found in organization: $ORG"
echo "${YELLOW}🚫 No public repositories found in organization: $ORG${RESET}"
else
printf "${RED}=> 📂 Public Repositories%s${RESET}\n" " ($ORG)" > /dev/tty
printf "${GREEN}=> 📂 Public Repositories%s${RESET}\n" " ($ORG)" > /dev/tty
echo "$ORG_PUBLIC_REPOS"
fi
else
echo "❌ Failed to fetch repositories for organization: $ORG"
echo "${RED}❌ Failed to fetch repositories for organization: $ORG${RESET}"
fi
echo "--------------------------------------------"
done

View File

@ -0,0 +1,50 @@
#!/bin/bash
# list_teams_and_members.sh: List all teams and their members for a GitHub organization
# Usage: ./list_teams_and_members.sh --org <orgname>
set -e
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
BLUE=$(tput setaf 4)
RESET=$(tput sgr0)
if ! command -v jq &>/dev/null; then
echo "${RED}❌ Error: 'jq' is required but not installed.${RESET}"
exit 1
fi
if [[ -z "$GITHUB_TOKEN" ]]; then
echo "${RED}❌ GITHUB_TOKEN is not set in your environment.${RESET}"
exit 1
fi
echo "${BLUE}Fetching organizations for the authenticated user...${RESET}"
ORGS=$(curl -s -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/user/orgs" | jq -r '.[].login')
if [[ -z "$ORGS" ]]; then
echo "${YELLOW}No organizations found for this user.${RESET}"
exit 0
fi
for ORG in $ORGS; do
echo -e "${GREEN}Organization: $ORG${RESET}"
TEAMS=$(curl -s -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/orgs/$ORG/teams" | jq -r '.[].slug')
if [[ -z "$TEAMS" ]]; then
echo " ${YELLOW}No teams found in $ORG${RESET}"
continue
fi
for TEAM in $TEAMS; do
echo " ${BLUE}Team: $TEAM${RESET}"
MEMBERS=$(curl -s -H "Authorization: token $GITHUB_TOKEN" "https://api.github.com/orgs/$ORG/teams/$TEAM/members" | jq -r '.[].login')
if [[ -z "$MEMBERS" ]]; then
echo " ${YELLOW}No members found in $TEAM${RESET}"
continue
fi
for MEMBER in $MEMBERS; do
echo " Member: $MEMBER"
done
done
done

175
list_repos_contributors.sh Normal file
View File

@ -0,0 +1,175 @@
#!/bin/bash
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
BLUE=$(tput setaf 4)
RESET=$(tput sgr0)
usage() {
echo "${BLUE}Usage:${RESET} $0"
echo " No input.json required."
echo " GITHUB_TOKEN must be set in your environment (e.g., in ~/.zshrc, ~/.bashrc, or .env)."
}
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
usage
exit 0
fi
# Check for required tools
for tool in jq curl; do
if ! command -v $tool &>/dev/null; then
echo "${RED}❌ Error: Required tool '$tool' is not installed. Please install it and try again.${RESET}"
exit 1
fi
done
# Load environment variables (token only)
if [[ -f .env ]]; then
export $(grep -v '^#' .env | xargs)
fi
if [[ -z "$GITHUB_TOKEN" ]]; then
echo "${RED}❌ Error: GITHUB_TOKEN is not set.\nSet it in your environment (e.g., export GITHUB_TOKEN=... in ~/.zshrc, ~/.bashrc, or .env).${RESET}"
exit 1
fi
# Get authenticated username
AUTH_USER=$(curl -s -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/user | jq -r '.login')
if [[ -z "$AUTH_USER" || "$AUTH_USER" == "null" ]]; then
echo "${RED}❌ Could not determine authenticated user. Check your GITHUB_TOKEN.${RESET}"
exit 1
fi
# Prompt for org (default to authenticated user)
read -p "Enter GitHub organization (leave blank for your user '$AUTH_USER'): " GITHUB_ORG
if [[ -z "$GITHUB_ORG" ]]; then
GITHUB_ORG="$AUTH_USER"
fi
# Prompt for whitelist (comma-separated, default to authenticated user)
read -p "Enter whitelist usernames (comma-separated, leave blank for '$AUTH_USER'): " WHITELIST_INPUT
if [[ -z "$WHITELIST_INPUT" ]]; then
WHITELIST=("$AUTH_USER")
else
IFS=',' read -ra WHITELIST <<< "$WHITELIST_INPUT"
for i in "${!WHITELIST[@]}"; do
WHITELIST[$i]="${WHITELIST[$i]// /}"
done
fi
# Prompt for interactive review
default_review="no"
read -p "Interactive review? (yes/no, default: $default_review): " INTERACTIVE_REVIEW
if [[ -z "$INTERACTIVE_REVIEW" ]]; then
INTERACTIVE_REVIEW="$default_review"
fi
INTERACTIVE_REVIEW=$(echo "$INTERACTIVE_REVIEW" | tr '[:upper:]' '[:lower:]')
if [[ "$INTERACTIVE_REVIEW" == "yes" ]]; then
INTERACTIVE_REVIEW="true"
else
INTERACTIVE_REVIEW="false"
fi
# Fetch all private repositories where the user is an owner or collaborator
REPO_DATA=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/user/repos?per_page=100&affiliation=owner,collaborator&visibility=private")
# Extract repository names
REPO_LIST=$(echo "$REPO_DATA" | jq -r '.[].name')
# Exit if no repositories found
if [[ -z "$REPO_LIST" ]]; then
echo "${YELLOW}❌ No private repositories found or token is missing the 'repo' scope.${RESET}"
exit 1
fi
echo "${BLUE}🔍 Checking repositories for non-whitelisted collaborators...${RESET}"
for REPO in $REPO_LIST; do
# Determine if repo is under organization or user
REPO_OWNER=$(echo "$REPO_DATA" | jq -r --arg REPO "$REPO" '.[] | select(.name==$REPO) | .owner.login')
# If repo belongs to the org, use $GITHUB_ORG instead of user
if [[ "$REPO_OWNER" == "$GITHUB_ORG" ]]; then
REPO_OWNER="$GITHUB_ORG"
fi
# Fetch all collaborators (includes users even if they haven't committed)
ALL_COLLABORATORS=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/repos/$REPO_OWNER/$REPO/collaborators" | jq -r '.[].login')
# Identify non-whitelisted collaborators
NON_WHITELISTED_COLLABS=()
for COLLAB in $ALL_COLLABORATORS; do
if [[ ! " ${WHITELIST[@]} " =~ " ${COLLAB} " ]]; then
NON_WHITELISTED_COLLABS+=("$COLLAB")
fi
done
# Only show repositories where non-whitelisted collaborators exist
if [[ ${#NON_WHITELISTED_COLLABS[@]} -gt 0 ]]; then
echo "${YELLOW}🚨 Repository: $REPO (Owner: $REPO_OWNER)${RESET}"
echo "${RED}❌ Non-Whitelisted Collaborators:${RESET}"
printf '%s\n' "${NON_WHITELISTED_COLLABS[@]}"
echo "--------------------------------------------"
if [[ "$INTERACTIVE_REVIEW" == "true" ]]; then
# Ask for confirmation and delete non-whitelisted collaborators
for USER in "${NON_WHITELISTED_COLLABS[@]}"; do
read -p "Do you want to remove collaborator '$USER' from '$REPO'? (yes/no): " CONFIRM
if [[ "$CONFIRM" == "yes" ]]; then
# Attempt to remove as a direct repository collaborator
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/repos/$REPO_OWNER/$REPO/collaborators/$USER")
if [[ "$RESPONSE" -eq 204 ]]; then
echo "${GREEN}✅ Successfully removed $USER from repository $REPO.${RESET}"
else
echo "${YELLOW}⚠️ Failed to remove $USER from repository $REPO (HTTP Status: $RESPONSE). Checking if they are an org member...${RESET}"
# Check if the user is an organization member
ORG_MEMBER_STATUS=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/orgs/$GITHUB_ORG/memberships/$USER")
if [[ "$ORG_MEMBER_STATUS" -eq 200 ]]; then
read -p "$USER is an organization member. Remove them from org '$GITHUB_ORG'? (yes/no): " CONFIRM_ORG
if [[ "$CONFIRM_ORG" == "yes" ]]; then
ORG_REMOVE_RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/orgs/$GITHUB_ORG/memberships/$USER")
if [[ "$ORG_REMOVE_RESPONSE" -eq 204 ]]; then
echo "${GREEN}✅ Successfully removed $USER from organization '$GITHUB_ORG'.${RESET}"
else
echo "${RED}❌ Failed to remove $USER from the organization (HTTP Status: $ORG_REMOVE_RESPONSE). Checking if they are in a team...${RESET}"
# If removal from org fails, check if the user is in a team
TEAMS=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/orgs/$GITHUB_ORG/teams" | jq -r '.[].slug')
for TEAM in $TEAMS; do
TEAM_REMOVE_RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE -H "Authorization: token $GITHUB_TOKEN" \
"https://api.github.com/orgs/$GITHUB_ORG/teams/$TEAM/memberships/$USER")
if [[ "$TEAM_REMOVE_RESPONSE" -eq 204 ]]; then
echo "${GREEN}✅ Successfully removed $USER from team '$TEAM'.${RESET}"
break
fi
done
fi
else
echo "${YELLOW}🚫 Skipped removal of $USER from organization.${RESET}"
fi
else
echo "${RED}$USER is neither a direct collaborator, nor an organization member, nor a team member. No action taken.${RESET}"
fi
fi
else
echo "${YELLOW}🚫 Skipped removal of $USER from $REPO.${RESET}"
fi
done
echo "--------------------------------------------"
fi
fi
done

View File

@ -1,12 +1,63 @@
#!/bin/bash
# Load environment variables
GITHUB_TOKEN="${GITHUB_TOKEN:?❌ Error: GITHUB_TOKEN is not set in ~/.zshrc}"
GITHUB_ORG="${GITHUB_ORG:?❌ Error: GITHUB_ORG is not set in ~/.zshrc}"
GITHUB_USER="${GITHUB_USER:?❌ Error: GITHUB_USER is not set in ~/.zshrc}"
RED=$(tput setaf 1)
GREEN=$(tput setaf 2)
YELLOW=$(tput setaf 3)
BLUE=$(tput setaf 4)
RESET=$(tput sgr0)
# Define the whitelist of allowed collaborators
WHITELIST=("saravanakumardb" "saravanange" "abhinaisai2002" "sandho" "akshaj-us" "saravanakumardb1" "bytelyst-ai" "umadev0931")
usage() {
echo "${BLUE}Usage:${RESET} $0 <input.json>"
echo " <input.json> Path to JSON file with parameters (org, user, whitelist)"
echo ""
echo "GITHUB_TOKEN must be set in your environment (e.g., in ~/.zshrc, ~/.bashrc, or .env)."
}
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
usage
exit 0
fi
if [[ $# -ne 1 ]]; then
usage
exit 1
fi
INPUT_JSON="$1"
if [[ ! -f "$INPUT_JSON" ]]; then
echo "${RED}❌ Error: Input file '$INPUT_JSON' not found.${RESET}"
exit 1
fi
# Check for required tools
for tool in jq curl; do
if ! command -v $tool &>/dev/null; then
echo "${RED}❌ Error: Required tool '$tool' is not installed. Please install it and try again.${RESET}"
exit 1
fi
done
# Load environment variables (token only)
if [[ -f .env ]]; then
export $(grep -v '^#' .env | xargs)
fi
if [[ -z "$GITHUB_TOKEN" ]]; then
echo "${RED}❌ Error: GITHUB_TOKEN is not set.\nSet it in your environment (e.g., export GITHUB_TOKEN=... in ~/.zshrc, ~/.bashrc, or .env).${RESET}"
exit 1
fi
# Parse JSON input
GITHUB_ORG=$(jq -r '.org // empty' "$INPUT_JSON")
GITHUB_USER=$(jq -r '.user // empty' "$INPUT_JSON")
WHITELIST=($(jq -r '.whitelist[]?' "$INPUT_JSON"))
INTERACTIVE_REVIEW=$(jq -r '.interactive_review // "false"' "$INPUT_JSON")
if [[ -z "$GITHUB_ORG" || -z "$GITHUB_USER" || ${#WHITELIST[@]} -eq 0 ]]; then
echo "${RED}❌ Error: 'org', 'user', and 'whitelist' must be specified in the JSON file.${RESET}"
exit 1
fi
# Fetch all private repositories where the user is an owner or collaborator
REPO_DATA=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
@ -17,11 +68,11 @@ REPO_LIST=$(echo "$REPO_DATA" | jq -r '.[].name')
# Exit if no repositories found
if [[ -z "$REPO_LIST" ]]; then
echo "❌ No private repositories found or token is missing the 'repo' scope."
echo "${YELLOW}❌ No private repositories found or token is missing the 'repo' scope.${RESET}"
exit 1
fi
echo "🔍 Checking repositories for non-whitelisted collaborators..."
echo "${BLUE}🔍 Checking repositories for non-whitelisted collaborators...${RESET}"
for REPO in $REPO_LIST; do
# Determine if repo is under organization or user
REPO_OWNER=$(echo "$REPO_DATA" | jq -r --arg REPO "$REPO" '.[] | select(.name==$REPO) | .owner.login')
@ -45,11 +96,12 @@ for REPO in $REPO_LIST; do
# Only show repositories where non-whitelisted collaborators exist
if [[ ${#NON_WHITELISTED_COLLABS[@]} -gt 0 ]]; then
echo "🚨 Repository: $REPO (Owner: $REPO_OWNER)"
echo "❌ Non-Whitelisted Collaborators:"
echo "${YELLOW}🚨 Repository: $REPO (Owner: $REPO_OWNER)${RESET}"
echo "${RED}❌ Non-Whitelisted Collaborators:${RESET}"
printf '%s\n' "${NON_WHITELISTED_COLLABS[@]}"
echo "--------------------------------------------"
if [[ "$INTERACTIVE_REVIEW" == "true" ]]; then
# Ask for confirmation and delete non-whitelisted collaborators
for USER in "${NON_WHITELISTED_COLLABS[@]}"; do
read -p "Do you want to remove collaborator '$USER' from '$REPO'? (yes/no): " CONFIRM
@ -59,9 +111,9 @@ for REPO in $REPO_LIST; do
"https://api.github.com/repos/$REPO_OWNER/$REPO/collaborators/$USER")
if [[ "$RESPONSE" -eq 204 ]]; then
echo "✅ Successfully removed $USER from repository $REPO."
echo "${GREEN}✅ Successfully removed $USER from repository $REPO.${RESET}"
else
echo "⚠️ Failed to remove $USER from repository $REPO (HTTP Status: $RESPONSE). Checking if they are an org member..."
echo "${YELLOW}⚠️ Failed to remove $USER from repository $REPO (HTTP Status: $RESPONSE). Checking if they are an org member...${RESET}"
# Check if the user is an organization member
ORG_MEMBER_STATUS=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token $GITHUB_TOKEN" \
@ -74,9 +126,9 @@ for REPO in $REPO_LIST; do
"https://api.github.com/orgs/$GITHUB_ORG/memberships/$USER")
if [[ "$ORG_REMOVE_RESPONSE" -eq 204 ]]; then
echo "✅ Successfully removed $USER from organization '$GITHUB_ORG'."
echo "${GREEN}✅ Successfully removed $USER from organization '$GITHUB_ORG'.${RESET}"
else
echo "❌ Failed to remove $USER from the organization (HTTP Status: $ORG_REMOVE_RESPONSE). Checking if they are in a team..."
echo "${RED}❌ Failed to remove $USER from the organization (HTTP Status: $ORG_REMOVE_RESPONSE). Checking if they are in a team...${RESET}"
# If removal from org fails, check if the user is in a team
TEAMS=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
@ -87,22 +139,24 @@ for REPO in $REPO_LIST; do
"https://api.github.com/orgs/$GITHUB_ORG/teams/$TEAM/memberships/$USER")
if [[ "$TEAM_REMOVE_RESPONSE" -eq 204 ]]; then
echo "✅ Successfully removed $USER from team '$TEAM'."
echo "${GREEN}✅ Successfully removed $USER from team '$TEAM'.${RESET}"
break
fi
done
fi
else
echo "🚫 Skipped removal of $USER from organization."
echo "${YELLOW}🚫 Skipped removal of $USER from organization.${RESET}"
fi
else
echo "$USER is neither a direct collaborator, nor an organization member, nor a team member. No action taken."
echo "${RED}$USER is neither a direct collaborator, nor an organization member, nor a team member. No action taken.${RESET}"
fi
fi
else
echo "🚫 Skipped removal of $USER from $REPO."
echo "${YELLOW}🚫 Skipped removal of $USER from $REPO.${RESET}"
fi
done
echo "--------------------------------------------"
fi
fi
done

View File

@ -4,7 +4,6 @@
"whitelist": [
"saravanakumardb",
"saravanange",
"abhinaisai2002",
"akshaj-us",
"saravanakumardb1",
"bytelyst-ai",