more changes
This commit is contained in:
parent
cfd6bc86c3
commit
b0fbf6c391
239
bytelyst-cli.sh
Normal file
239
bytelyst-cli.sh
Normal 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
|
||||||
61
delete_team_interactive.sh
Normal file
61
delete_team_interactive.sh
Normal 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
67
github_acc_input.json
Normal 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
49
github_repos.json
Normal 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"
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -2,85 +2,118 @@
|
|||||||
|
|
||||||
# Color codes using tput for better terminal compatibility
|
# Color codes using tput for better terminal compatibility
|
||||||
RED=$(tput setaf 1)
|
RED=$(tput setaf 1)
|
||||||
|
GREEN=$(tput setaf 2)
|
||||||
|
YELLOW=$(tput setaf 3)
|
||||||
|
BLUE=$(tput setaf 4)
|
||||||
RESET=$(tput sgr0)
|
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
|
# 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
|
# Function to check for API errors
|
||||||
check_api_error() {
|
check_api_error() {
|
||||||
local response="$1"
|
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')
|
local error_message=$(echo "$response" | jq -r 'if type == "object" and has("message") then .message else empty end')
|
||||||
|
|
||||||
if [[ -n "$error_message" ]]; then
|
if [[ -n "$error_message" ]]; then
|
||||||
echo "❌ GitHub API Error: $error_message"
|
echo "${RED}❌ GitHub API Error: $error_message${RESET}"
|
||||||
return 1
|
return 1
|
||||||
fi
|
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')
|
local is_array=$(echo "$response" | jq -r 'if type == "array" then "true" else "false" end')
|
||||||
if [[ "$is_array" != "true" ]]; then
|
if [[ "$is_array" != "true" ]]; then
|
||||||
echo "❌ GitHub API Error: Unexpected response format"
|
echo "${RED}❌ GitHub API Error: Unexpected response format${RESET}"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
return 0
|
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" \
|
RESPONSE=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
|
||||||
"https://api.github.com/user/repos?per_page=100&type=public")
|
"https://api.github.com/user/repos?per_page=100&type=public")
|
||||||
|
|
||||||
# Check for API errors
|
|
||||||
if check_api_error "$RESPONSE"; then
|
if check_api_error "$RESPONSE"; then
|
||||||
USER_PUBLIC_REPOS=$(echo "$RESPONSE" | jq -r '.[].full_name')
|
USER_PUBLIC_REPOS=$(echo "$RESPONSE" | jq -r '.[].full_name')
|
||||||
|
|
||||||
if [[ -z "$USER_PUBLIC_REPOS" ]]; then
|
if [[ -z "$USER_PUBLIC_REPOS" ]]; then
|
||||||
echo "❌ No public repositories found for user."
|
echo "${YELLOW}🚫 No public repositories found for user.${RESET}"
|
||||||
else
|
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 "$USER_PUBLIC_REPOS"
|
||||||
echo "--------------------------------------------"
|
echo "--------------------------------------------"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "❌ Failed to fetch user repositories."
|
echo "${RED}❌ Failed to fetch user repositories.${RESET}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "🔍 Fetching organizations..."
|
# Fetch organizations
|
||||||
|
echo "${BLUE}🔍 Fetching organizations...${RESET}"
|
||||||
RESPONSE=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
|
RESPONSE=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
|
||||||
"https://api.github.com/user/orgs")
|
"https://api.github.com/user/orgs")
|
||||||
|
|
||||||
# Check for API errors
|
|
||||||
if check_api_error "$RESPONSE"; then
|
if check_api_error "$RESPONSE"; then
|
||||||
ORG_LIST=$(echo "$RESPONSE" | jq -r '.[].login')
|
ORG_LIST=$(echo "$RESPONSE" | jq -r '.[].login')
|
||||||
|
|
||||||
if [[ -z "$ORG_LIST" ]]; then
|
if [[ -z "$ORG_LIST" ]]; then
|
||||||
echo "❌ No organizations found for user."
|
echo "${YELLOW}🚫 No organizations found for user.${RESET}"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "❌ Failed to fetch organizations."
|
echo "${RED}❌ Failed to fetch organizations.${RESET}"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
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
|
for ORG in $ORG_LIST; do
|
||||||
RESPONSE=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
|
RESPONSE=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
|
||||||
"https://api.github.com/orgs/$ORG/repos?per_page=100&type=public")
|
"https://api.github.com/orgs/$ORG/repos?per_page=100&type=public")
|
||||||
|
|
||||||
# Check for API errors
|
|
||||||
if check_api_error "$RESPONSE"; then
|
if check_api_error "$RESPONSE"; then
|
||||||
ORG_PUBLIC_REPOS=$(echo "$RESPONSE" | jq -r '.[].full_name')
|
ORG_PUBLIC_REPOS=$(echo "$RESPONSE" | jq -r '.[].full_name')
|
||||||
|
|
||||||
if [[ -z "$ORG_PUBLIC_REPOS" ]]; then
|
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
|
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"
|
echo "$ORG_PUBLIC_REPOS"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "❌ Failed to fetch repositories for organization: $ORG"
|
echo "${RED}❌ Failed to fetch repositories for organization: $ORG${RESET}"
|
||||||
fi
|
fi
|
||||||
echo "--------------------------------------------"
|
echo "--------------------------------------------"
|
||||||
done
|
done
|
||||||
|
|||||||
50
list_orgs_teams_members.sh
Normal file
50
list_orgs_teams_members.sh
Normal 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
175
list_repos_contributors.sh
Normal 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
|
||||||
@ -1,12 +1,63 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Load environment variables
|
RED=$(tput setaf 1)
|
||||||
GITHUB_TOKEN="${GITHUB_TOKEN:?❌ Error: GITHUB_TOKEN is not set in ~/.zshrc}"
|
GREEN=$(tput setaf 2)
|
||||||
GITHUB_ORG="${GITHUB_ORG:?❌ Error: GITHUB_ORG is not set in ~/.zshrc}"
|
YELLOW=$(tput setaf 3)
|
||||||
GITHUB_USER="${GITHUB_USER:?❌ Error: GITHUB_USER is not set in ~/.zshrc}"
|
BLUE=$(tput setaf 4)
|
||||||
|
RESET=$(tput sgr0)
|
||||||
|
|
||||||
# Define the whitelist of allowed collaborators
|
usage() {
|
||||||
WHITELIST=("saravanakumardb" "saravanange" "abhinaisai2002" "sandho" "akshaj-us" "saravanakumardb1" "bytelyst-ai" "umadev0931")
|
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
|
# Fetch all private repositories where the user is an owner or collaborator
|
||||||
REPO_DATA=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
|
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
|
# Exit if no repositories found
|
||||||
if [[ -z "$REPO_LIST" ]]; then
|
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
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "🔍 Checking repositories for non-whitelisted collaborators..."
|
echo "${BLUE}🔍 Checking repositories for non-whitelisted collaborators...${RESET}"
|
||||||
for REPO in $REPO_LIST; do
|
for REPO in $REPO_LIST; do
|
||||||
# Determine if repo is under organization or user
|
# Determine if repo is under organization or user
|
||||||
REPO_OWNER=$(echo "$REPO_DATA" | jq -r --arg REPO "$REPO" '.[] | select(.name==$REPO) | .owner.login')
|
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
|
# Only show repositories where non-whitelisted collaborators exist
|
||||||
if [[ ${#NON_WHITELISTED_COLLABS[@]} -gt 0 ]]; then
|
if [[ ${#NON_WHITELISTED_COLLABS[@]} -gt 0 ]]; then
|
||||||
echo "🚨 Repository: $REPO (Owner: $REPO_OWNER)"
|
echo "${YELLOW}🚨 Repository: $REPO (Owner: $REPO_OWNER)${RESET}"
|
||||||
echo "❌ Non-Whitelisted Collaborators:"
|
echo "${RED}❌ Non-Whitelisted Collaborators:${RESET}"
|
||||||
printf '%s\n' "${NON_WHITELISTED_COLLABS[@]}"
|
printf '%s\n' "${NON_WHITELISTED_COLLABS[@]}"
|
||||||
echo "--------------------------------------------"
|
echo "--------------------------------------------"
|
||||||
|
|
||||||
|
if [[ "$INTERACTIVE_REVIEW" == "true" ]]; then
|
||||||
# Ask for confirmation and delete non-whitelisted collaborators
|
# Ask for confirmation and delete non-whitelisted collaborators
|
||||||
for USER in "${NON_WHITELISTED_COLLABS[@]}"; do
|
for USER in "${NON_WHITELISTED_COLLABS[@]}"; do
|
||||||
read -p "Do you want to remove collaborator '$USER' from '$REPO'? (yes/no): " CONFIRM
|
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")
|
"https://api.github.com/repos/$REPO_OWNER/$REPO/collaborators/$USER")
|
||||||
|
|
||||||
if [[ "$RESPONSE" -eq 204 ]]; then
|
if [[ "$RESPONSE" -eq 204 ]]; then
|
||||||
echo "✅ Successfully removed $USER from repository $REPO."
|
echo "${GREEN}✅ Successfully removed $USER from repository $REPO.${RESET}"
|
||||||
else
|
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
|
# Check if the user is an organization member
|
||||||
ORG_MEMBER_STATUS=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token $GITHUB_TOKEN" \
|
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")
|
"https://api.github.com/orgs/$GITHUB_ORG/memberships/$USER")
|
||||||
|
|
||||||
if [[ "$ORG_REMOVE_RESPONSE" -eq 204 ]]; then
|
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
|
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
|
# If removal from org fails, check if the user is in a team
|
||||||
TEAMS=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
|
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")
|
"https://api.github.com/orgs/$GITHUB_ORG/teams/$TEAM/memberships/$USER")
|
||||||
|
|
||||||
if [[ "$TEAM_REMOVE_RESPONSE" -eq 204 ]]; then
|
if [[ "$TEAM_REMOVE_RESPONSE" -eq 204 ]]; then
|
||||||
echo "✅ Successfully removed $USER from team '$TEAM'."
|
echo "${GREEN}✅ Successfully removed $USER from team '$TEAM'.${RESET}"
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "🚫 Skipped removal of $USER from organization."
|
echo "${YELLOW}🚫 Skipped removal of $USER from organization.${RESET}"
|
||||||
fi
|
fi
|
||||||
else
|
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
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo "🚫 Skipped removal of $USER from $REPO."
|
echo "${YELLOW}🚫 Skipped removal of $USER from $REPO.${RESET}"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
echo "--------------------------------------------"
|
echo "--------------------------------------------"
|
||||||
fi
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
done
|
done
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
"whitelist": [
|
"whitelist": [
|
||||||
"saravanakumardb",
|
"saravanakumardb",
|
||||||
"saravanange",
|
"saravanange",
|
||||||
"abhinaisai2002",
|
|
||||||
"akshaj-us",
|
"akshaj-us",
|
||||||
"saravanakumardb1",
|
"saravanakumardb1",
|
||||||
"bytelyst-ai",
|
"bytelyst-ai",
|
||||||
Loading…
Reference in New Issue
Block a user