Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 45 additions & 3 deletions .claude/tasks/2025-07-07-bash-migration.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
# Bash Migration Epic

## Current Status (July 7, 2025)
## Current Status (July 11, 2025)

**Task**: Migrate dotfiles installation infrastructure from custom zsh to industry-standard bash + shellcheck + bats
**Approach**: Enhanced 3-phase migration with setup.bash at the center for maximum tooling leverage
**Current**: Phase 1 enhanced scope - migrating setup.bash + core scripts + shared utilities
**Current**: Phase 1 nearing completion - core utilities and 4 installation scripts migrated, setup.bash pending

## Migration Strategy

### Phase 1: Setup + Core Infrastructure Migration (IN PROGRESS - Enhanced Scope)
**Goal**: Migrate setup.bash + core installation scripts + shared utilities for maximum tooling leverage

#### βœ… PR #13: GitHub Installation Testing (MERGED)
#### Completed PRs

##### βœ… PR #13: GitHub Installation Testing (MERGED)
- **Files Created**:
- `lib/github-utils.bash` - GitHub SSH utilities (shellcheck clean)
- `bin/install/github.bash` - Bash replacement for github.zsh
Expand All @@ -22,6 +24,46 @@
- **Benefits Demonstrated**: Better error catching, industry-standard tooling, cleaner syntax
- **Status**: MERGED - established complete migration pattern with 20 passing tests

##### βœ… PR #15: SSH Installation Testing (MERGED)
- **Files Created**:
- `lib/ssh-utils.bash` - SSH utilities with comprehensive functionality
- `bin/install/ssh.bash` - Bash replacement for ssh.zsh
- `test/install/test-ssh-utils.bats` - 14 utility function tests
- `test/install/test-ssh-installation.bats` - 7 integration tests
- **Test Results**: All 21 tests passing, shellcheck compliance verified
- **Improvements**: Better macOS version detection for ssh-add keychain flag
- **Status**: MERGED - SSH installation fully migrated to bash

##### βœ… PR #17: Homebrew Utilities Migration (MERGED)
- **Files Created**:
- `lib/homebrew-utils.bash` - Homebrew shared utilities
- `bin/install/homebrew.bash` - Bash replacement for homebrew.zsh
- `test/install/test-homebrew-utils.bats` - Comprehensive utility tests
- **Status**: MERGED - Homebrew installation fully migrated with shared utilities

##### βœ… PR #18: Core Utility Libraries Migration (MERGED)
- **Files Migrated**:
- `bin/lib/machine-detection.bash` - Dynamic hostname-based machine detection
- `bin/lib/prerequisite-validation.bash` - System prerequisites validation
- Test files for all core utilities
- **Status**: MERGED - Core utilities successfully migrated to bash

##### βœ… PR #19: Dry-run and Error Handling Utilities (MERGED)
- **Files Created**:
- `bin/lib/dry-run-utils.bash` - Complete dry-run functionality
- `bin/lib/error-handling.bash` - Error handling and retry mechanisms
- `test/setup/test-dry-run-utils-bash.bats` - 20 tests for dry-run utilities
- **Test Results**: 20/20 tests passing, zero shellcheck warnings
- **Status**: MERGED - Dry-run and error handling utilities in bash
- **Note**: Error handling tests still needed

##### βœ… PR #20: Symlink Utilities Extraction (MERGED)
- **Files Created**:
- `lib/symlink-utils.bash` - Symlink management utilities
- `bin/install/symlinks.bash` - Bash replacement for symlinks installation
- `test/setup/test-symlink-utils-bash.bats` - Comprehensive symlink tests
- **Status**: MERGED - Symlink functionality fully migrated to bash

### Phase 2: Remaining Script Migration (Pending)
**Goal**: Migrate remaining installation scripts using established three-tier architecture

Expand Down
135 changes: 135 additions & 0 deletions test/setup/test-error-handling-bash.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#!/usr/bin/env bats

# Test error handling utilities (bash implementation)

# Load the error handling utilities
load "../../bin/lib/error-handling.bash"

# Test capture_error with no command provided
@test "capture_error returns error when no command provided" {
run capture_error
[ "$status" -eq 1 ]
[[ "$output" =~ "Error: No command provided to capture_error" ]]
}

# Test capture_error with successful command
@test "capture_error executes successful command and returns 0" {
run capture_error "echo 'Hello World'"
[ "$status" -eq 0 ]
[[ "$output" == "Hello World" ]]
}

# Test capture_error with failing command
@test "capture_error handles failing command and provides context" {
run capture_error "exit 42" "Test operation"
[ "$status" -eq 42 ]
[[ "$output" =~ "Error: Test operation failed (exit code: 42)" ]]
[[ "$output" =~ "Command: exit 42" ]]
}

# Test capture_error preserves command output before showing error
@test "capture_error shows command output before error message" {
run capture_error "echo 'Output before failure' && exit 1" "Command with output"
[ "$status" -eq 1 ]
[[ "${lines[0]}" == "Output before failure" ]]
[[ "$output" =~ "Error: Command with output failed" ]]
}

# Test retry_with_backoff with no command provided
@test "retry_with_backoff returns error when no command provided" {
run retry_with_backoff
[ "$status" -eq 1 ]
[[ "$output" =~ "Error: No command provided to retry_with_backoff" ]]
}

# Test retry_with_backoff with successful command on first try
@test "retry_with_backoff succeeds on first attempt" {
run retry_with_backoff "exit 0"
[ "$status" -eq 0 ]
}

# Test retry_with_backoff exhausts all attempts and fails
@test "retry_with_backoff fails after exhausting max attempts" {
run retry_with_backoff "exit 1" 2 0
[ "$status" -eq 1 ]
}

# Test handle_error with no command provided
@test "handle_error returns error when no command provided" {
run handle_error
[ "$status" -eq 1 ]
[[ "$output" =~ "Error: No command provided to handle_error" ]]
}

# Test handle_error displays error message and generic suggestion
@test "handle_error displays error message and generic suggestion" {
run handle_error "test-command" "999" "Custom error message"
[ "$status" -eq 1 ]
[[ "$output" =~ "❌ Error occurred while running: test-command" ]]
[[ "$output" =~ "Error: Custom error message" ]]
[[ "$output" =~ "πŸ’‘ Suggestion: Check the command syntax and try again" ]]
}

# Test handle_error provides permission-specific suggestion
@test "handle_error provides permission-specific suggestion for EACCES" {
run handle_error "test-command" "EACCES" "Permission denied"
[ "$status" -eq 1 ]
[[ "$output" =~ "❌ Error occurred while running: test-command" ]]
[[ "$output" =~ "Error: Permission denied" ]]
[[ "$output" =~ "πŸ’‘ Suggestion: Try running with sudo or check file permissions" ]]
}

# Test handle_error provides file-not-found suggestion
@test "handle_error provides file-not-found suggestion for ENOENT" {
run handle_error "test-command" "ENOENT" "No such file or directory"
[ "$status" -eq 1 ]
[[ "$output" =~ "❌ Error occurred while running: test-command" ]]
[[ "$output" =~ "Error: No such file or directory" ]]
[[ "$output" =~ "πŸ’‘ Suggestion: Check if the file or directory exists" ]]
}

# Test handle_error provides network-specific suggestion
@test "handle_error provides network-specific suggestion for ECONNREFUSED" {
run handle_error "test-command" "ECONNREFUSED" "Connection refused"
[ "$status" -eq 1 ]
[[ "$output" =~ "❌ Error occurred while running: test-command" ]]
[[ "$output" =~ "Error: Connection refused" ]]
[[ "$output" =~ "πŸ’‘ Suggestion: Check your internet connection or try again later" ]]
}

# Test handle_error provides disk-space suggestion
@test "handle_error provides disk-space suggestion for ENOSPC" {
run handle_error "test-command" "ENOSPC" "No space left on device"
[ "$status" -eq 1 ]
[[ "$output" =~ "❌ Error occurred while running: test-command" ]]
[[ "$output" =~ "Error: No space left on device" ]]
[[ "$output" =~ "πŸ’‘ Suggestion: Free up disk space and try again" ]]
}

# Test retry_with_backoff succeeds on second attempt
@test "retry_with_backoff succeeds on second attempt after one failure" {
# Create a file that tracks attempts
local attempt_file=$(mktemp)
echo "0" > "$attempt_file"

# Command that fails first time, succeeds second time
local test_command="
current=\$(cat '$attempt_file')
next=\$((current + 1))
echo \$next > '$attempt_file'
[ \$next -eq 2 ]
"

run retry_with_backoff "$test_command" 3 0
[ "$status" -eq 0 ]

# Clean up
rm -f "$attempt_file"
}

# Test capture_error with default context
@test "capture_error uses default context when none provided" {
run capture_error "exit 1"
[ "$status" -eq 1 ]
[[ "$output" =~ "Error: Command execution failed" ]]
}
Loading