239 lines
8.8 KiB
Bash
239 lines
8.8 KiB
Bash
#!/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 |