From 6a6bfb5d12932cd0c058c7acf9076171efacdbd0 Mon Sep 17 00:00:00 2001 From: Saravana Dhandapani Date: Fri, 4 Jul 2025 12:49:05 -0700 Subject: [PATCH] feat: add interactive user removal tool with wildcard matching MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add remove_user_interactive.sh with rich visual logging and progress tracking - Support wildcard patterns for repository matching (*-go-api*, frontend-*, etc.) - Handle both root account and organization repositories - Implement flexible confirmation system (yes/no/all/skip/quit) - Add comprehensive documentation and usage examples - Update README.md with tool overview and usage instructions - Create CLAUDE.md for repository guidance - Add detailed documentation in docs/remove_user_interactive.md 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- CLAUDE.md | 85 +++++++ README.md | 135 ++++++++++- docs/remove_user_interactive.md | 204 ++++++++++++++++ remove_user_interactive.sh | 416 ++++++++++++++++++++++++++++++++ 4 files changed, 838 insertions(+), 2 deletions(-) create mode 100644 CLAUDE.md create mode 100644 docs/remove_user_interactive.md create mode 100755 remove_user_interactive.sh diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..6661efb --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,85 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Repository Overview + +This is a collection of Bash-based DevOps tools for GitHub repository management, specifically designed for ByteLyst AI organization. The tools focus on repository security, user management, and multi-repository operations. + +## Core Components + +### Main CLI Interface +- `bytelyst-cli.sh` - Unified command-line interface for all tools with both CLI and interactive modes +- Requires `jq` and `curl` dependencies +- Requires `GITHUB_TOKEN` environment variable for GitHub API access + +### Git Safety Tools (`git-work-safety-tools/`) +- `git_repos_status.sh` - Recursively scans directories for git repositories and shows status (commits, uncommitted files, unpushed changes) +- `git_repos_rebase_commit_push.sh` - Safely rebases, commits, and pushes changes across multiple repos +- `multi_repo_*.sh` - Additional multi-repository management utilities + +### User Management Tools +- `remove_user_interactive.sh` - Interactive user removal with wildcard repository matching + - Supports patterns like `*-go-api*`, `frontend-*` + - Handles both root account and organization repositories + - Rich visual logging with progress tracking + - Flexible confirmation system (yes/no/all/skip/quit) + +### Individual Tools +- `list_all_public_repos.sh` - Lists public repositories for a user +- `list_orgs_teams_members.sh` - Lists organization teams and members +- `list_prs_by_user.sh` - Lists pull requests by specific user +- `list_repos_contributors.sh` - Lists contributors for repositories +- `make_repos_private.sh` - Converts public repos to private +- `delete_team_interactive.sh` - Interactive team deletion tool + +## Development Commands + +### Setup +```bash +./setup.sh +``` +This installs pre-commit hooks and sets up the development environment. + +### Code Quality +```bash +pre-commit run --all-files +``` +Runs all pre-commit hooks including shellcheck for shell scripts. + +### Testing +```bash +./test.sh +``` +Basic test script (currently minimal). + +## Architecture Notes + +### Authentication +All tools use GitHub Personal Access Tokens via `GITHUB_TOKEN` environment variable. The token can be set in: +- Environment variables +- `.env` file (loaded automatically by `bytelyst-cli.sh`) + +### Configuration Files +- `github_repos.json` - Repository configuration for batch operations +- `github_acc_input.json` - Account input configuration +- `users_white_list.json` / `users_black_list.json` - User access control lists +- `repos.json` / `repos.txt` - Repository lists for operations + +### Error Handling +- Tools validate required dependencies (`jq`, `curl`) before execution +- GitHub API responses are checked for HTTP status codes +- Interactive confirmations for destructive operations + +### Multi-Repository Operations +The git safety tools are designed to work across multiple repositories by: +1. Recursively finding all `.git` directories +2. Operating on each repository independently +3. Providing summary reports of operations + +## Security Considerations + +- All tools require explicit confirmation for destructive operations +- GitHub tokens are validated before operations +- Pre-commit hooks include security checks (large file detection, trailing whitespace) +- Repository access is controlled via whitelist/blacklist mechanisms \ No newline at end of file diff --git a/README.md b/README.md index d3c5837..9046166 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,123 @@ -## Pre-commit Hooks +# ByteLyst DevOps Tools + +A comprehensive collection of Bash-based DevOps tools for GitHub repository management, specifically designed for ByteLyst AI organization. The tools focus on repository security, user management, and multi-repository operations. + +## 🚀 Quick Start + +1. **Setup the environment:** + ```bash + ./setup.sh + ``` + +2. **Set your GitHub token:** + ```bash + export GITHUB_TOKEN=your_github_token_here + ``` + +3. **Run the main CLI:** + ```bash + ./bytelyst-cli.sh + ``` + +## 📋 Available Tools + +### đŸŽ¯ Main CLI Interface +- **`bytelyst-cli.sh`** - Unified command-line interface for all tools + - Interactive menu mode + - Direct command execution + - Supports both user and organization operations + +### 🔐 User Management Tools +- **`remove_user_interactive.sh`** - Interactive user removal with wildcard repository matching + - Supports patterns like `*-go-api*`, `frontend-*` + - Handles both root account and organization repositories + - Rich visual logging with progress tracking + - Flexible confirmation system (yes/no/all/skip/quit) + +### đŸ›Ąī¸ Git Safety Tools (`git-work-safety-tools/`) +- **`git_repos_status.sh`** - Recursively scan directories for git repositories status +- **`git_repos_rebase_commit_push.sh`** - Safely rebase, commit, and push changes +- **`multi_repo_*.sh`** - Additional multi-repository management utilities + +### 📊 Repository Analysis Tools +- **`list_all_public_repos.sh`** - List all public repositories for a user +- **`list_orgs_teams_members.sh`** - List organization teams and members +- **`list_prs_by_user.sh`** - List pull requests by specific user +- **`list_repos_contributors.sh`** - List contributors for repositories +- **`list_repos_contributors_by_user.sh`** - List contributors filtered by user + +### 🔧 Repository Management Tools +- **`make_repos_private.sh`** - Convert public repositories to private +- **`delete_team_interactive.sh`** - Interactive team deletion tool +- **`cleanup.sh`** - General cleanup utilities + +## đŸ› ī¸ Prerequisites + +- **Required tools:** `curl`, `jq` +- **GitHub Personal Access Token** with permissions: + - `repo` (for repository access) + - `admin:org` (for organization management) + +## 📝 Usage Examples + +### Interactive User Removal +```bash +./remove_user_interactive.sh +# Follow the prompts to: +# 1. Enter GitHub token +# 2. Specify root user/organization +# 3. Enter user to remove +# 4. Define repository pattern (e.g., *-go-api*) +# 5. Confirm removals interactively +``` + +### CLI Commands +```bash +# List public repositories +./bytelyst-cli.sh list-public-repos --user username + +# List private repositories +./bytelyst-cli.sh list-private-repos --org orgname + +# Check collaborators +./bytelyst-cli.sh check-collaborators --input input.json + +# Remove user from all matching repositories +./bytelyst-cli.sh remove-user-from-all-repos --user username +``` + +### Git Repository Status +```bash +# Check status of all git repositories in current directory tree +./git-work-safety-tools/git_repos_status.sh + +# Safe multi-repository operations +./git-work-safety-tools/multi_repo_safe_push.sh +``` + +## 📁 Configuration Files + +- **`github_repos.json`** - Repository configuration for batch operations +- **`github_acc_input.json`** - Account input configuration +- **`users_white_list.json`** / **`users_black_list.json`** - User access control lists +- **`repos.json`** / **`repos.txt`** - Repository lists for operations + +## 🔒 Security Features + +- **Token validation** before operations +- **Interactive confirmations** for destructive operations +- **Access control** via whitelist/blacklist mechanisms +- **Pre-commit hooks** with security checks +- **Error handling** for API failures and network issues + +## 🎨 Visual Features + +- **Rich logging** with colors and emojis +- **Progress tracking** with percentage indicators +- **Summary reports** with success/failure statistics +- **Interactive menus** for ease of use + +## 📋 Pre-commit Hooks This project uses [pre-commit](https://pre-commit.com/) to ensure code quality and consistent formatting for all contributors. @@ -25,4 +144,16 @@ pre-commit run --all-files ### CI Enforcement -All commits and pull requests are checked with pre-commit hooks in CI. You must pass these checks to merge code. \ No newline at end of file +All commits and pull requests are checked with pre-commit hooks in CI. You must pass these checks to merge code. + +## 🤝 Contributing + +1. Ensure all scripts pass shellcheck validation +2. Follow existing code conventions and patterns +3. Add appropriate error handling and logging +4. Test scripts thoroughly before committing +5. Update documentation for new features + +## 📄 License + +This project is designed for internal use by ByteLyst AI organization. \ No newline at end of file diff --git a/docs/remove_user_interactive.md b/docs/remove_user_interactive.md new file mode 100644 index 0000000..0ba5adb --- /dev/null +++ b/docs/remove_user_interactive.md @@ -0,0 +1,204 @@ +# Interactive User Removal Tool + +## Overview + +`remove_user_interactive.sh` is a comprehensive command-line tool designed to remove users from GitHub repositories with advanced pattern matching and interactive confirmation features. The tool supports both individual user repositories and organization-wide operations. + +## Features + +### đŸŽ¯ Core Functionality +- **Interactive User Input**: Guides users through token, user, and pattern collection +- **Multi-Level Repository Discovery**: Handles both root account and organization repositories +- **Wildcard Pattern Matching**: Supports complex repository patterns +- **Batch Operations**: Process multiple repositories efficiently +- **Rich Visual Feedback**: Color-coded logging with progress indicators + +### 🔐 Security Features +- **Token Validation**: Verifies GitHub API access before operations +- **Interactive Confirmations**: Prevents accidental bulk operations +- **Permission Checks**: Validates repository access permissions +- **Error Handling**: Comprehensive error reporting and recovery + +### 🎨 User Experience +- **Progress Tracking**: Real-time progress indicators +- **Flexible Confirmation System**: Multiple response options +- **Summary Reports**: Detailed operation statistics +- **Color-Coded Output**: Enhanced readability with emojis + +## Usage + +### Basic Execution +```bash +./remove_user_interactive.sh +``` + +### Interactive Flow +1. **Dependency Check**: Validates required tools (`curl`, `jq`) +2. **Authentication**: Collects and validates GitHub token +3. **Root User Input**: Specifies the root account/organization +4. **Target User**: Defines the user to remove +5. **Pattern Matching**: Sets repository selection criteria +6. **Repository Discovery**: Finds all matching repositories +7. **Confirmation**: Reviews and confirms the operation +8. **Batch Processing**: Removes user from selected repositories +9. **Summary Report**: Displays operation results + +## Pattern Matching + +The tool supports sophisticated wildcard patterns for repository selection: + +### Pattern Examples +- `*-go-api*` - Matches any repository containing "-go-api" +- `frontend-*` - Matches repositories starting with "frontend-" +- `*-service` - Matches repositories ending with "-service" +- `web-*-app` - Matches repositories with "web-" prefix and "-app" suffix +- `exact-repo-name` - Matches specific repository name + +### Pattern Behavior +- Patterns are case-sensitive +- Wildcards (`*`) match any sequence of characters +- Patterns apply to repository names, not full paths +- Multiple patterns can be combined using shell globbing + +## Interactive Confirmation System + +During the removal process, users have multiple response options: + +### Confirmation Options +- **`[y]es`** - Remove user from current repository +- **`[n]o`** - Skip current repository +- **`[a]ll yes`** - Remove user from all remaining repositories +- **`[s]kip all`** - Skip all remaining repositories +- **`[q]uit`** - Cancel entire operation + +### Confirmation Modes +- **`ask`** - Default mode, prompts for each repository +- **`yes_all`** - Automatically confirm all operations +- **`no_all`** - Automatically skip all operations + +## Repository Discovery + +The tool performs comprehensive repository discovery: + +### Discovery Process +1. **Root User Repositories**: Fetches all repositories owned by the root user +2. **Organization Discovery**: Identifies organizations the root user belongs to +3. **Organization Repositories**: Fetches repositories from each organization +4. **Pattern Filtering**: Applies wildcard patterns to repository names +5. **Deduplication**: Removes duplicate repositories from the final list + +### API Endpoints Used +- `GET /users/{user}/repos` - User repositories +- `GET /users/{user}/orgs` - User organizations +- `GET /orgs/{org}/repos` - Organization repositories +- `DELETE /repos/{owner}/{repo}/collaborators/{username}` - Remove collaborator + +## Error Handling + +The tool includes comprehensive error handling: + +### HTTP Status Codes +- **`204`** - Successful removal +- **`404`** - User not found or not a collaborator +- **`403`** - Insufficient permissions +- **`401`** - Invalid authentication + +### Error Recovery +- **Network Failures**: Retry mechanisms for API calls +- **Rate Limiting**: Respects GitHub API rate limits +- **Permission Errors**: Clear error messages and suggestions +- **Invalid Input**: Input validation and correction prompts + +## Logging and Output + +### Log Levels +- **Info** (â„šī¸): General information messages +- **Success** (✅): Successful operations +- **Warning** (âš ī¸): Non-critical issues +- **Error** (❌): Critical failures +- **Progress** (🔄): Operation progress updates + +### Output Format +``` +[EMOJI] [TIMESTAMP] [LEVEL] Message +``` + +### Summary Report +``` +Operation Summary +================= +Total repositories processed: 15 +Successful removals: 12 +Failed removals: 1 +Skipped removals: 2 +Success rate: 80% +``` + +## Prerequisites + +### Required Tools +- `curl` - HTTP client for API requests +- `jq` - JSON processor for API responses + +### GitHub Token Permissions +- `repo` - Repository access (read/write) +- `admin:org` - Organization administration + +### Environment Requirements +- Bash 4.0 or higher +- Internet connectivity for GitHub API access +- Valid GitHub Personal Access Token + +## Security Considerations + +### Token Security +- Tokens are not stored or logged +- Input is hidden during token entry +- Tokens are validated before use + +### Operation Safety +- Interactive confirmations prevent accidental operations +- Detailed logging for audit trails +- Rollback information provided for manual recovery + +### Access Control +- Respects GitHub repository permissions +- Validates user access before operations +- Handles permission errors gracefully + +## Troubleshooting + +### Common Issues +1. **Token Validation Fails**: Ensure token has correct permissions +2. **Repository Not Found**: Check repository name and access permissions +3. **User Not Found**: Verify username spelling and existence +4. **Rate Limiting**: Wait for rate limit reset or use token with higher limits + +### Debug Mode +Enable verbose output by setting: +```bash +export DEBUG=1 +./remove_user_interactive.sh +``` + +## Integration + +The tool integrates seamlessly with other ByteLyst DevOps tools: +- Can be called from `bytelyst-cli.sh` +- Supports JSON configuration files +- Compatible with existing workflow scripts +- Follows established logging and error handling patterns + +## Performance + +### Optimization Features +- Paginated API requests for large datasets +- Parallel processing where possible +- Efficient pattern matching algorithms +- Minimal memory footprint + +### Scale Considerations +- Handles hundreds of repositories efficiently +- Respects GitHub API rate limits +- Provides progress feedback for long operations +- Supports interruption and resumption \ No newline at end of file diff --git a/remove_user_interactive.sh b/remove_user_interactive.sh new file mode 100755 index 0000000..b8808c7 --- /dev/null +++ b/remove_user_interactive.sh @@ -0,0 +1,416 @@ +#!/bin/bash + +# Interactive User Removal Tool for GitHub Repositories +# Supports wildcard matching and handles both user and organization repositories + +set -euo pipefail + +# Color definitions +readonly RED='\033[0;31m' +readonly GREEN='\033[0;32m' +readonly YELLOW='\033[1;33m' +readonly BLUE='\033[0;34m' +readonly CYAN='\033[0;36m' +readonly PURPLE='\033[0;35m' +readonly BOLD='\033[1m' +readonly NC='\033[0m' # No Color + +# Global variables +GITHUB_TOKEN="" +ROOT_USER="" +USER_TO_REMOVE="" +REPO_PATTERN="" +CONFIRMATION_MODE="ask" # ask, yes_all, no_all +TOTAL_REPOS=0 +PROCESSED_REPOS=0 +SUCCESSFUL_REMOVALS=0 +FAILED_REMOVALS=0 +SKIPPED_REMOVALS=0 + +# Required tools +REQUIRED_TOOLS=(curl jq) + +# Utility functions +log_info() { + echo -e "${BLUE}â„šī¸ $1${NC}" +} + +log_success() { + echo -e "${GREEN}✅ $1${NC}" +} + +log_warning() { + echo -e "${YELLOW}âš ī¸ $1${NC}" +} + +log_error() { + echo -e "${RED}❌ $1${NC}" +} + +log_progress() { + echo -e "${CYAN}🔄 $1${NC}" +} + +log_header() { + echo -e "\n${BOLD}${PURPLE}$1${NC}" + echo -e "${PURPLE}$(printf '=%.0s' {1..50})${NC}" +} + +# Check required tools +check_dependencies() { + log_header "Checking Dependencies" + for tool in "${REQUIRED_TOOLS[@]}"; do + if ! command -v "$tool" &>/dev/null; then + log_error "Required tool '$tool' is not installed. Please install it and try again." + exit 1 + fi + log_success "$tool is available" + done +} + +# Input collection functions +collect_github_token() { + log_header "GitHub Authentication" + echo -e "${YELLOW}Enter your GitHub Personal Access Token:${NC}" + echo -e "${CYAN}(Token needs 'repo' and 'admin:org' permissions)${NC}" + read -s -r -p "Token: " GITHUB_TOKEN + echo + + if [[ -z "$GITHUB_TOKEN" ]]; then + log_error "GitHub token cannot be empty" + exit 1 + fi + + # Validate token + log_progress "Validating GitHub token..." + local response + response=$(curl -s -w "%{http_code}" -H "Authorization: token $GITHUB_TOKEN" https://api.github.com/user) + local http_code="${response: -3}" + + if [[ "$http_code" != "200" ]]; then + log_error "Invalid GitHub token or insufficient permissions" + exit 1 + fi + + log_success "GitHub token validated successfully" +} + +collect_root_user() { + log_header "Root Account Information" + echo -e "${YELLOW}Enter the root GitHub username/organization:${NC}" + read -r -p "Root user: " ROOT_USER + + if [[ -z "$ROOT_USER" ]]; then + log_error "Root user cannot be empty" + exit 1 + fi + + log_success "Root user set to: $ROOT_USER" +} + +collect_user_to_remove() { + log_header "User Removal Target" + echo -e "${YELLOW}Enter the username to remove from repositories:${NC}" + read -r -p "User to remove: " USER_TO_REMOVE + + if [[ -z "$USER_TO_REMOVE" ]]; then + log_error "User to remove cannot be empty" + exit 1 + fi + + log_success "Target user: $USER_TO_REMOVE" +} + +collect_repo_pattern() { + log_header "Repository Pattern" + echo -e "${YELLOW}Enter repository pattern (supports wildcards):${NC}" + echo -e "${CYAN}Examples: *-go-api*, frontend-*, *-service, specific-repo${NC}" + read -r -p "Repository pattern: " REPO_PATTERN + + if [[ -z "$REPO_PATTERN" ]]; then + log_error "Repository pattern cannot be empty" + exit 1 + fi + + log_success "Repository pattern: $REPO_PATTERN" +} + +# GitHub API functions +fetch_user_repos() { + local user="$1" + local page=1 + local all_repos=() + + log_progress "Fetching repositories for user: $user" + + while true; do + local response + response=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \ + "https://api.github.com/users/$user/repos?per_page=100&page=$page&type=all") + + local repos + repos=$(echo "$response" | jq -r '.[].full_name // empty') + + if [[ -z "$repos" ]]; then + break + fi + + while IFS= read -r repo; do + all_repos+=("$repo") + done <<< "$repos" + + ((page++)) + done + + printf '%s\n' "${all_repos[@]}" +} + +fetch_org_repos() { + local org="$1" + local page=1 + local all_repos=() + + log_progress "Fetching repositories for organization: $org" + + while true; do + local response + response=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \ + "https://api.github.com/orgs/$org/repos?per_page=100&page=$page&type=all") + + local repos + repos=$(echo "$response" | jq -r '.[].full_name // empty') + + if [[ -z "$repos" ]]; then + break + fi + + while IFS= read -r repo; do + all_repos+=("$repo") + done <<< "$repos" + + ((page++)) + done + + printf '%s\n' "${all_repos[@]}" +} + +fetch_user_orgs() { + local user="$1" + log_progress "Fetching organizations for user: $user" + + local response + response=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \ + "https://api.github.com/users/$user/orgs") + + echo "$response" | jq -r '.[].login // empty' +} + +# Repository matching function +match_repo_pattern() { + local repo_name="$1" + local pattern="$2" + + # Convert shell wildcard pattern to regex + local regex_pattern + regex_pattern="${pattern//\*/.*}" + + if [[ "$repo_name" =~ $regex_pattern ]]; then + return 0 + else + return 1 + fi +} + +# User confirmation functions +get_confirmation() { + local repo="$1" + local current="$2" + local total="$3" + + case "$CONFIRMATION_MODE" in + "yes_all") + return 0 + ;; + "no_all") + return 1 + ;; + "ask") + echo -e "\n${YELLOW}[$current/$total] Remove user '$USER_TO_REMOVE' from '$repo'?${NC}" + echo -e "${CYAN}Options: [y]es, [n]o, [a]ll yes, [q]uit, [s]kip all${NC}" + read -p "Choice: " -n 1 -r choice + echo + + case "$choice" in + y|Y) + return 0 + ;; + n|N) + return 1 + ;; + a|A) + CONFIRMATION_MODE="yes_all" + log_info "Switched to 'yes to all' mode" + return 0 + ;; + s|S) + CONFIRMATION_MODE="no_all" + log_info "Switched to 'skip all' mode" + return 1 + ;; + q|Q) + log_warning "Operation cancelled by user" + exit 0 + ;; + *) + log_warning "Invalid choice, skipping..." + return 1 + ;; + esac + ;; + esac +} + +# User removal function +remove_user_from_repo() { + local repo="$1" + + log_progress "Removing $USER_TO_REMOVE from $repo..." + + local response + response=$(curl -s -w "%{http_code}" -X DELETE \ + -H "Authorization: token $GITHUB_TOKEN" \ + "https://api.github.com/repos/$repo/collaborators/$USER_TO_REMOVE") + + local http_code="${response: -3}" + + case "$http_code" in + 204) + log_success "Successfully removed $USER_TO_REMOVE from $repo" + ((SUCCESSFUL_REMOVALS++)) + return 0 + ;; + 404) + log_warning "$USER_TO_REMOVE is not a collaborator on $repo or repo not found" + ((SKIPPED_REMOVALS++)) + return 1 + ;; + *) + log_error "Failed to remove $USER_TO_REMOVE from $repo (HTTP: $http_code)" + ((FAILED_REMOVALS++)) + return 1 + ;; + esac +} + +# Progress display +show_progress() { + local current="$1" + local total="$2" + local percentage=$((current * 100 / total)) + + printf "\r${CYAN}Progress: [%3d%%] %d/%d repositories processed${NC}" "$percentage" "$current" "$total" +} + +# Summary report +show_summary() { + log_header "Operation Summary" + echo -e "${BOLD}Total repositories processed: $PROCESSED_REPOS${NC}" + echo -e "${GREEN}Successful removals: $SUCCESSFUL_REMOVALS${NC}" + echo -e "${RED}Failed removals: $FAILED_REMOVALS${NC}" + echo -e "${YELLOW}Skipped removals: $SKIPPED_REMOVALS${NC}" + echo -e "${CYAN}Success rate: $(( SUCCESSFUL_REMOVALS * 100 / (SUCCESSFUL_REMOVALS + FAILED_REMOVALS + SKIPPED_REMOVALS) ))%${NC}" +} + +# Main execution function +main() { + log_header "Interactive GitHub User Removal Tool" + + # Check dependencies + check_dependencies + + # Collect inputs + collect_github_token + collect_root_user + collect_user_to_remove + collect_repo_pattern + + # Collect all repositories + log_header "Repository Discovery" + local all_repos=() + + # Fetch root user repositories + while IFS= read -r repo; do + [[ -n "$repo" ]] && all_repos+=("$repo") + done < <(fetch_user_repos "$ROOT_USER") + + # Fetch organization repositories + while IFS= read -r org; do + if [[ -n "$org" ]]; then + log_info "Found organization: $org" + while IFS= read -r repo; do + [[ -n "$repo" ]] && all_repos+=("$repo") + done < <(fetch_org_repos "$org") + fi + done < <(fetch_user_orgs "$ROOT_USER") + + # Filter repositories by pattern + log_header "Repository Filtering" + local matching_repos=() + + for repo in "${all_repos[@]}"; do + local repo_name + repo_name=$(basename "$repo") + + if match_repo_pattern "$repo_name" "$REPO_PATTERN"; then + matching_repos+=("$repo") + log_info "Matched: $repo" + fi + done + + TOTAL_REPOS=${#matching_repos[@]} + + if [[ $TOTAL_REPOS -eq 0 ]]; then + log_warning "No repositories match the pattern '$REPO_PATTERN'" + exit 0 + fi + + log_success "Found $TOTAL_REPOS matching repositories" + + # Confirmation before proceeding + echo -e "\n${YELLOW}About to remove user '$USER_TO_REMOVE' from $TOTAL_REPOS repositories matching '$REPO_PATTERN'${NC}" + read -p "Continue? [y/N]: " -n 1 -r + echo + + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + log_warning "Operation cancelled" + exit 0 + fi + + # Process repositories + log_header "User Removal Process" + + for repo in "${matching_repos[@]}"; do + ((PROCESSED_REPOS++)) + + show_progress "$PROCESSED_REPOS" "$TOTAL_REPOS" + + if get_confirmation "$repo" "$PROCESSED_REPOS" "$TOTAL_REPOS"; then + remove_user_from_repo "$repo" + else + log_info "Skipped: $repo" + ((SKIPPED_REMOVALS++)) + fi + done + + echo # New line after progress + + # Show final summary + show_summary + + log_success "Operation completed successfully!" +} + +# Script execution +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + main "$@" +fi \ No newline at end of file