feat: add interactive user removal tool with wildcard matching
- 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 <noreply@anthropic.com>
This commit is contained in:
parent
9320b3401d
commit
6a6bfb5d12
85
CLAUDE.md
Normal file
85
CLAUDE.md
Normal file
@ -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
|
||||
135
README.md
135
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.
|
||||
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.
|
||||
204
docs/remove_user_interactive.md
Normal file
204
docs/remove_user_interactive.md
Normal file
@ -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
|
||||
416
remove_user_interactive.sh
Executable file
416
remove_user_interactive.sh
Executable file
@ -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
|
||||
Loading…
Reference in New Issue
Block a user