From 1beb8807ef7f9dca04005054b3a9388b3d876ae0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Feb 2026 11:52:46 +0000 Subject: [PATCH 1/5] Initial plan From 6507693b7fd6501a1de8b2172777df1355a4bace Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Feb 2026 11:56:38 +0000 Subject: [PATCH 2/5] refactor: extract package parsing helper and derive environments dynamically - Added parse_packages() function to eliminate code duplication - Added get_available_environments() to dynamically derive environment list from apt/ directory - Updated interactive menu to use dynamically generated environment list - Updated help text to reflect dynamic environment detection - Addresses PR review feedback from thread #3769662762 Co-authored-by: swarm-protocol <169869917+swarm-protocol@users.noreply.github.com> --- bootstrap.sh | 124 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 75 insertions(+), 49 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index dbf26a9..ad100e6 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -34,8 +34,11 @@ show_help() { echo " -y, --yes Assume yes to all prompts (non-interactive)" echo " --help Show this help message" echo - echo "Available environments: common, test, docker, documentation, code-review," - echo " refactoring, wrangler, terraform, ansible, security, all" + echo "Available environments:" + echo " Environments are detected from the apt/ or nix/ directories." + echo " Common environments: common, test, docker, documentation, code-review," + echo " refactoring, wrangler, terraform, ansible, security" + echo " Special: all (APT only - installs all environments)" } print_header() { @@ -168,6 +171,13 @@ prepare_apt_environment() { return 0 } +# Parse packages from a packages.txt file +# Removes comments (including trailing ones) and empty lines +parse_packages() { + local packages_file=$1 + sed 's/#.*//' "$packages_file" | xargs +} + # Setup environment using APT setup_apt_environment() { local env_type=$1 @@ -184,9 +194,9 @@ setup_apt_environment() { print_info "Installing packages from apt/$env_type/packages.txt" print_warning "This requires sudo privileges" - # Use sed to remove comments (including trailing ones) and empty lines + # Use the centralized package parsing function local pkgs - pkgs=$(sed 's/#.*//' "apt/$env_type/packages.txt" | xargs) + pkgs=$(parse_packages "apt/$env_type/packages.txt") if [ -n "$pkgs" ]; then if sudo apt install -y $pkgs; then @@ -202,11 +212,29 @@ setup_apt_environment() { fi } +# Get list of available environments dynamically from apt/ directory +get_available_environments() { + local envs=() + if [ -d "apt" ]; then + while IFS= read -r -d '' env_dir; do + local env_name + env_name="${env_dir#apt/}" + env_name="${env_name%/}" + envs+=("$env_name") + done < <(find apt -mindepth 1 -maxdepth 1 -type d -print0 2>/dev/null | sort -z) + fi + echo "${envs[@]}" +} + # Show environment menu show_environment_menu() { local setup_method=$1 local env_type=$ENV_TYPE + # Get available environments dynamically + local -a envs + IFS=' ' read -r -a envs <<< "$(get_available_environments)" + if [ -z "$env_type" ]; then if [ "$ASSUME_YES" = true ]; then print_error "Environment type (--env) must be specified in non-interactive mode" @@ -215,53 +243,51 @@ show_environment_menu() { print_header "Choose Development Environment" echo "Available environments:" - echo " 1) common - Core development tools (git, editors, etc.)" - echo " 2) test - Testing frameworks and tools" - echo " 3) docker - Docker and container tools" - echo " 4) documentation - Documentation generation tools" - echo " 5) code-review - Linters, formatters, analyzers" - echo " 6) refactoring - Code transformation tools" - echo " 7) wrangler - CloudFlare Workers development" - echo " 8) terraform - Infrastructure as Code tools" - echo " 9) ansible - Ansible automation tools" - echo " 10) security - Security auditing and scanning tools" - echo " 11) all - Install all environments (APT only)" + local i=1 + for env in "${envs[@]}"; do + # Format environment names for display + local description="" + case "$env" in + common) description="Core development tools (git, editors, etc.)" ;; + test) description="Testing frameworks and tools" ;; + docker) description="Docker and container tools" ;; + documentation) description="Documentation generation tools" ;; + code-review) description="Linters, formatters, analyzers" ;; + refactoring) description="Code transformation tools" ;; + wrangler) description="CloudFlare Workers development" ;; + terraform) description="Infrastructure as Code tools" ;; + ansible) description="Ansible automation tools" ;; + security) description="Security auditing and scanning tools" ;; + *) description="$env environment" ;; + esac + printf " %2d) %-15s - %s\n" "$i" "$env" "$description" + ((i++)) + done + + # Add "all" option for APT + if [ "$setup_method" = "apt" ]; then + printf " %2d) %-15s - %s\n" "$i" "all" "Install all environments (APT only)" + local all_option=$i + ((i++)) + fi + echo " 0) exit - Exit setup" echo - read -p "Select environment (1-11, 0 to exit): " choice - - case $choice in - 1) env_type="common" ;; - 2) env_type="test" ;; - 3) env_type="docker" ;; - 4) env_type="documentation" ;; - 5) env_type="code-review" ;; - 6) env_type="refactoring" ;; - 7) env_type="wrangler" ;; - 8) env_type="terraform" ;; - 9) env_type="ansible" ;; - 10) env_type="security" ;; - 11) - if [ "$setup_method" = "apt" ]; then - env_type="all" - else - print_error "Installing all environments is only supported with APT" - return 1 - fi - ;; - 0) - print_info "Exiting setup" - exit 0 - ;; - *) - print_error "Invalid choice" - return 1 - ;; - esac + read -p "Select environment (0-$((i-1))): " choice + + if [ "$choice" = "0" ]; then + print_info "Exiting setup" + exit 0 + elif [ "$choice" -ge 1 ] && [ "$choice" -le "${#envs[@]}" ]; then + env_type="${envs[$((choice-1))]}" + elif [ "$setup_method" = "apt" ] && [ "$choice" = "$all_option" ]; then + env_type="all" + else + print_error "Invalid choice" + return 1 + fi fi - - local envs=("common" "test" "docker" "documentation" "code-review" "refactoring" "wrangler" "terraform" "ansible" "security") if [ "$setup_method" = "nix" ]; then setup_nix_environment "$env_type" || return 1 @@ -280,8 +306,8 @@ show_environment_menu() { if [ -f "apt/$env/packages.txt" ]; then # Call preparation logic for each environment to preserve abstraction prepare_apt_environment "$env" - # Collect packages while handling comments - all_packages+="$(sed 's/#.*//' "apt/$env/packages.txt") " + # Collect packages using the centralized parsing function + all_packages+="$(parse_packages "apt/$env/packages.txt") " fi done From c734dcaadd1186c611194548d77ef71e589b8d4f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Feb 2026 11:57:40 +0000 Subject: [PATCH 3/5] fix: add input validation and robustness checks - Add validation for empty environment names in get_available_environments() - Add numeric validation for user choice input - Fix all_option check to handle undefined variable safely - Addresses code review feedback Co-authored-by: swarm-protocol <169869917+swarm-protocol@users.noreply.github.com> --- bootstrap.sh | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index ad100e6..c00940b 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -220,7 +220,10 @@ get_available_environments() { local env_name env_name="${env_dir#apt/}" env_name="${env_name%/}" - envs+=("$env_name") + # Validate env_name is not empty + if [ -n "$env_name" ]; then + envs+=("$env_name") + fi done < <(find apt -mindepth 1 -maxdepth 1 -type d -print0 2>/dev/null | sort -z) fi echo "${envs[@]}" @@ -276,12 +279,18 @@ show_environment_menu() { read -p "Select environment (0-$((i-1))): " choice + # Validate choice is numeric + if ! [[ "$choice" =~ ^[0-9]+$ ]]; then + print_error "Invalid choice: must be a number" + return 1 + fi + if [ "$choice" = "0" ]; then print_info "Exiting setup" exit 0 elif [ "$choice" -ge 1 ] && [ "$choice" -le "${#envs[@]}" ]; then env_type="${envs[$((choice-1))]}" - elif [ "$setup_method" = "apt" ] && [ "$choice" = "$all_option" ]; then + elif [ "$setup_method" = "apt" ] && [ -n "${all_option:-}" ] && [ "$choice" = "$all_option" ]; then env_type="all" else print_error "Invalid choice" From 6b8def93bb72b344c47591c702402ed157593f73 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Feb 2026 11:58:23 +0000 Subject: [PATCH 4/5] fix: improve shell scripting best practices - Quote function parameter to prevent word splitting - Handle empty environment list gracefully - Add numeric validation for all_option before comparison - Fix Cloudflare capitalization (one word, lowercase 'f') - Addresses final code review feedback Co-authored-by: swarm-protocol <169869917+swarm-protocol@users.noreply.github.com> --- bootstrap.sh | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index c00940b..0e1f78b 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -174,7 +174,7 @@ prepare_apt_environment() { # Parse packages from a packages.txt file # Removes comments (including trailing ones) and empty lines parse_packages() { - local packages_file=$1 + local packages_file="$1" sed 's/#.*//' "$packages_file" | xargs } @@ -236,7 +236,16 @@ show_environment_menu() { # Get available environments dynamically local -a envs - IFS=' ' read -r -a envs <<< "$(get_available_environments)" + local env_list + env_list=$(get_available_environments) + + # Handle empty environment list + if [ -z "$env_list" ]; then + print_error "No environments found in apt/ or nix/ directory" + return 1 + fi + + IFS=' ' read -r -a envs <<< "$env_list" if [ -z "$env_type" ]; then if [ "$ASSUME_YES" = true ]; then @@ -257,7 +266,7 @@ show_environment_menu() { documentation) description="Documentation generation tools" ;; code-review) description="Linters, formatters, analyzers" ;; refactoring) description="Code transformation tools" ;; - wrangler) description="CloudFlare Workers development" ;; + wrangler) description="Cloudflare Workers development" ;; terraform) description="Infrastructure as Code tools" ;; ansible) description="Ansible automation tools" ;; security) description="Security auditing and scanning tools" ;; @@ -290,7 +299,7 @@ show_environment_menu() { exit 0 elif [ "$choice" -ge 1 ] && [ "$choice" -le "${#envs[@]}" ]; then env_type="${envs[$((choice-1))]}" - elif [ "$setup_method" = "apt" ] && [ -n "${all_option:-}" ] && [ "$choice" = "$all_option" ]; then + elif [ "$setup_method" = "apt" ] && [ -n "${all_option:-}" ] && [[ "$all_option" =~ ^[0-9]+$ ]] && [ "$choice" = "$all_option" ]; then env_type="all" else print_error "Invalid choice" From dc7cc7b456ca7cc62bb48b8779e53f2ff5dee375 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Feb 2026 11:59:07 +0000 Subject: [PATCH 5/5] refactor: simplify complex conditional and fix error message - Extract all_option validation into separate boolean for readability - Fix error message to only mention apt/ directory (matching function behavior) - Addresses final code review feedback Co-authored-by: swarm-protocol <169869917+swarm-protocol@users.noreply.github.com> --- bootstrap.sh | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/bootstrap.sh b/bootstrap.sh index 0e1f78b..77e99e0 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -241,7 +241,7 @@ show_environment_menu() { # Handle empty environment list if [ -z "$env_list" ]; then - print_error "No environments found in apt/ or nix/ directory" + print_error "No environments found in apt/ directory" return 1 fi @@ -299,11 +299,19 @@ show_environment_menu() { exit 0 elif [ "$choice" -ge 1 ] && [ "$choice" -le "${#envs[@]}" ]; then env_type="${envs[$((choice-1))]}" - elif [ "$setup_method" = "apt" ] && [ -n "${all_option:-}" ] && [[ "$all_option" =~ ^[0-9]+$ ]] && [ "$choice" = "$all_option" ]; then - env_type="all" else - print_error "Invalid choice" - return 1 + # Check if this is the "all" option for APT + local is_all_option=false + if [ "$setup_method" = "apt" ] && [ -n "${all_option:-}" ] && [[ "$all_option" =~ ^[0-9]+$ ]] && [ "$choice" = "$all_option" ]; then + is_all_option=true + fi + + if [ "$is_all_option" = true ]; then + env_type="all" + else + print_error "Invalid choice" + return 1 + fi fi fi