mirror of
https://github.com/acedanger/shell.git
synced 2025-12-06 00:00:13 -08:00
Enhance setup and testing scripts for improved package management and logging
- Updated setup.sh to check for Nala installation and provide alternative installation methods based on Ubuntu version. - Added error handling for package installation, allowing fallback to apt if Nala fails. - Introduced startup.sh to perform container startup checks, including system info and permissions for logs directory. - Created test-setup.sh to validate bootstrap and setup scripts, including detailed logging of package availability and installation results. - Implemented checks for missing packages and provided recommendations for manual installation. - Enhanced logging for better traceability of actions and errors during setup and testing processes.
This commit is contained in:
161
.github/copilot-instructions.md
vendored
Normal file
161
.github/copilot-instructions.md
vendored
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
# GitHub Copilot Instructions for Shell Repository
|
||||||
|
|
||||||
|
This document provides context and guidance for GitHub Copilot when working with this shell script and dotfiles repository.
|
||||||
|
|
||||||
|
## Repository Overview
|
||||||
|
|
||||||
|
This repository contains:
|
||||||
|
|
||||||
|
1. **Shell scripts** for system administration tasks
|
||||||
|
2. **Dotfiles** for system configuration
|
||||||
|
3. **Setup scripts** for automated environment configuration
|
||||||
|
4. **Docker-based testing framework** for validating setup across environments
|
||||||
|
|
||||||
|
## Repository Structure
|
||||||
|
|
||||||
|
- **Root directory**: Contains various utility shell scripts
|
||||||
|
- **docs/**: Documentation for individual scripts and components
|
||||||
|
- **dotfiles/**: System configuration files that get symlinked to the user's home directory
|
||||||
|
- **powershell/**: PowerShell scripts for Windows environments
|
||||||
|
- **setup/**: Setup scripts and package lists for automated environment configuration
|
||||||
|
- **.github/**: GitHub-related configuration files
|
||||||
|
|
||||||
|
## Key Files Overview
|
||||||
|
|
||||||
|
### Shell Scripts
|
||||||
|
|
||||||
|
- **bootstrap.sh**: Entry point script for automated setup
|
||||||
|
- **test-setup.sh**: Testing script for validating environment setup
|
||||||
|
- **run-docker-tests.sh**: Runner for Docker-based testing
|
||||||
|
- **update.sh**: System update scripts
|
||||||
|
- **plex.sh**: Plex Media Server management
|
||||||
|
|
||||||
|
### Configuration Files
|
||||||
|
|
||||||
|
- **setup/packages.list**: List of packages to install during setup
|
||||||
|
- **dotfiles/my-aliases.zsh**: Custom ZSH aliases
|
||||||
|
- **dotfiles/tailscale-acl.json**: Tailscale ACL configuration
|
||||||
|
|
||||||
|
### Documentation
|
||||||
|
|
||||||
|
- **README.md**: Main repository documentation
|
||||||
|
- **docs/testing.md**: Detailed documentation for the testing framework
|
||||||
|
- **dotfiles/README.md**: Documentation for dotfiles setup and usage
|
||||||
|
|
||||||
|
## Style Guidelines
|
||||||
|
|
||||||
|
When suggesting code or modifications:
|
||||||
|
|
||||||
|
1. **Shell Scripts**:
|
||||||
|
- Use `#!/bin/bash` for most scripts
|
||||||
|
- Include proper error handling with `set -e` where appropriate
|
||||||
|
- For test scripts, avoid `set -e` to allow testing all components
|
||||||
|
- Add descriptive comments for script sections
|
||||||
|
- Use colors for terminal output when appropriate (GREEN, RED, YELLOW, etc.)
|
||||||
|
- Use capitalized variable names (e.g., `USER_HOME=/home/user`)
|
||||||
|
|
||||||
|
2. **Docker Files**:
|
||||||
|
- Follow Docker best practices for layer optimization
|
||||||
|
- Use specific tags for base images rather than 'latest'
|
||||||
|
- Include proper LABEL directives for metadata
|
||||||
|
|
||||||
|
3. **Documentation**:
|
||||||
|
- Use proper Markdown formatting
|
||||||
|
- Include code examples using appropriate syntax highlighting
|
||||||
|
- Document script parameters and usage
|
||||||
|
|
||||||
|
## Testing Framework
|
||||||
|
|
||||||
|
When modifying the testing framework:
|
||||||
|
|
||||||
|
1. Make sure to test across both Ubuntu and Debian environments
|
||||||
|
2. Ensure tests continue even when individual components fail
|
||||||
|
3. Track and summarize all errors at the end of tests
|
||||||
|
4. Maintain proper error reporting and logging
|
||||||
|
|
||||||
|
### Docker Testing Enhancements
|
||||||
|
|
||||||
|
The Docker-based testing framework includes these key features:
|
||||||
|
|
||||||
|
1. **Continuous Testing**: Tests continue running even when individual package installations fail
|
||||||
|
- Achieved by removing `set -e` from test scripts
|
||||||
|
- Uses a counter to track errors rather than exiting immediately
|
||||||
|
|
||||||
|
2. **Package Testing**:
|
||||||
|
- Dynamically reads packages from `setup/packages.list`
|
||||||
|
- Tests each package individually
|
||||||
|
- Maintains an array of missing packages for final reporting
|
||||||
|
|
||||||
|
3. **Summary Reporting**:
|
||||||
|
- Provides a comprehensive summary of all failed tests
|
||||||
|
- Suggests commands to fix missing packages
|
||||||
|
- Saves detailed logs to a timestamped file in /tmp
|
||||||
|
|
||||||
|
4. **Cross-Platform Testing**:
|
||||||
|
- Tests both Ubuntu and Debian environments
|
||||||
|
- Handles platform-specific package names (e.g., `bat` vs `batcat`)
|
||||||
|
|
||||||
|
## Key Concepts
|
||||||
|
|
||||||
|
- **Shell Environment Setup**: Focuses on ZSH with Oh My Zsh and plugins
|
||||||
|
- **Docker Testing**: Validates environment setup in isolated containers
|
||||||
|
- **Dotfiles Management**: Uses symbolic links to user's home directory
|
||||||
|
- **Package Installation**: Uses apt/nala on Debian-based systems
|
||||||
|
|
||||||
|
## Main Use Cases
|
||||||
|
|
||||||
|
1. **Setting up a new development environment**: Using bootstrap.sh
|
||||||
|
2. **Managing media services**: Using plex.sh and related scripts
|
||||||
|
3. **System maintenance**: Using update.sh and backup scripts
|
||||||
|
4. **Testing configuration changes**: Using the Docker testing framework
|
||||||
|
|
||||||
|
## Code Organization Principles
|
||||||
|
|
||||||
|
1. **Modularity**: Keep scripts focused on one task
|
||||||
|
2. **Documentation**: Document all scripts and configurations
|
||||||
|
3. **Testing**: Ensure all changes are testable
|
||||||
|
4. **Cross-platform**: Support both Ubuntu and Debian where possible
|
||||||
|
|
||||||
|
## Security Practices
|
||||||
|
|
||||||
|
When suggesting security-related code:
|
||||||
|
|
||||||
|
1. **Permissions**:
|
||||||
|
- Avoid running scripts as root unless necessary
|
||||||
|
- Use `sudo` for specific commands rather than entire scripts
|
||||||
|
- Set appropriate file permissions (e.g., `chmod 600` for sensitive files)
|
||||||
|
|
||||||
|
2. **Secret Management**:
|
||||||
|
- Never include hardcoded credentials in scripts
|
||||||
|
- Use environment variables or external secret management
|
||||||
|
- Add sensitive files to .gitignore
|
||||||
|
|
||||||
|
3. **Input Validation**:
|
||||||
|
- Validate and sanitize all user inputs
|
||||||
|
- Use quotes around variables to prevent word splitting and globbing
|
||||||
|
- Implement proper error handling for invalid inputs
|
||||||
|
|
||||||
|
4. **Network Security**:
|
||||||
|
- Verify URLs before downloading (`curl`/`wget`)
|
||||||
|
- Use HTTPS instead of HTTP when possible
|
||||||
|
- Validate checksums for downloaded packages
|
||||||
|
|
||||||
|
## Contribution Guidelines
|
||||||
|
|
||||||
|
For contributors and Copilot suggestions:
|
||||||
|
|
||||||
|
1. **Script Modifications**:
|
||||||
|
- Test all changes using the Docker testing framework
|
||||||
|
- Update documentation when adding new functionality
|
||||||
|
- Maintain backward compatibility when possible
|
||||||
|
|
||||||
|
2. **New Scripts**:
|
||||||
|
- Follow the established naming conventions
|
||||||
|
- Include a header with description, usage, and author
|
||||||
|
- Add appropriate documentation to the docs/ directory
|
||||||
|
- Add any new dependencies to setup/packages.list
|
||||||
|
|
||||||
|
3. **Review Process**:
|
||||||
|
- Run tests before submitting changes
|
||||||
|
- Document what was changed and why
|
||||||
|
- Consider both Ubuntu and Debian compatibility
|
||||||
80
Dockerfile
Normal file
80
Dockerfile
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
# Dockerfile to test bootstrap.sh and setup.sh scripts in different environments
|
||||||
|
# This allows testing the setup process in isolated containers
|
||||||
|
|
||||||
|
# Ubuntu test environment
|
||||||
|
FROM ubuntu:24.04 as ubuntu-test
|
||||||
|
LABEL description="Ubuntu test environment for shell setup scripts"
|
||||||
|
|
||||||
|
# Install minimal dependencies needed to run the test
|
||||||
|
ENV TZ=America/New_York
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=1
|
||||||
|
|
||||||
|
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone \
|
||||||
|
&& apt-get update && apt-get install -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" -y curl git sudo wget
|
||||||
|
|
||||||
|
# Pre-install cowsay and lolcat packages for testing
|
||||||
|
RUN apt-get update && apt-get install -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" -y cowsay lolcat
|
||||||
|
|
||||||
|
# Create logs directory with proper permissions
|
||||||
|
RUN mkdir -p /logs && chmod -R 777 /logs
|
||||||
|
|
||||||
|
# Create a test user with sudo permissions
|
||||||
|
RUN useradd -ms /bin/bash testuser && \
|
||||||
|
echo "testuser ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/testuser
|
||||||
|
|
||||||
|
USER testuser
|
||||||
|
WORKDIR /home/testuser
|
||||||
|
|
||||||
|
# Create directory structure for shell setup
|
||||||
|
RUN mkdir -p /home/testuser/shell/setup
|
||||||
|
|
||||||
|
# Copy test script, startup script, and packages.list
|
||||||
|
COPY --chown=testuser:testuser test-setup.sh /home/testuser/
|
||||||
|
COPY --chown=testuser:testuser startup.sh /home/testuser/
|
||||||
|
COPY --chown=testuser:testuser setup/packages.list /home/testuser/shell/setup/
|
||||||
|
|
||||||
|
# Make scripts executable
|
||||||
|
RUN chmod +x /home/testuser/test-setup.sh
|
||||||
|
RUN chmod +x /home/testuser/startup.sh
|
||||||
|
|
||||||
|
CMD ["/bin/bash", "-c", "./startup.sh"]
|
||||||
|
|
||||||
|
# Debian test environment
|
||||||
|
FROM debian:12 as debian-test
|
||||||
|
LABEL description="Debian test environment for shell setup scripts"
|
||||||
|
|
||||||
|
# Install minimal dependencies needed to run the test
|
||||||
|
ENV TZ=America/New_York
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
ARG APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=1
|
||||||
|
|
||||||
|
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone \
|
||||||
|
&& apt-get update && apt-get install -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" -y curl git sudo wget
|
||||||
|
|
||||||
|
# Pre-install cowsay and lolcat packages for testing
|
||||||
|
RUN apt-get update && apt-get install -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" -y cowsay lolcat
|
||||||
|
|
||||||
|
# Create logs directory with proper permissions
|
||||||
|
RUN mkdir -p /logs && chmod -R 777 /logs
|
||||||
|
|
||||||
|
# Create a test user with sudo permissions
|
||||||
|
RUN useradd -ms /bin/bash testuser && \
|
||||||
|
echo "testuser ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/testuser
|
||||||
|
|
||||||
|
USER testuser
|
||||||
|
WORKDIR /home/testuser
|
||||||
|
|
||||||
|
# Create directory structure for shell setup
|
||||||
|
RUN mkdir -p /home/testuser/shell/setup
|
||||||
|
|
||||||
|
# Copy test script, startup script, and packages.list
|
||||||
|
COPY --chown=testuser:testuser test-setup.sh /home/testuser/
|
||||||
|
COPY --chown=testuser:testuser startup.sh /home/testuser/
|
||||||
|
COPY --chown=testuser:testuser setup/packages.list /home/testuser/shell/setup/
|
||||||
|
|
||||||
|
# Make scripts executable
|
||||||
|
RUN chmod +x /home/testuser/test-setup.sh
|
||||||
|
RUN chmod +x /home/testuser/startup.sh
|
||||||
|
|
||||||
|
CMD ["/bin/bash", "-c", "./startup.sh"]
|
||||||
55
README.md
55
README.md
@@ -14,6 +14,7 @@ This repository contains various shell scripts for managing media-related tasks
|
|||||||
- [Plex Backup Script Documentation](./docs/plex-backup.md): Detailed documentation for the `backup-plex.sh` script.
|
- [Plex Backup Script Documentation](./docs/plex-backup.md): Detailed documentation for the `backup-plex.sh` script.
|
||||||
- [Plex Management Script Documentation](./docs/plex-management.md): Detailed documentation for the `plex.sh` script.
|
- [Plex Management Script Documentation](./docs/plex-management.md): Detailed documentation for the `plex.sh` script.
|
||||||
- [Folder Metrics Script Documentation](./docs/folder-metrics.md): Detailed documentation for the `folder-metrics.sh` script.
|
- [Folder Metrics Script Documentation](./docs/folder-metrics.md): Detailed documentation for the `folder-metrics.sh` script.
|
||||||
|
- [Testing Framework Documentation](./docs/testing.md): Detailed documentation for the Docker-based testing system.
|
||||||
|
|
||||||
## Dotfiles
|
## Dotfiles
|
||||||
|
|
||||||
@@ -25,6 +26,60 @@ curl -fsSL https://raw.githubusercontent.com/acedanger/shell/main/bootstrap.sh |
|
|||||||
|
|
||||||
For more information about the dotfiles, see [Dotfiles README](./dotfiles/README.md).
|
For more information about the dotfiles, see [Dotfiles README](./dotfiles/README.md).
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
This repository includes Docker-based testing to validate the setup process across different environments:
|
||||||
|
|
||||||
|
- **test-setup.sh**: Script that validates the bootstrap and setup process
|
||||||
|
- **run-docker-tests.sh**: Runner script that executes tests in Docker containers
|
||||||
|
- **Dockerfile**: Defines test environments (Ubuntu, Debian)
|
||||||
|
|
||||||
|
### Running Tests
|
||||||
|
|
||||||
|
Test your setup in isolated Docker containers with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test in Ubuntu container
|
||||||
|
./run-docker-tests.sh ubuntu
|
||||||
|
|
||||||
|
# Test in Debian container
|
||||||
|
./run-docker-tests.sh debian
|
||||||
|
|
||||||
|
# Run full bootstrap test in Ubuntu
|
||||||
|
./run-docker-tests.sh full-ubuntu
|
||||||
|
|
||||||
|
# Run full bootstrap test in Debian
|
||||||
|
./run-docker-tests.sh full-debian
|
||||||
|
|
||||||
|
# Test in both Ubuntu and Debian
|
||||||
|
./run-docker-tests.sh all
|
||||||
|
```
|
||||||
|
|
||||||
|
#### When to Use Each Testing Option
|
||||||
|
|
||||||
|
- **Use `./run-docker-tests.sh ubuntu` or `./run-docker-tests.sh debian`** when you want to:
|
||||||
|
- Quickly validate if packages in packages.list are available and installed
|
||||||
|
- Test if your test-setup.sh script is working correctly
|
||||||
|
- Check for issues with specific components without performing a full setup
|
||||||
|
|
||||||
|
- **Use `./run-docker-tests.sh full-ubuntu` or `./run-docker-tests.sh full-debian`** when you want to:
|
||||||
|
- Test the complete bootstrap installation process end-to-end
|
||||||
|
- Validate that all installation steps work correctly on a fresh system
|
||||||
|
- Simulate what users will experience when running the bootstrap script
|
||||||
|
|
||||||
|
- **Use `./run-docker-tests.sh all`** when you want to:
|
||||||
|
- Ensure your test-setup.sh works across both Ubuntu and Debian
|
||||||
|
- Run comprehensive checks before committing changes
|
||||||
|
|
||||||
|
The test environment checks:
|
||||||
|
- Package availability and installation
|
||||||
|
- Core components (git, curl, wget, etc.)
|
||||||
|
- Additional packages from `setup/packages.list`
|
||||||
|
- Oh My Zsh and plugin installation
|
||||||
|
- Dotfile symlinks
|
||||||
|
|
||||||
|
Tests will continue even when some packages fail to install, reporting all issues in a comprehensive summary.
|
||||||
|
|
||||||
# plex.sh
|
# plex.sh
|
||||||
|
|
||||||
This script is used to manage the Plex Media Server service on a systemd-based Linux distribution. It provides the following functionalities:
|
This script is used to manage the Plex Media Server service on a systemd-based Linux distribution. It provides the following functionalities:
|
||||||
|
|||||||
225
debian-patches.sh
Executable file
225
debian-patches.sh
Executable file
@@ -0,0 +1,225 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# This script applies Debian-specific patches to the setup scripts
|
||||||
|
# It should be run before bootstrap.sh on Debian systems
|
||||||
|
|
||||||
|
set -e # Exit on error
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[0;33m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Check if running on Debian
|
||||||
|
if [ -f /etc/os-release ]; then
|
||||||
|
. /etc/os-release
|
||||||
|
if [[ "$ID" == "debian" ]]; then
|
||||||
|
echo -e "${BLUE}Running on Debian $VERSION_ID ($PRETTY_NAME)${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}This script is intended for Debian systems but detected $PRETTY_NAME${NC}"
|
||||||
|
echo -e "${YELLOW}Continue anyway? [y/N]${NC}"
|
||||||
|
read -r response
|
||||||
|
if [[ ! "$response" =~ ^([yY][eE][sS]|[yY])$ ]]; then
|
||||||
|
echo -e "${RED}Exiting...${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create a packages mapping file
|
||||||
|
PATCH_DIR="$HOME/.shell-debian-patches"
|
||||||
|
mkdir -p "$PATCH_DIR"
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Creating Debian package name mappings...${NC}"
|
||||||
|
cat > "$PATCH_DIR/debian-packages.map" << 'EOF'
|
||||||
|
# Debian package name mappings
|
||||||
|
# format: ubuntu-name|debian-name
|
||||||
|
|
||||||
|
# bat is called batcat on Debian
|
||||||
|
bat|batcat
|
||||||
|
|
||||||
|
# Keep original names for packages that are the same
|
||||||
|
git|git
|
||||||
|
python3|python3
|
||||||
|
wget|wget
|
||||||
|
curl|curl
|
||||||
|
cowsay|cowsay
|
||||||
|
lolcat|lolcat
|
||||||
|
fzf|fzf
|
||||||
|
zsh|zsh
|
||||||
|
|
||||||
|
# Different package names for Nala source
|
||||||
|
software-properties-common|software-properties-common
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Create a patching script that will be called by setup.sh
|
||||||
|
echo -e "${YELLOW}Creating Debian patching script...${NC}"
|
||||||
|
cat > "$PATCH_DIR/apply-debian-patches.sh" << 'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Script to apply Debian-specific patches to the setup process
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[0;33m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
PATCH_DIR="$HOME/.shell-debian-patches"
|
||||||
|
|
||||||
|
# Check if running on Debian
|
||||||
|
if [ -f /etc/os-release ]; then
|
||||||
|
. /etc/os-release
|
||||||
|
if [[ "$ID" != "debian" ]]; then
|
||||||
|
echo -e "${YELLOW}Not running on Debian, skipping patches${NC}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${BLUE}Applying Debian-specific patches...${NC}"
|
||||||
|
|
||||||
|
# Function to map package names from Ubuntu to Debian
|
||||||
|
map_package() {
|
||||||
|
local ubuntu_pkg="$1"
|
||||||
|
local debian_pkg
|
||||||
|
|
||||||
|
# Look for the package in the mapping file
|
||||||
|
if [ -f "$PATCH_DIR/debian-packages.map" ]; then
|
||||||
|
debian_pkg=$(grep -v "^#" "$PATCH_DIR/debian-packages.map" | grep "^$ubuntu_pkg|" | cut -d'|' -f2)
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If not found or empty, use the original name
|
||||||
|
if [ -z "$debian_pkg" ]; then
|
||||||
|
debian_pkg="$ubuntu_pkg"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$debian_pkg"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Patch the packages.list file if it exists
|
||||||
|
if [ -f "$HOME/shell/setup/packages.list" ]; then
|
||||||
|
echo -e "${YELLOW}Patching packages.list for Debian compatibility...${NC}"
|
||||||
|
|
||||||
|
# Create a temporary patched file
|
||||||
|
temp_file=$(mktemp)
|
||||||
|
|
||||||
|
# Process each line
|
||||||
|
while IFS= read -r line; do
|
||||||
|
# Skip comments and empty lines
|
||||||
|
if [[ "$line" =~ ^//.*$ ]] || [[ -z "$line" ]]; then
|
||||||
|
echo "$line" >> "$temp_file"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Map the package name
|
||||||
|
debian_pkg=$(map_package "$line")
|
||||||
|
echo "$debian_pkg" >> "$temp_file"
|
||||||
|
|
||||||
|
done < "$HOME/shell/setup/packages.list"
|
||||||
|
|
||||||
|
# Backup original and replace with patched version
|
||||||
|
cp "$HOME/shell/setup/packages.list" "$HOME/shell/setup/packages.list.orig"
|
||||||
|
mv "$temp_file" "$HOME/shell/setup/packages.list"
|
||||||
|
|
||||||
|
echo -e "${GREEN}Patched packages.list for Debian compatibility${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Other Debian-specific patches can be added here...
|
||||||
|
|
||||||
|
# Add contrib and non-free repositories if they're not already enabled
|
||||||
|
echo -e "${YELLOW}Checking Debian repositories...${NC}"
|
||||||
|
if ! grep -q "contrib" /etc/apt/sources.list; then
|
||||||
|
echo -e "${YELLOW}Adding contrib and non-free repositories...${NC}"
|
||||||
|
# Create a backup of the original sources.list
|
||||||
|
sudo cp /etc/apt/sources.list /etc/apt/sources.list.backup
|
||||||
|
|
||||||
|
# Add contrib and non-free to each deb line
|
||||||
|
sudo sed -i 's/main$/main contrib non-free non-free-firmware/g' /etc/apt/sources.list
|
||||||
|
|
||||||
|
echo -e "${GREEN}Added contrib and non-free repositories${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}Debian patches applied successfully${NC}"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x "$PATCH_DIR/apply-debian-patches.sh"
|
||||||
|
|
||||||
|
# Create a wrapper script for bootstrap.sh
|
||||||
|
echo -e "${YELLOW}Creating Debian bootstrap wrapper...${NC}"
|
||||||
|
cat > "$HOME/debian-bootstrap.sh" << 'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Debian wrapper for bootstrap.sh
|
||||||
|
|
||||||
|
set -e # Exit on error
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[0;33m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
PATCH_DIR="$HOME/.shell-debian-patches"
|
||||||
|
|
||||||
|
# Apply Debian patches first
|
||||||
|
if [ -x "$PATCH_DIR/apply-debian-patches.sh" ]; then
|
||||||
|
echo -e "${BLUE}Applying Debian patches before bootstrap...${NC}"
|
||||||
|
"$PATCH_DIR/apply-debian-patches.sh"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Download and run the bootstrap script
|
||||||
|
echo -e "${BLUE}Running bootstrap script...${NC}"
|
||||||
|
curl -s https://raw.githubusercontent.com/acedanger/shell/main/bootstrap.sh | bash
|
||||||
|
|
||||||
|
# Apply patches again after bootstrap (in case packages.list was just downloaded)
|
||||||
|
if [ -x "$PATCH_DIR/apply-debian-patches.sh" ]; then
|
||||||
|
echo -e "${BLUE}Applying Debian patches after bootstrap...${NC}"
|
||||||
|
"$PATCH_DIR/apply-debian-patches.sh"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}Debian bootstrap completed!${NC}"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x "$HOME/debian-bootstrap.sh"
|
||||||
|
|
||||||
|
# Add a hook to setup.sh to call the Debian patch script
|
||||||
|
echo -e "${YELLOW}Creating setup.sh hook for Debian...${NC}"
|
||||||
|
cat > "$PATCH_DIR/setup-hook.sh" << 'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Hook to modify setup.sh to call Debian patches
|
||||||
|
|
||||||
|
if [ -f /etc/os-release ]; then
|
||||||
|
. /etc/os-release
|
||||||
|
if [[ "$ID" == "debian" ]]; then
|
||||||
|
# Modify setup.sh to call Debian patches
|
||||||
|
if [ -f "$HOME/shell/setup/setup.sh" ]; then
|
||||||
|
# Check if the patch hasn't been applied yet
|
||||||
|
if ! grep -q "apply-debian-patches" "$HOME/shell/setup/setup.sh"; then
|
||||||
|
# Add call to Debian patch script right after the shebang
|
||||||
|
sed -i '2i\
|
||||||
|
# Apply Debian patches if available\
|
||||||
|
if [ -x "$HOME/.shell-debian-patches/apply-debian-patches.sh" ]; then\
|
||||||
|
echo -e "${YELLOW}Applying Debian-specific patches...${NC}"\
|
||||||
|
"$HOME/.shell-debian-patches/apply-debian-patches.sh"\
|
||||||
|
fi' "$HOME/shell/setup/setup.sh"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x "$PATCH_DIR/setup-hook.sh"
|
||||||
|
|
||||||
|
echo -e "${GREEN}Debian compatibility patch has been set up!${NC}"
|
||||||
|
echo -e "${YELLOW}To bootstrap your Debian system, run:${NC}"
|
||||||
|
echo -e " ${BLUE}bash ~/debian-bootstrap.sh${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "${YELLOW}This has created:${NC}"
|
||||||
|
echo -e "1. Package name mappings for Debian"
|
||||||
|
echo -e "2. A patch script for Debian-specific adjustments"
|
||||||
|
echo -e "3. A Debian-specific bootstrap wrapper"
|
||||||
83
docs/testing-fixes.md
Normal file
83
docs/testing-fixes.md
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
# Docker-based Testing Framework Improvements
|
||||||
|
|
||||||
|
This document outlines the improvements made to the Docker-based testing framework for validating shell scripts and dotfiles across different environments.
|
||||||
|
|
||||||
|
## Issues Fixed
|
||||||
|
|
||||||
|
### 1. `local` Keyword Usage Outside Function
|
||||||
|
|
||||||
|
Fixed a syntax error where the `local` keyword was used outside of a function context:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Before (incorrect):
|
||||||
|
for pkg in $packages; do
|
||||||
|
local actual_pkg=$(get_package_name "$pkg")
|
||||||
|
# ...
|
||||||
|
done
|
||||||
|
|
||||||
|
# After (correct):
|
||||||
|
for pkg in $packages; do
|
||||||
|
actual_pkg=$(get_package_name "$pkg")
|
||||||
|
# ...
|
||||||
|
done
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Log Directory Handling
|
||||||
|
|
||||||
|
Enhanced log directory handling to ensure proper permissions and fallback mechanisms:
|
||||||
|
|
||||||
|
- Added better error handling for log directory creation and permissions
|
||||||
|
- Added validation to verify write permissions before proceeding
|
||||||
|
- Implemented fallback to /tmp if host volume mounting fails
|
||||||
|
- Added debugging information when log operations fail
|
||||||
|
|
||||||
|
### 3. Package Verification
|
||||||
|
|
||||||
|
Improved package detection, especially for packages like `cowsay` and `lolcat` that are typically installed in `/usr/games/`:
|
||||||
|
|
||||||
|
- Enhanced `test_package()` function to check in common alternate locations
|
||||||
|
- Added specific handling for packages that may be installed with different paths
|
||||||
|
- Added detailed debugging output for problematic packages
|
||||||
|
|
||||||
|
### 4. Docker Container Configuration
|
||||||
|
|
||||||
|
Improved the Docker container configuration for more reliable testing:
|
||||||
|
|
||||||
|
- Added proper volume mounting with explicit read/write permissions
|
||||||
|
- Added timestamp consistency between host and container
|
||||||
|
- Added container type labels to log files for better tracking
|
||||||
|
- Enhanced error detection for volume mounting issues
|
||||||
|
|
||||||
|
## Implementation Details
|
||||||
|
|
||||||
|
### 1. Enhanced Logging System
|
||||||
|
|
||||||
|
- Timestamps are now synchronized between host and container
|
||||||
|
- Log file names include container type (ubuntu/debian) for clarity
|
||||||
|
- Added validation to confirm logs are properly saved to host
|
||||||
|
|
||||||
|
### 2. Container Environment Setup
|
||||||
|
|
||||||
|
- Improved `startup.sh` with better diagnostics before running tests
|
||||||
|
- Added permissions verification for mounted volumes
|
||||||
|
- Added write tests to confirm permissions are correctly set
|
||||||
|
|
||||||
|
### 3. Test Framework Improvements
|
||||||
|
|
||||||
|
- Improved error handling for better diagnostics
|
||||||
|
- Enhanced reporting for package detection issues
|
||||||
|
- Better isolation between test iterations
|
||||||
|
|
||||||
|
## Running Tests
|
||||||
|
|
||||||
|
To run tests with the improved framework:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test in Ubuntu container
|
||||||
|
./run-docker-tests.sh ubuntu
|
||||||
|
|
||||||
|
# Test in Debian container
|
||||||
|
./run-docker-tests.sh debian
|
||||||
|
```
|
||||||
|
|
||||||
|
The logs will be saved in the `./logs` directory with filenames that include the timestamp and container type.
|
||||||
132
docs/testing.md
Normal file
132
docs/testing.md
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
# Shell Setup Testing Framework
|
||||||
|
|
||||||
|
This document describes the testing framework for validating the shell setup across different environments.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The testing framework consists of three main components:
|
||||||
|
|
||||||
|
1. **test-setup.sh**: The main test script that validates the bootstrap and setup process
|
||||||
|
2. **run-docker-tests.sh**: A runner script that executes tests in Docker containers
|
||||||
|
3. **Dockerfile**: Definition of test environments (Ubuntu and Debian)
|
||||||
|
|
||||||
|
## Testing Features
|
||||||
|
|
||||||
|
- **Cross-platform testing**: Test on both Ubuntu and Debian environments
|
||||||
|
- **Isolated environments**: All tests run in fresh Docker containers
|
||||||
|
- **Comprehensive validation**: Tests both the bootstrap and setup processes
|
||||||
|
- **Continuous testing**: Tests all packages regardless of individual failures
|
||||||
|
- **Detailed reporting**: Summary of all successful and failed components
|
||||||
|
|
||||||
|
## How Testing Works
|
||||||
|
|
||||||
|
### The Docker Test Environment
|
||||||
|
|
||||||
|
The `Dockerfile` defines two testing environments:
|
||||||
|
- **ubuntu-test**: Based on Ubuntu 24.04
|
||||||
|
- **debian-test**: Based on Debian 12
|
||||||
|
|
||||||
|
Each environment:
|
||||||
|
1. Installs minimal dependencies (curl, git, sudo, wget)
|
||||||
|
2. Creates a test user with sudo permissions
|
||||||
|
3. Sets up the directory structure for testing
|
||||||
|
4. Copies the test script and packages list
|
||||||
|
5. Runs the test script when the container starts
|
||||||
|
|
||||||
|
### The Test Script (test-setup.sh)
|
||||||
|
|
||||||
|
The test script validates:
|
||||||
|
|
||||||
|
1. **Script Syntax**: Checks if bootstrap.sh and setup.sh have valid syntax
|
||||||
|
2. **Core Tools**: Verifies git, curl, wget are available
|
||||||
|
3. **Package Availability**: Checks if packages in packages.list are available in repositories
|
||||||
|
4. **Package Installation**: Tests if each package is installed
|
||||||
|
5. **Shell Setup**: Validates Oh My Zsh and plugin installation
|
||||||
|
6. **Dotfiles**: Checks if dotfiles are properly symlinked
|
||||||
|
|
||||||
|
The script tracks all missing or misconfigured components and provides a summary at the end, including suggestions for fixing issues.
|
||||||
|
|
||||||
|
### Test Runner (run-docker-tests.sh)
|
||||||
|
|
||||||
|
The runner script provides several test modes:
|
||||||
|
|
||||||
|
- **ubuntu**: Run test on Ubuntu container
|
||||||
|
- **debian**: Run test on Debian container
|
||||||
|
- **full-ubuntu**: Run full bootstrap test on Ubuntu
|
||||||
|
- **full-debian**: Run full bootstrap test on Debian
|
||||||
|
- **all**: Run tests on both Ubuntu and Debian
|
||||||
|
|
||||||
|
## Testing Without Stopping on Failures
|
||||||
|
|
||||||
|
A key feature is the ability to test all packages in `packages.list` without stopping at the first failure. This ensures:
|
||||||
|
|
||||||
|
1. Complete coverage of all requirements
|
||||||
|
2. Comprehensive reporting of all issues
|
||||||
|
3. Better debugging experience when multiple components need attention
|
||||||
|
|
||||||
|
## Running Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test on Ubuntu
|
||||||
|
./run-docker-tests.sh ubuntu
|
||||||
|
|
||||||
|
# Test on Debian
|
||||||
|
./run-docker-tests.sh debian
|
||||||
|
|
||||||
|
# Full bootstrap test on Ubuntu
|
||||||
|
./run-docker-tests.sh full-ubuntu
|
||||||
|
|
||||||
|
# Full bootstrap test on Debian
|
||||||
|
./run-docker-tests.sh full-debian
|
||||||
|
|
||||||
|
# Test on both Ubuntu and Debian
|
||||||
|
./run-docker-tests.sh all
|
||||||
|
```
|
||||||
|
|
||||||
|
### Choosing the Right Test Option
|
||||||
|
|
||||||
|
The testing framework offers different options for different testing needs:
|
||||||
|
|
||||||
|
| If you want to... | Use this command | Why |
|
||||||
|
|-------------------|------------------|-----|
|
||||||
|
| Quickly check if specific packages are available | `./run-docker-tests.sh ubuntu` or `debian` | Fast validation of packages without full installation |
|
||||||
|
| Test changes to the test-setup.sh script | `./run-docker-tests.sh ubuntu` or `debian` | Executes only the test script in a clean environment |
|
||||||
|
| Validate a fix for a package installation issue | `./run-docker-tests.sh ubuntu` or `debian` | Tests package availability and installation |
|
||||||
|
| Test the complete user experience | `./run-docker-tests.sh full-ubuntu` or `full-debian` | Executes the actual bootstrap script like a real user would |
|
||||||
|
| Ensure bootstrap.sh works correctly | `./run-docker-tests.sh full-ubuntu` or `full-debian` | Tests the entire installation process from scratch |
|
||||||
|
| Verify cross-platform compatibility | `./run-docker-tests.sh all` | Tests on both supported platforms |
|
||||||
|
| Before pushing changes to main | `./run-docker-tests.sh all` and both full tests | Complete validation across environments |
|
||||||
|
|
||||||
|
### Key Differences
|
||||||
|
|
||||||
|
**Standard Tests** (`ubuntu`, `debian`):
|
||||||
|
- Use the Docker targets defined in the main Dockerfile
|
||||||
|
- Run the `test-setup.sh` script to check components
|
||||||
|
- Faster execution, focused on component validation
|
||||||
|
- Don't perform the actual bootstrap installation
|
||||||
|
|
||||||
|
**Full Tests** (`full-ubuntu`, `full-debian`):
|
||||||
|
- Create a temporary Dockerfile for comprehensive testing
|
||||||
|
- Execute the bootstrap script directly from GitHub
|
||||||
|
- Complete end-to-end testing of the actual installation process
|
||||||
|
- Simulate the real user experience
|
||||||
|
|
||||||
|
## Test Output
|
||||||
|
|
||||||
|
The test provides:
|
||||||
|
|
||||||
|
1. A color-coded console output showing success/failure of each component
|
||||||
|
2. A list of missing packages at the end
|
||||||
|
3. A detailed log file with all test results (saved to /tmp)
|
||||||
|
4. Suggestions for fixing detected issues
|
||||||
|
|
||||||
|
## Adding New Tests
|
||||||
|
|
||||||
|
To add new package tests:
|
||||||
|
1. Add the package name to `setup/packages.list`
|
||||||
|
2. The test framework will automatically validate its availability and installation
|
||||||
|
|
||||||
|
For more complex components:
|
||||||
|
1. Add a new test function in `test-setup.sh`
|
||||||
|
2. Call the function in the main testing sequence
|
||||||
|
3. Increment the error counter if the test fails
|
||||||
@@ -93,6 +93,41 @@ curl -fsSL https://raw.githubusercontent.com/acedanger/shell/main/bootstrap.sh |
|
|||||||
- Configure zoxide for better navigation
|
- Configure zoxide for better navigation
|
||||||
- Install and configure Git
|
- Install and configure Git
|
||||||
|
|
||||||
|
## Testing
|
||||||
|
|
||||||
|
The repository includes a comprehensive testing framework to validate the shell setup process across different environments.
|
||||||
|
|
||||||
|
### Docker-Based Testing
|
||||||
|
|
||||||
|
Tests are run in isolated Docker containers to ensure consistent, repeatable validation:
|
||||||
|
- **Ubuntu 24.04 environment**: Tests compatibility with the latest Ubuntu LTS
|
||||||
|
- **Debian 12 environment**: Tests compatibility with Debian Stable
|
||||||
|
|
||||||
|
### Test Coverage
|
||||||
|
|
||||||
|
The tests validate:
|
||||||
|
- Package availability in repositories
|
||||||
|
- Successful installation of all packages in `packages.list`
|
||||||
|
- Oh My Zsh installation
|
||||||
|
- Zsh plugin installation
|
||||||
|
- Dotfile symlinking
|
||||||
|
- NVM and Node.js setup
|
||||||
|
|
||||||
|
### Running Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Test your setup on Ubuntu
|
||||||
|
./run-docker-tests.sh ubuntu
|
||||||
|
|
||||||
|
# Test your setup on Debian
|
||||||
|
./run-docker-tests.sh debian
|
||||||
|
|
||||||
|
# Run a full bootstrap test (including installation)
|
||||||
|
./run-docker-tests.sh full-ubuntu
|
||||||
|
```
|
||||||
|
|
||||||
|
For more details on testing, see [Testing Documentation](../docs/testing.md).
|
||||||
|
|
||||||
## Manual Steps
|
## Manual Steps
|
||||||
|
|
||||||
If you need to manually set up aliases:
|
If you need to manually set up aliases:
|
||||||
|
|||||||
237
run-docker-tests.sh
Executable file
237
run-docker-tests.sh
Executable file
@@ -0,0 +1,237 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Script to run setup tests in Docker containers
|
||||||
|
# This allows testing the setup process in isolated environments
|
||||||
|
|
||||||
|
set -e # Exit on error
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[0;33m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Check if Docker is installed and working
|
||||||
|
if ! command -v docker &> /dev/null; then
|
||||||
|
echo -e "${RED}Error: Docker is not installed. Please install Docker to run tests.${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create logs directory at the top level to ensure it exists
|
||||||
|
LOGS_DIR="$(pwd)/logs"
|
||||||
|
if [ ! -d "$LOGS_DIR" ]; then
|
||||||
|
echo -e "${YELLOW}Creating logs directory at: $LOGS_DIR${NC}"
|
||||||
|
mkdir -p "$LOGS_DIR" || {
|
||||||
|
echo -e "${RED}Failed to create logs directory! Check permissions.${NC}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}Logs directory already exists at: $LOGS_DIR${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ensure the logs directory is writable
|
||||||
|
if [ ! -w "$LOGS_DIR" ]; then
|
||||||
|
echo -e "${YELLOW}Setting permissions on logs directory...${NC}"
|
||||||
|
chmod -R 777 "$LOGS_DIR" || {
|
||||||
|
echo -e "${RED}Failed to set write permissions on logs directory!${NC}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create a test file to verify we can write to it
|
||||||
|
if touch "$LOGS_DIR/test_file" && rm "$LOGS_DIR/test_file"; then
|
||||||
|
echo -e "${GREEN}Log directory is writable and ready for use${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}Cannot write to logs directory even after setting permissions!${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if Docker is running
|
||||||
|
if ! docker info &>/dev/null; then
|
||||||
|
echo -e "${YELLOW}Warning: Docker appears to be installed but not running or not properly configured.${NC}"
|
||||||
|
echo -e "${YELLOW}If using WSL2, ensure Docker Desktop is running with WSL integration enabled.${NC}"
|
||||||
|
echo -e "${YELLOW}Would you like to run the local test instead? [Y/n]${NC}"
|
||||||
|
read -r response
|
||||||
|
if [[ "$response" =~ ^([nN][oO]|[nN])$ ]]; then
|
||||||
|
echo -e "${RED}Exiting...${NC}"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo -e "${BLUE}Running local test instead...${NC}"
|
||||||
|
./test-setup.sh
|
||||||
|
exit $?
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build and run Ubuntu test container
|
||||||
|
run_ubuntu_test() {
|
||||||
|
echo -e "\n${BLUE}=== Running test in Ubuntu container ===${NC}"
|
||||||
|
# Create the logs directory if it doesn't exist
|
||||||
|
local log_dir="$(pwd)/logs"
|
||||||
|
mkdir -p "$log_dir" || true
|
||||||
|
|
||||||
|
# Use sudo for chmod only if necessary
|
||||||
|
if [ ! -w "$log_dir" ]; then
|
||||||
|
echo -e "${YELLOW}Attempting to fix permissions with sudo...${NC}"
|
||||||
|
sudo chmod -R 777 "$log_dir" 2>/dev/null || {
|
||||||
|
echo -e "${YELLOW}Could not change permissions with sudo, continuing anyway...${NC}"
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Logs will be saved to: $log_dir${NC}"
|
||||||
|
echo -e "${YELLOW}Building Ubuntu test container...${NC}"
|
||||||
|
docker build --target ubuntu-test -t shell-test:ubuntu .
|
||||||
|
|
||||||
|
echo -e "${GREEN}Running tests with package installation...${NC}"
|
||||||
|
|
||||||
|
# Create a timestamp for this test run
|
||||||
|
TEST_TIMESTAMP=$(date +"%Y%m%d-%H%M%S")
|
||||||
|
echo -e "${YELLOW}Test run timestamp: $TEST_TIMESTAMP${NC}"
|
||||||
|
|
||||||
|
# Run container with proper volume mount and add environment variable for timestamp
|
||||||
|
docker run --rm -it \
|
||||||
|
-e TEST_TIMESTAMP="$TEST_TIMESTAMP" \
|
||||||
|
-e CONTAINER_TYPE="ubuntu" \
|
||||||
|
-v "$log_dir:/logs:z" \
|
||||||
|
shell-test:ubuntu
|
||||||
|
|
||||||
|
# Check if logs were created
|
||||||
|
if ls "$log_dir"/setup-test-*"$TEST_TIMESTAMP"* &>/dev/null 2>&1; then
|
||||||
|
echo -e "${GREEN}Test logs successfully created in host directory${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}Warning: No log files found matching timestamp $TEST_TIMESTAMP${NC}"
|
||||||
|
echo -e "${YELLOW}This may indicate issues with volume mounting or permissions${NC}"
|
||||||
|
echo -e "${YELLOW}Contents of log directory:${NC}"
|
||||||
|
ls -la "$log_dir" || echo "Cannot list directory contents"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${BLUE}Test completed. Check logs in $log_dir directory${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Build and run Debian test container
|
||||||
|
run_debian_test() {
|
||||||
|
echo -e "\n${BLUE}=== Running test in Debian container ===${NC}"
|
||||||
|
# Create the logs directory if it doesn't exist
|
||||||
|
local log_dir="$(pwd)/logs"
|
||||||
|
mkdir -p "$log_dir" || true
|
||||||
|
|
||||||
|
# Use sudo for chmod only if necessary
|
||||||
|
if [ ! -w "$log_dir" ]; then
|
||||||
|
echo -e "${YELLOW}Attempting to fix permissions with sudo...${NC}"
|
||||||
|
sudo chmod -R 777 "$log_dir" 2>/dev/null || {
|
||||||
|
echo -e "${YELLOW}Could not change permissions with sudo, continuing anyway...${NC}"
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Logs will be saved to: $log_dir${NC}"
|
||||||
|
echo -e "${YELLOW}Building Debian test container...${NC}"
|
||||||
|
docker build --target debian-test -t shell-test:debian .
|
||||||
|
|
||||||
|
echo -e "${GREEN}Running tests with package installation...${NC}"
|
||||||
|
|
||||||
|
# Create a timestamp for this test run
|
||||||
|
TEST_TIMESTAMP=$(date +"%Y%m%d-%H%M%S")
|
||||||
|
echo -e "${YELLOW}Test run timestamp: $TEST_TIMESTAMP${NC}"
|
||||||
|
|
||||||
|
# Run container with proper volume mount and add environment variable for timestamp
|
||||||
|
docker run --rm -it \
|
||||||
|
-e TEST_TIMESTAMP="$TEST_TIMESTAMP" \
|
||||||
|
-e CONTAINER_TYPE="debian" \
|
||||||
|
-v "$log_dir:/logs:z" \
|
||||||
|
shell-test:debian
|
||||||
|
|
||||||
|
# Check if logs were created
|
||||||
|
if ls "$log_dir"/setup-test-*"$TEST_TIMESTAMP"* &>/dev/null 2>&1; then
|
||||||
|
echo -e "${GREEN}Test logs successfully created in host directory${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}Warning: No log files found matching timestamp $TEST_TIMESTAMP${NC}"
|
||||||
|
echo -e "${YELLOW}This may indicate issues with volume mounting or permissions${NC}"
|
||||||
|
echo -e "${YELLOW}Contents of log directory:${NC}"
|
||||||
|
ls -la "$log_dir" || echo "Cannot list directory contents"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${BLUE}Test completed. Check logs in $log_dir directory${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Full test with bootstrap script
|
||||||
|
run_full_test() {
|
||||||
|
local distro=$1
|
||||||
|
local tag_name=$(echo $distro | sed 's/:/-/g') # Replace colon with hyphen for tag
|
||||||
|
echo -e "\n${BLUE}=== Running full bootstrap test in $distro container ===${NC}"
|
||||||
|
|
||||||
|
# Create a Dockerfile for full test
|
||||||
|
cat > Dockerfile.fulltest <<EOF
|
||||||
|
FROM $distro
|
||||||
|
LABEL description="$distro full test environment for bootstrap.sh script"
|
||||||
|
|
||||||
|
# Install minimal dependencies needed to run the bootstrap
|
||||||
|
ENV TZ=America/New_York
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone \
|
||||||
|
&& apt-get update && apt-get install -y curl git sudo wget
|
||||||
|
|
||||||
|
# Create a test user with sudo permissions
|
||||||
|
RUN useradd -ms /bin/bash testuser && \\
|
||||||
|
echo "testuser ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/testuser
|
||||||
|
|
||||||
|
# Create directory structure for setup files
|
||||||
|
RUN mkdir -p /home/testuser/shell
|
||||||
|
|
||||||
|
# Copy test script for post-bootstrap validation
|
||||||
|
COPY --chown=testuser:testuser test-setup.sh /home/testuser/
|
||||||
|
|
||||||
|
# Copy entire repo structure to ensure we have all needed files
|
||||||
|
COPY --chown=testuser:testuser . /home/testuser/shell/
|
||||||
|
|
||||||
|
USER testuser
|
||||||
|
WORKDIR /home/testuser
|
||||||
|
|
||||||
|
# Make the script executable
|
||||||
|
RUN chmod +x /home/testuser/test-setup.sh
|
||||||
|
|
||||||
|
# Run tests before and after bootstrap to verify package installation
|
||||||
|
CMD ["/bin/bash", "-c", "echo -e '\\n\\nRunning pre-bootstrap tests...' && ./test-setup.sh && echo -e '\\n\\nRunning bootstrap...' && /home/testuser/shell/bootstrap.sh && echo -e '\\n\\nRunning post-bootstrap tests...' && ./test-setup.sh"]
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Build and run the container
|
||||||
|
# Create the logs directory if it doesn't exist
|
||||||
|
mkdir -p "$(pwd)/logs"
|
||||||
|
docker build -f Dockerfile.fulltest -t shell-full-test:$tag_name .
|
||||||
|
docker run --rm -it -v "$(pwd)/logs:/logs" shell-full-test:$tag_name
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
rm Dockerfile.fulltest
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parse command line arguments
|
||||||
|
case "$1" in
|
||||||
|
ubuntu)
|
||||||
|
run_ubuntu_test
|
||||||
|
;;
|
||||||
|
debian)
|
||||||
|
run_debian_test
|
||||||
|
;;
|
||||||
|
full-ubuntu)
|
||||||
|
run_full_test "ubuntu:24.04"
|
||||||
|
;;
|
||||||
|
full-debian)
|
||||||
|
run_full_test "debian:12"
|
||||||
|
;;
|
||||||
|
all)
|
||||||
|
run_ubuntu_test
|
||||||
|
run_debian_test
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo -e "${BLUE}Shell Setup Test Runner${NC}"
|
||||||
|
echo -e "Usage: $0 [option]"
|
||||||
|
echo -e "\nOptions:"
|
||||||
|
echo " ubuntu Run test on Ubuntu container (tests packages and components)"
|
||||||
|
echo " debian Run test on Debian container (tests packages and components)"
|
||||||
|
echo " full-ubuntu Run full bootstrap test on Ubuntu container (performs complete installation)"
|
||||||
|
echo " full-debian Run full bootstrap test on Debian container (performs complete installation)"
|
||||||
|
echo " all Run tests on both Ubuntu and Debian containers (component tests only)"
|
||||||
|
echo -e "\nExamples:"
|
||||||
|
echo -e " $0 ubuntu # Quick test for package availability"
|
||||||
|
echo -e " $0 full-debian # Test complete bootstrap installation"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
@@ -25,11 +25,21 @@ echo -e "${YELLOW}Setting up Nala repository...${NC}"
|
|||||||
if apt-cache show nala &>/dev/null; then
|
if apt-cache show nala &>/dev/null; then
|
||||||
echo -e "${GREEN}Nala is available in standard repositories${NC}"
|
echo -e "${GREEN}Nala is available in standard repositories${NC}"
|
||||||
else
|
else
|
||||||
# Try Ubuntu PPA as an alternative
|
echo -e "${YELLOW}Nala not found in standard repositories. Trying alternative installation methods...${NC}"
|
||||||
echo -e "${YELLOW}Trying Nala from Ubuntu PPA...${NC}"
|
|
||||||
sudo apt-get update
|
# Check Ubuntu version
|
||||||
sudo apt-get install -y software-properties-common
|
if grep -q "noble\|lunar\|mantic\|jammy" /etc/os-release; then
|
||||||
sudo add-apt-repository -y ppa:volitank/ppa
|
echo -e "${GREEN}Ubuntu $(grep VERSION_CODENAME /etc/os-release | cut -d= -f2) detected. Ensuring universe repository is enabled...${NC}"
|
||||||
|
# Make sure universe repository is enabled
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y software-properties-common
|
||||||
|
sudo add-apt-repository -y universe
|
||||||
|
else
|
||||||
|
# For older Ubuntu versions try to install directly
|
||||||
|
echo -e "${YELLOW}Older Ubuntu version detected. Trying to install Nala directly...${NC}"
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y software-properties-common
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Setup VS Code repository
|
# Setup VS Code repository
|
||||||
@@ -47,21 +57,49 @@ out=$(mktemp) && wget -nv -O$out https://cli.github.com/packages/githubcli-archi
|
|||||||
&& rm "$out" \
|
&& rm "$out" \
|
||||||
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
|
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null
|
||||||
|
|
||||||
# Update package lists
|
# Initialize USING_NALA variable
|
||||||
sudo apt update
|
USING_NALA=false
|
||||||
|
|
||||||
|
# Update package lists (ignoring previous errors)
|
||||||
|
echo -e "${YELLOW}Updating package lists...${NC}"
|
||||||
|
sudo apt update || echo -e "${YELLOW}Warning: apt update had some errors, but continuing...${NC}"
|
||||||
|
|
||||||
# Install Nala first
|
# Install Nala first
|
||||||
echo -e "${YELLOW}Installing Nala package manager...${NC}"
|
echo -e "${YELLOW}Installing Nala package manager...${NC}"
|
||||||
sudo apt-get install -y nala
|
if sudo apt-get install -y nala; then
|
||||||
|
USING_NALA=true
|
||||||
|
echo -e "${GREEN}Nala installed successfully!${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}Failed to install Nala. Continuing with standard apt...${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
# Configure Nala mirrors
|
# Configure Nala mirrors and install packages
|
||||||
echo -e "${YELLOW}Configuring Nala mirrors...${NC}"
|
if [ "$USING_NALA" = true ]; then
|
||||||
sudo nala fetch --auto --fetches 3
|
echo -e "${YELLOW}Configuring Nala mirrors...${NC}"
|
||||||
|
|
||||||
# Install remaining packages using Nala
|
# First, remove any existing nala sources list to avoid issues with invalid mirrors
|
||||||
echo -e "${YELLOW}Installing packages from packages.list...${NC}"
|
sudo rm -f /etc/apt/sources.list.d/nala-sources.list 2>/dev/null
|
||||||
mapfile -t pkgs < <(grep -v '^//' "$SCRIPT_DIR/packages.list" | grep -v -e '^$' -e '^nala$')
|
|
||||||
sudo nala install -y "${pkgs[@]}"
|
# Try to fetch mirrors with less aggressive settings
|
||||||
|
if ! sudo nala fetch --auto --fetches 1 --country auto; then
|
||||||
|
echo -e "${YELLOW}Mirror selection failed, continuing with system default mirrors...${NC}"
|
||||||
|
# Remove any potentially corrupted Nala sources
|
||||||
|
sudo rm -f /etc/apt/sources.list.d/nala-sources.list 2>/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install remaining packages using Nala
|
||||||
|
echo -e "${YELLOW}Installing packages from packages.list with Nala...${NC}"
|
||||||
|
mapfile -t pkgs < <(grep -v '^//' "$SCRIPT_DIR/packages.list" | grep -v -e '^$' -e '^nala$')
|
||||||
|
sudo nala install -y "${pkgs[@]}" || {
|
||||||
|
echo -e "${YELLOW}Nala install failed, falling back to apt...${NC}"
|
||||||
|
sudo apt-get install -y "${pkgs[@]}"
|
||||||
|
}
|
||||||
|
else
|
||||||
|
# Fall back to apt if Nala installation failed
|
||||||
|
echo -e "${YELLOW}Installing packages from packages.list with apt...${NC}"
|
||||||
|
mapfile -t pkgs < <(grep -v '^//' "$SCRIPT_DIR/packages.list" | grep -v -e '^$' -e '^nala$')
|
||||||
|
sudo apt-get install -y "${pkgs[@]}"
|
||||||
|
fi
|
||||||
|
|
||||||
# Install Zsh if not already installed
|
# Install Zsh if not already installed
|
||||||
echo -e "${YELLOW}Installing Zsh...${NC}"
|
echo -e "${YELLOW}Installing Zsh...${NC}"
|
||||||
|
|||||||
75
startup.sh
Executable file
75
startup.sh
Executable file
@@ -0,0 +1,75 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Startup script for Docker containers to ensure permissions and run tests
|
||||||
|
|
||||||
|
# Define colors for output
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[0;33m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
echo -e "${BLUE}=== Container Startup Checks ===${NC}"
|
||||||
|
|
||||||
|
# Display system information
|
||||||
|
echo -e "${BLUE}System information:${NC}"
|
||||||
|
if [ -f /etc/os-release ]; then
|
||||||
|
. /etc/os-release
|
||||||
|
echo -e "- OS: ${GREEN}$PRETTY_NAME${NC}"
|
||||||
|
else
|
||||||
|
echo -e "- OS: ${YELLOW}Unknown${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ensure packages.list is available
|
||||||
|
echo -e "${BLUE}Checking for packages.list:${NC}"
|
||||||
|
if [ -f "$HOME/shell/setup/packages.list" ]; then
|
||||||
|
echo -e "- packages.list: ${GREEN}Found${NC}"
|
||||||
|
# Count packages in list (excluding comments and empty lines)
|
||||||
|
pkg_count=$(grep -v '^//' "$HOME/shell/setup/packages.list" | grep -v -e '^$' | wc -l)
|
||||||
|
echo -e "- Package count: ${GREEN}$pkg_count packages${NC}"
|
||||||
|
else
|
||||||
|
echo -e "- packages.list: ${RED}Not found${NC}"
|
||||||
|
echo "Error: Could not find packages.list file. Tests will fail."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Ensure logs directory has correct permissions
|
||||||
|
echo -e "${BLUE}Setting up logs directory:${NC}"
|
||||||
|
if [ -d "/logs" ]; then
|
||||||
|
echo -e "- Logs directory: ${GREEN}Found${NC}"
|
||||||
|
|
||||||
|
# Check ownership and permissions
|
||||||
|
logs_owner=$(stat -c '%U:%G' /logs)
|
||||||
|
echo -e "- Current ownership: $logs_owner"
|
||||||
|
|
||||||
|
echo "- Setting permissions on /logs directory..."
|
||||||
|
sudo chown -R $(whoami):$(whoami) /logs 2>/dev/null || echo -e "${YELLOW}Failed to set ownership${NC}"
|
||||||
|
sudo chmod -R 777 /logs 2>/dev/null || echo -e "${YELLOW}Failed to set permissions${NC}"
|
||||||
|
|
||||||
|
# Verify permissions are correct
|
||||||
|
if [ -w "/logs" ]; then
|
||||||
|
echo -e "- Write permission: ${GREEN}OK${NC}"
|
||||||
|
|
||||||
|
# Create a test file to really verify we can write
|
||||||
|
if touch "/logs/test_file" 2>/dev/null; then
|
||||||
|
echo -e "- Test write: ${GREEN}Succeeded${NC}"
|
||||||
|
rm -f "/logs/test_file"
|
||||||
|
else
|
||||||
|
echo -e "- Test write: ${RED}Failed${NC}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "- Write permission: ${RED}Failed${NC}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "- Logs directory: ${YELLOW}Not found${NC}"
|
||||||
|
echo "- Creating /logs directory..."
|
||||||
|
if sudo mkdir -p /logs && sudo chown -R $(whoami):$(whoami) /logs && sudo chmod -R 777 /logs; then
|
||||||
|
echo -e "- Created logs directory with proper permissions: ${GREEN}Success${NC}"
|
||||||
|
else
|
||||||
|
echo -e "- Creating logs directory: ${RED}Failed${NC}"
|
||||||
|
echo "Warning: Logs will be saved inside container only"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${BLUE}=== Starting Test Script ===${NC}"
|
||||||
|
# Run the test script
|
||||||
|
./test-setup.sh
|
||||||
764
test-setup.sh
Executable file
764
test-setup.sh
Executable file
@@ -0,0 +1,764 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Script to test bootstrap.sh and setup.sh scripts in different environments
|
||||||
|
# This script can be run on different systems to validate the setup process
|
||||||
|
|
||||||
|
# NOTE: We don't use 'set -e' to allow testing all packages even if some fail
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[0;33m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Maximum number of installation attempts
|
||||||
|
MAX_INSTALL_ATTEMPTS=3
|
||||||
|
CURRENT_ATTEMPT=1
|
||||||
|
|
||||||
|
# Log file
|
||||||
|
# Create logs directory if it doesn't exist and is writable
|
||||||
|
# First, try creating the logs directory in case it doesn't exist
|
||||||
|
if [ -d "/logs" ] || mkdir -p /logs 2>/dev/null; then
|
||||||
|
if [ -w "/logs" ]; then
|
||||||
|
LOGS_DIR="/logs"
|
||||||
|
echo -e "${GREEN}Logs will be saved to host system at ./logs/${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}Warning: /logs directory exists but is not writable${NC}"
|
||||||
|
sudo chmod -R 777 /logs 2>/dev/null || true
|
||||||
|
if [ -w "/logs" ]; then
|
||||||
|
LOGS_DIR="/logs"
|
||||||
|
echo -e "${GREEN}Logs will be saved to host system at ./logs/ (permissions fixed)${NC}"
|
||||||
|
else
|
||||||
|
LOGS_DIR="/tmp"
|
||||||
|
echo -e "${RED}Warning: Could not fix /logs permissions. Logs will be saved to $LOGS_DIR (container only)${NC}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
LOGS_DIR="/tmp"
|
||||||
|
echo -e "${YELLOW}Warning: /logs directory not available or could not be created. Logs will be saved to $LOGS_DIR (container only)${NC}"
|
||||||
|
fi
|
||||||
|
# Use the timestamp from environment variable if set, otherwise generate a new one
|
||||||
|
TIMESTAMP="${TEST_TIMESTAMP:-$(date +"%Y%m%d-%H%M%S")}"
|
||||||
|
CONTAINER_INFO="${CONTAINER_TYPE:+$CONTAINER_TYPE-}"
|
||||||
|
|
||||||
|
LOG_FILE="$LOGS_DIR/setup-test-${CONTAINER_INFO}${TIMESTAMP}.log"
|
||||||
|
echo "Starting setup test at $(date)" > "$LOG_FILE" || {
|
||||||
|
echo -e "${RED}Error: Failed to write to log file at $LOG_FILE. Check permissions.${NC}"
|
||||||
|
ls -la "$LOGS_DIR" 2>/dev/null || echo "Cannot list logs directory contents"
|
||||||
|
LOGS_DIR="/tmp"
|
||||||
|
LOG_FILE="$LOGS_DIR/setup-test-${CONTAINER_INFO}${TIMESTAMP}.log"
|
||||||
|
echo -e "${YELLOW}Attempting to use fallback log location: $LOG_FILE${NC}"
|
||||||
|
echo "Starting setup test at $(date)" > "$LOG_FILE"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Identify the system
|
||||||
|
echo -e "${BLUE}=== System Information ===${NC}"
|
||||||
|
if [ -f /etc/os-release ]; then
|
||||||
|
. /etc/os-release
|
||||||
|
echo -e "Detected: ${GREEN}$PRETTY_NAME${NC}"
|
||||||
|
echo "Testing on: $PRETTY_NAME" >> "$LOG_FILE"
|
||||||
|
else
|
||||||
|
echo -e "${RED}Could not determine OS${NC}"
|
||||||
|
echo "Could not determine OS" >> "$LOG_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Determine if this is a pre-bootstrap or post-bootstrap test
|
||||||
|
TEST_STAGE="Unknown"
|
||||||
|
if [ -d "$HOME/shell" ] && [ -f "$HOME/shell/bootstrap.sh" ] && [ -d "$HOME/shell/setup" ] && [ -f "$HOME/shell/setup/setup.sh" ]; then
|
||||||
|
# Check if there are any signs that bootstrap has been completed
|
||||||
|
if [ -d "$HOME/.oh-my-zsh" ] || [ -f "$HOME/.zshrc" ] || [ -d "$HOME/.nvm" ]; then
|
||||||
|
TEST_STAGE="Post-Bootstrap"
|
||||||
|
else
|
||||||
|
TEST_STAGE="Mid-Bootstrap"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
TEST_STAGE="Pre-Bootstrap"
|
||||||
|
fi
|
||||||
|
echo -e "Test Stage: ${GREEN}$TEST_STAGE${NC}"
|
||||||
|
echo "Test Stage: $TEST_STAGE" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Check if this is running in a test environment (container or VM)
|
||||||
|
ENV_TYPE="Unknown"
|
||||||
|
if [ -f /.dockerenv ]; then
|
||||||
|
ENV_TYPE="Docker container"
|
||||||
|
elif grep -q "^flags.*hypervisor" /proc/cpuinfo 2>/dev/null; then
|
||||||
|
ENV_TYPE="Virtual machine"
|
||||||
|
else
|
||||||
|
ENV_TYPE="Physical machine"
|
||||||
|
fi
|
||||||
|
echo -e "Environment: ${GREEN}$ENV_TYPE${NC}"
|
||||||
|
echo "Environment: $ENV_TYPE" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Initialize arrays for tracking
|
||||||
|
missing_packages=()
|
||||||
|
installed_this_round=()
|
||||||
|
failed_packages=()
|
||||||
|
|
||||||
|
# Helper functions
|
||||||
|
check_command() {
|
||||||
|
command -v "$1" &> /dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
test_package() {
|
||||||
|
local pkg=$1
|
||||||
|
local cmd=${2:-$1}
|
||||||
|
local alt_cmd=$3 # Optional alternative command name
|
||||||
|
|
||||||
|
echo -en "Testing if $pkg is installed... "
|
||||||
|
|
||||||
|
# Special case for cowsay and lolcat which might be in different paths
|
||||||
|
if [ "$pkg" = "cowsay" ]; then
|
||||||
|
if check_command "$cmd"; then
|
||||||
|
echo -e "${GREEN}✓${NC}"
|
||||||
|
echo "$pkg: Installed (found in PATH as $cmd)" >> "$LOG_FILE"
|
||||||
|
return 0
|
||||||
|
elif [ -x "/usr/games/cowsay" ]; then
|
||||||
|
echo -e "${GREEN}✓${NC} (in /usr/games)"
|
||||||
|
echo "$pkg: Installed (found in /usr/games/)" >> "$LOG_FILE"
|
||||||
|
# Create a symlink to make it available in PATH for other scripts
|
||||||
|
if [ ! -e "$HOME/.local/bin" ]; then
|
||||||
|
mkdir -p "$HOME/.local/bin"
|
||||||
|
fi
|
||||||
|
if [ ! -e "$HOME/.local/bin/cowsay" ] && [ -w "$HOME/.local/bin" ]; then
|
||||||
|
ln -sf /usr/games/cowsay "$HOME/.local/bin/cowsay"
|
||||||
|
echo "Created symlink for cowsay in $HOME/.local/bin" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
elif [ "$pkg" = "lolcat" ]; then
|
||||||
|
if check_command "$cmd"; then
|
||||||
|
echo -e "${GREEN}✓${NC}"
|
||||||
|
echo "$pkg: Installed (found in PATH as $cmd)" >> "$LOG_FILE"
|
||||||
|
return 0
|
||||||
|
elif [ -x "/usr/games/lolcat" ]; then
|
||||||
|
echo -e "${GREEN}✓${NC} (in /usr/games)"
|
||||||
|
echo "$pkg: Installed (found in /usr/games/)" >> "$LOG_FILE"
|
||||||
|
# Create a symlink to make it available in PATH for other scripts
|
||||||
|
if [ ! -e "$HOME/.local/bin" ]; then
|
||||||
|
mkdir -p "$HOME/.local/bin"
|
||||||
|
fi
|
||||||
|
if [ ! -e "$HOME/.local/bin/lolcat" ] && [ -w "$HOME/.local/bin" ]; then
|
||||||
|
ln -sf /usr/games/lolcat "$HOME/.local/bin/lolcat"
|
||||||
|
echo "Created symlink for lolcat in $HOME/.local/bin" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
elif check_command "$cmd"; then
|
||||||
|
echo -e "${GREEN}✓${NC}"
|
||||||
|
echo "$pkg: Installed (as $cmd)" >> "$LOG_FILE"
|
||||||
|
return 0
|
||||||
|
elif [ -n "$alt_cmd" ] && check_command "$alt_cmd"; then
|
||||||
|
echo -e "${GREEN}✓${NC} (as $alt_cmd)"
|
||||||
|
echo "$pkg: Installed (as $alt_cmd)" >> "$LOG_FILE"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗${NC}"
|
||||||
|
echo "$pkg: Missing" >> "$LOG_FILE"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
# Note: The calling code will handle the failure and continue testing
|
||||||
|
}
|
||||||
|
|
||||||
|
test_file_exists() {
|
||||||
|
local file=$1
|
||||||
|
local description=${2:-"File exists"}
|
||||||
|
echo -en "Testing if $file exists... "
|
||||||
|
if [ -e "$file" ]; then
|
||||||
|
echo -e "${GREEN}✓${NC}"
|
||||||
|
echo "$description: Yes" >> "$LOG_FILE"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗${NC}"
|
||||||
|
echo "$description: No" >> "$LOG_FILE"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get actual package name based on distribution
|
||||||
|
get_package_name() {
|
||||||
|
local pkg=$1
|
||||||
|
|
||||||
|
# Handle Debian-specific package name differences
|
||||||
|
if [[ "$ID" == "debian" ]]; then
|
||||||
|
case "$pkg" in
|
||||||
|
"bat")
|
||||||
|
echo "batcat"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "$pkg"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
else
|
||||||
|
# Default to the original package name for Ubuntu and others
|
||||||
|
echo "$pkg"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to install missing packages
|
||||||
|
install_missing_packages() {
|
||||||
|
local packages=("$@")
|
||||||
|
local install_cmd_name
|
||||||
|
local install_cmd=()
|
||||||
|
|
||||||
|
if [ ${#packages[@]} -eq 0 ]; then
|
||||||
|
echo -e "${GREEN}No packages to install${NC}"
|
||||||
|
echo "No packages to install" >> "$LOG_FILE"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "\n${BLUE}=== Installing missing packages (Attempt $CURRENT_ATTEMPT of $MAX_INSTALL_ATTEMPTS) ===${NC}"
|
||||||
|
echo "=== Installing missing packages (Attempt $CURRENT_ATTEMPT of $MAX_INSTALL_ATTEMPTS) ===" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Determine the best installation command
|
||||||
|
if check_command nala; then
|
||||||
|
install_cmd=(sudo DEBIAN_FRONTEND=noninteractive nala install -y)
|
||||||
|
install_cmd_name="nala"
|
||||||
|
echo -e "${GREEN}Using nala for package installation${NC}"
|
||||||
|
echo "Using nala for package installation" >> "$LOG_FILE"
|
||||||
|
else
|
||||||
|
install_cmd=(sudo DEBIAN_FRONTEND=noninteractive apt-get -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confnew" install -y)
|
||||||
|
install_cmd_name="apt-get"
|
||||||
|
echo -e "${YELLOW}Using apt-get for package installation${NC}"
|
||||||
|
echo "Using apt-get for package installation" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Convert package list to distribution-specific names
|
||||||
|
local install_list=()
|
||||||
|
for pkg in "${packages[@]}"; do
|
||||||
|
local actual_pkg=$(get_package_name "$pkg")
|
||||||
|
install_list+=("$actual_pkg")
|
||||||
|
done
|
||||||
|
|
||||||
|
# Update package lists
|
||||||
|
echo -e "${YELLOW}Updating package lists...${NC}"
|
||||||
|
echo "Updating package lists" >> "$LOG_FILE"
|
||||||
|
if check_command nala; then
|
||||||
|
echo -e "${GREEN}Running: sudo DEBIAN_FRONTEND=noninteractive nala update${NC}"
|
||||||
|
sudo DEBIAN_FRONTEND=noninteractive nala update | tee -a "$LOG_FILE"
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}Running: sudo DEBIAN_FRONTEND=noninteractive apt-get update${NC}"
|
||||||
|
sudo DEBIAN_FRONTEND=noninteractive apt-get update | tee -a "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install packages
|
||||||
|
echo -e "${YELLOW}Installing packages: ${install_list[*]}${NC}"
|
||||||
|
echo "Installing packages: ${install_list[*]}" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Show the exact command being run for debugging
|
||||||
|
echo -e "${BLUE}Running: ${install_cmd[*]} ${install_list[*]}${NC}"
|
||||||
|
|
||||||
|
# Execute the install command with the package list
|
||||||
|
if ! "${install_cmd[@]}" "${install_list[@]}" 2>&1 | tee -a "$LOG_FILE"; then
|
||||||
|
echo -e "${RED}Failed to install some packages. Check the log for details.${NC}"
|
||||||
|
echo "Failed to install some packages" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Try to install packages one by one to identify problematic ones
|
||||||
|
echo -e "${YELLOW}Trying to install packages individually...${NC}"
|
||||||
|
echo "Trying to install packages individually" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
installed_this_round=()
|
||||||
|
local failed_this_round=()
|
||||||
|
|
||||||
|
for i in "${!packages[@]}"; do
|
||||||
|
local pkg="${packages[$i]}"
|
||||||
|
local actual_pkg="${install_list[$i]}"
|
||||||
|
|
||||||
|
echo -en "Installing $pkg as $actual_pkg... "
|
||||||
|
if "${install_cmd[@]}" "$actual_pkg" >> "$LOG_FILE" 2>&1; then
|
||||||
|
echo -e "${GREEN}✓${NC}"
|
||||||
|
echo "$pkg: Installed successfully" >> "$LOG_FILE"
|
||||||
|
installed_this_round+=("$pkg")
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗${NC}"
|
||||||
|
echo "$pkg: Installation failed" >> "$LOG_FILE"
|
||||||
|
failed_this_round+=("$pkg")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
failed_packages=("${failed_this_round[@]}")
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}Successfully installed all packages!${NC}"
|
||||||
|
echo "Successfully installed all packages" >> "$LOG_FILE"
|
||||||
|
installed_this_round=("${packages[@]}")
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create a temporary backup of .zshrc if it exists
|
||||||
|
if [ -f "$HOME/.zshrc" ]; then
|
||||||
|
cp "$HOME/.zshrc" "$HOME/.zshrc.test_backup"
|
||||||
|
echo "Backed up existing .zshrc" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Main testing sequence
|
||||||
|
echo -e "\n${BLUE}=== Testing bootstrap.sh ===${NC}"
|
||||||
|
echo "=== Testing bootstrap.sh ===" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Get the bootstrap script if it doesn't exist locally
|
||||||
|
if [ ! -f "$HOME/shell/bootstrap.sh" ]; then
|
||||||
|
echo -e "${YELLOW}Downloading bootstrap.sh...${NC}"
|
||||||
|
echo "Downloading bootstrap.sh" >> "$LOG_FILE"
|
||||||
|
curl -s -o /tmp/bootstrap.sh https://raw.githubusercontent.com/acedanger/shell/main/bootstrap.sh || {
|
||||||
|
echo -e "${RED}Failed to download bootstrap.sh${NC}"
|
||||||
|
echo "Failed to download bootstrap.sh" >> "$LOG_FILE"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
chmod +x /tmp/bootstrap.sh
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}Using local bootstrap.sh${NC}"
|
||||||
|
echo "Using local bootstrap.sh" >> "$LOG_FILE"
|
||||||
|
cp "$HOME/shell/bootstrap.sh" /tmp/bootstrap.sh
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Run bootstrap in test mode (no actual execution)
|
||||||
|
echo -e "${YELLOW}Analyzing bootstrap script...${NC}"
|
||||||
|
bash -n /tmp/bootstrap.sh
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo -e "${GREEN}Bootstrap script syntax is valid${NC}"
|
||||||
|
echo "Bootstrap script syntax: Valid" >> "$LOG_FILE"
|
||||||
|
else
|
||||||
|
echo -e "${RED}Bootstrap script has syntax errors${NC}"
|
||||||
|
echo "Bootstrap script syntax: Invalid" >> "$LOG_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "\n${BLUE}=== Testing setup.sh ===${NC}"
|
||||||
|
echo "=== Testing setup.sh ===" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Check setup.sh script if available
|
||||||
|
if [ -f "$HOME/shell/setup/setup.sh" ]; then
|
||||||
|
echo -e "${YELLOW}Analyzing setup script...${NC}"
|
||||||
|
bash -n "$HOME/shell/setup/setup.sh"
|
||||||
|
if [ $? -eq 0 ]; then
|
||||||
|
echo -e "${GREEN}Setup script syntax is valid${NC}"
|
||||||
|
echo "Setup script syntax: Valid" >> "$LOG_FILE"
|
||||||
|
else
|
||||||
|
echo -e "${RED}Setup script has syntax errors${NC}"
|
||||||
|
echo "Setup script syntax: Invalid" >> "$LOG_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}Setup script not available locally. Will be downloaded by bootstrap.${NC}"
|
||||||
|
echo "Setup script not available locally" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "\n${BLUE}=== Testing Debian compatibility ===${NC}"
|
||||||
|
echo "=== Testing Debian compatibility ===" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Check for Debian-specific commands used in scripts
|
||||||
|
echo -en "Checking if apt is available... "
|
||||||
|
if check_command apt; then
|
||||||
|
echo -e "${GREEN}✓${NC}"
|
||||||
|
echo "apt: Available" >> "$LOG_FILE"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗${NC} (Scripts may not work here)"
|
||||||
|
echo "apt: Not available" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if the package list is valid for this system
|
||||||
|
if [ -f "$HOME/shell/setup/packages.list" ]; then
|
||||||
|
echo -e "${YELLOW}Testing package availability in repositories:${NC}"
|
||||||
|
echo "Testing package availability:" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Exclude commented lines and empty lines
|
||||||
|
packages=$(grep -v '^//' "$HOME/shell/setup/packages.list" | grep -v -e '^$')
|
||||||
|
|
||||||
|
for pkg in $packages; do
|
||||||
|
echo -en "Checking if $pkg is available in repos... "
|
||||||
|
actual_pkg=$(get_package_name "$pkg")
|
||||||
|
if apt-cache show "$actual_pkg" &>/dev/null; then
|
||||||
|
echo -e "${GREEN}✓${NC}"
|
||||||
|
echo "$pkg: Available in repos as $actual_pkg" >> "$LOG_FILE"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗${NC}"
|
||||||
|
echo "$pkg: Not available in repos" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Main testing and installation loop
|
||||||
|
while [ $CURRENT_ATTEMPT -le $MAX_INSTALL_ATTEMPTS ]; do
|
||||||
|
echo -e "\n${BLUE}=== Testing installed components (Attempt $CURRENT_ATTEMPT of $MAX_INSTALL_ATTEMPTS) ===${NC}"
|
||||||
|
echo "=== Testing installed components (Attempt $CURRENT_ATTEMPT of $MAX_INSTALL_ATTEMPTS) ===" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
errors=0
|
||||||
|
missing_packages=()
|
||||||
|
|
||||||
|
# Test core required tools
|
||||||
|
core_tools=("git" "curl" "wget")
|
||||||
|
for tool in "${core_tools[@]}"; do
|
||||||
|
if ! test_package "$tool"; then
|
||||||
|
((errors++))
|
||||||
|
missing_packages+=("$tool")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Test if setup has already been run
|
||||||
|
if [ -d "$HOME/.oh-my-zsh" ]; then
|
||||||
|
echo -e "Oh My Zsh: ${GREEN}Installed${NC}"
|
||||||
|
echo "Oh My Zsh: Installed" >> "$LOG_FILE"
|
||||||
|
else
|
||||||
|
echo -e "Oh My Zsh: ${YELLOW}Not installed${NC}"
|
||||||
|
echo "Oh My Zsh: Not installed" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check custom packages from packages.list
|
||||||
|
echo -e "${YELLOW}Testing packages listed in packages.list:${NC}"
|
||||||
|
echo "Testing packages listed in packages.list:" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
if [ -f "$HOME/shell/setup/packages.list" ]; then
|
||||||
|
# Exclude commented lines and empty lines
|
||||||
|
packages=$(grep -v '^//' "$HOME/shell/setup/packages.list" | grep -v -e '^$')
|
||||||
|
|
||||||
|
for pkg in $packages; do
|
||||||
|
case "$pkg" in
|
||||||
|
"bat")
|
||||||
|
if ! test_package "bat" "bat" "batcat"; then
|
||||||
|
((errors++))
|
||||||
|
missing_packages+=("$pkg")
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
"cowsay")
|
||||||
|
# Extra debugging for cowsay
|
||||||
|
echo -e "\n${BLUE}Debugging cowsay package:${NC}" | tee -a "$LOG_FILE"
|
||||||
|
if [ -f "/usr/games/cowsay" ]; then
|
||||||
|
echo -e "- Cowsay found at /usr/games/cowsay" | tee -a "$LOG_FILE"
|
||||||
|
ls -la /usr/games/cowsay | tee -a "$LOG_FILE"
|
||||||
|
else
|
||||||
|
echo -e "- Cowsay not found at /usr/games/cowsay" | tee -a "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
if check_command cowsay; then
|
||||||
|
echo -e "- Cowsay found in PATH" | tee -a "$LOG_FILE"
|
||||||
|
command -v cowsay | tee -a "$LOG_FILE"
|
||||||
|
else
|
||||||
|
echo -e "- Cowsay not found in PATH" | tee -a "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! test_package "cowsay" "cowsay"; then
|
||||||
|
((errors++))
|
||||||
|
missing_packages+=("$pkg")
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
"lolcat")
|
||||||
|
# Extra debugging for lolcat
|
||||||
|
echo -e "\n${BLUE}Debugging lolcat package:${NC}" | tee -a "$LOG_FILE"
|
||||||
|
if [ -f "/usr/games/lolcat" ]; then
|
||||||
|
echo -e "- Lolcat found at /usr/games/lolcat" | tee -a "$LOG_FILE"
|
||||||
|
ls -la /usr/games/lolcat | tee -a "$LOG_FILE"
|
||||||
|
else
|
||||||
|
echo -e "- Lolcat not found at /usr/games/lolcat" | tee -a "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
if check_command lolcat; then
|
||||||
|
echo -e "- Lolcat found in PATH" | tee -a "$LOG_FILE"
|
||||||
|
command -v lolcat | tee -a "$LOG_FILE"
|
||||||
|
else
|
||||||
|
echo -e "- Lolcat not found in PATH" | tee -a "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! test_package "lolcat" "lolcat"; then
|
||||||
|
((errors++))
|
||||||
|
missing_packages+=("$pkg")
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if ! test_package "$pkg" "$pkg"; then
|
||||||
|
((errors++))
|
||||||
|
missing_packages+=("$pkg")
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Report missing packages
|
||||||
|
if [ ${#missing_packages[@]} -gt 0 ]; then
|
||||||
|
echo -e "\n${YELLOW}Missing packages:${NC}"
|
||||||
|
for pkg in "${missing_packages[@]}"; do
|
||||||
|
echo -e "- ${RED}$pkg${NC}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Count installed vs. total packages
|
||||||
|
total_pkgs=$(grep -v '^//' "$HOME/shell/setup/packages.list" | grep -v -e '^$' | wc -l)
|
||||||
|
installed_pkgs=$((total_pkgs - ${#missing_packages[@]}))
|
||||||
|
echo -e "${GREEN}$installed_pkgs of $total_pkgs packages installed${NC} (${YELLOW}${#missing_packages[@]} missing${NC})"
|
||||||
|
echo "$installed_pkgs of $total_pkgs packages installed (${#missing_packages[@]} missing)" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Install missing packages if we haven't reached the maximum attempts
|
||||||
|
if [ $CURRENT_ATTEMPT -lt $MAX_INSTALL_ATTEMPTS ]; then
|
||||||
|
install_missing_packages "${missing_packages[@]}"
|
||||||
|
|
||||||
|
echo -e "\n${BLUE}=== Installation Results ===${NC}"
|
||||||
|
if [ ${#installed_this_round[@]} -gt 0 ]; then
|
||||||
|
echo -e "${GREEN}Successfully installed:${NC}"
|
||||||
|
for pkg in "${installed_this_round[@]}"; do
|
||||||
|
echo -e "- ${GREEN}$pkg${NC}"
|
||||||
|
done
|
||||||
|
echo "Successfully installed: ${installed_this_round[*]}" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ${#failed_packages[@]} -gt 0 ]; then
|
||||||
|
echo -e "${RED}Failed to install:${NC}"
|
||||||
|
for pkg in "${failed_packages[@]}"; do
|
||||||
|
echo -e "- ${RED}$pkg${NC}"
|
||||||
|
done
|
||||||
|
echo "Failed to install: ${failed_packages[*]}" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
CURRENT_ATTEMPT=$((CURRENT_ATTEMPT + 1))
|
||||||
|
echo -e "\n${YELLOW}Continuing to next test iteration...${NC}"
|
||||||
|
echo "Continuing to next test iteration" >> "$LOG_FILE"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
total_pkgs=$(grep -v '^//' "$HOME/shell/setup/packages.list" | grep -v -e '^$' | wc -l)
|
||||||
|
echo -e "\n${GREEN}All $total_pkgs packages are installed!${NC}"
|
||||||
|
echo "All $total_pkgs packages are installed" >> "$LOG_FILE"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "${RED}packages.list file not found at $HOME/shell/setup/packages.list${NC}"
|
||||||
|
echo "packages.list file not found" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If no missing packages or we've reached max attempts, break out of the loop
|
||||||
|
if [ ${#missing_packages[@]} -eq 0 ] || [ $CURRENT_ATTEMPT -ge $MAX_INSTALL_ATTEMPTS ]; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
CURRENT_ATTEMPT=$((CURRENT_ATTEMPT + 1))
|
||||||
|
done
|
||||||
|
|
||||||
|
# Test nvm installation
|
||||||
|
if [ -d "$HOME/.nvm" ]; then
|
||||||
|
echo -e "NVM: ${GREEN}Installed${NC}"
|
||||||
|
echo "NVM: Installed" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Source NVM
|
||||||
|
export NVM_DIR="$HOME/.nvm"
|
||||||
|
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
|
||||||
|
|
||||||
|
# Test Node.js installed by NVM
|
||||||
|
if check_command node; then
|
||||||
|
node_version=$(node -v)
|
||||||
|
echo -e "Node.js: ${GREEN}$node_version${NC}"
|
||||||
|
echo "Node.js: $node_version" >> "$LOG_FILE"
|
||||||
|
else
|
||||||
|
echo -e "Node.js: ${RED}Not installed${NC}"
|
||||||
|
echo "Node.js: Not installed" >> "$LOG_FILE"
|
||||||
|
((errors++))
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "NVM: ${YELLOW}Not installed${NC}"
|
||||||
|
echo "NVM: Not installed" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Test zoxide
|
||||||
|
if test_package "zoxide"; then
|
||||||
|
echo -e "Zoxide integration: ${GREEN}Available${NC}"
|
||||||
|
echo "Zoxide integration: Available" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Test ZSH plugins
|
||||||
|
zsh_plugins=(
|
||||||
|
"$HOME/.oh-my-zsh/custom/plugins/zsh-autosuggestions"
|
||||||
|
"$HOME/.oh-my-zsh/custom/plugins/zsh-syntax-highlighting"
|
||||||
|
"$HOME/.oh-my-zsh/custom/plugins/zsh-you-should-use"
|
||||||
|
)
|
||||||
|
|
||||||
|
for plugin_dir in "${zsh_plugins[@]}"; do
|
||||||
|
plugin_name=$(basename "$plugin_dir")
|
||||||
|
if [ -d "$plugin_dir" ]; then
|
||||||
|
echo -e "ZSH plugin $plugin_name: ${GREEN}Installed${NC}"
|
||||||
|
echo "ZSH plugin $plugin_name: Installed" >> "$LOG_FILE"
|
||||||
|
else
|
||||||
|
echo -e "ZSH plugin $plugin_name: ${YELLOW}Not installed${NC}"
|
||||||
|
echo "ZSH plugin $plugin_name: Not installed" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Test dotfile linking
|
||||||
|
dotfiles=(
|
||||||
|
"$HOME/.zshrc"
|
||||||
|
"$HOME/.nanorc"
|
||||||
|
"$HOME/.profile"
|
||||||
|
"$HOME/.gitconfig"
|
||||||
|
)
|
||||||
|
|
||||||
|
for dotfile in "${dotfiles[@]}"; do
|
||||||
|
if [ -L "$dotfile" ]; then
|
||||||
|
echo -e "Dotfile $dotfile: ${GREEN}Symlinked${NC}"
|
||||||
|
echo "Dotfile $dotfile: Symlinked" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Check if symlink is valid
|
||||||
|
if [ -e "$dotfile" ]; then
|
||||||
|
target=$(readlink -f "$dotfile")
|
||||||
|
echo -e " → Links to: ${GREEN}$target${NC}"
|
||||||
|
echo " → Links to: $target" >> "$LOG_FILE"
|
||||||
|
else
|
||||||
|
echo -e " → ${RED}Broken symlink${NC}"
|
||||||
|
echo " → Broken symlink" >> "$LOG_FILE"
|
||||||
|
((errors++))
|
||||||
|
fi
|
||||||
|
elif [ -f "$dotfile" ]; then
|
||||||
|
echo -e "Dotfile $dotfile: ${YELLOW}Exists but not symlinked${NC}"
|
||||||
|
echo "Dotfile $dotfile: Exists but not symlinked" >> "$LOG_FILE"
|
||||||
|
else
|
||||||
|
echo -e "Dotfile $dotfile: ${YELLOW}Not present${NC}"
|
||||||
|
echo "Dotfile $dotfile: Not present" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -e "\n${BLUE}=== Summary ===${NC}"
|
||||||
|
echo "=== Summary ===" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Test summary
|
||||||
|
if [ $errors -eq 0 ]; then
|
||||||
|
echo -e "${GREEN}All critical components and packages passed! Your setup appears to be working correctly.${NC}"
|
||||||
|
echo "Result: All critical components and packages passed" >> "$LOG_FILE"
|
||||||
|
else
|
||||||
|
echo -e "${RED}Found $errors potential issues with your setup.${NC}"
|
||||||
|
echo "Result: Found $errors potential issues" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Display missing packages if any
|
||||||
|
if [ ${#missing_packages[@]} -gt 0 ]; then
|
||||||
|
echo -e "\n${YELLOW}The following packages were not found:${NC}"
|
||||||
|
echo "Missing packages:" >> "$LOG_FILE"
|
||||||
|
for pkg in "${missing_packages[@]}"; do
|
||||||
|
echo -e " - ${RED}$pkg${NC}"
|
||||||
|
echo " - $pkg" >> "$LOG_FILE"
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $CURRENT_ATTEMPT -gt $MAX_INSTALL_ATTEMPTS ]; then
|
||||||
|
echo -e "\n${RED}Reached maximum installation attempts ($MAX_INSTALL_ATTEMPTS).${NC}"
|
||||||
|
echo -e "${YELLOW}Some packages could not be installed automatically.${NC}"
|
||||||
|
echo "Reached maximum installation attempts" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "\n${BLUE}You can manually install these packages with:${NC}"
|
||||||
|
echo -e " sudo apt-get install ${missing_packages[*]}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Provide more detailed information about log files
|
||||||
|
if [[ "$LOG_FILE" == "/logs/"* ]]; then
|
||||||
|
HOST_LOG_FILE="./logs/$(basename "$LOG_FILE")"
|
||||||
|
echo -e "\n${YELLOW}Complete test log saved to:${NC} $LOG_FILE"
|
||||||
|
echo -e "${GREEN}This log file is accessible on the host system at:${NC} $HOST_LOG_FILE"
|
||||||
|
else
|
||||||
|
echo -e "\n${YELLOW}Complete test log saved to:${NC} $LOG_FILE (in container only)"
|
||||||
|
echo -e "${YELLOW}Note: This log file will be lost when the container exits."
|
||||||
|
echo -e "To preserve logs, run with the logs volume mounted using run-docker-tests.sh${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for Debian-specific issues
|
||||||
|
if [[ "$ID" == "debian" ]]; then
|
||||||
|
echo -e "\n${BLUE}=== Debian-Specific Recommendations ===${NC}"
|
||||||
|
echo "=== Debian-Specific Recommendations ===" >> "$LOG_FILE"
|
||||||
|
echo "1. Ensure Debian's 'universe' equivalent repositories are enabled (contrib, non-free)"
|
||||||
|
echo "2. Some packages like 'bat' may have different names in Debian (batcat)"
|
||||||
|
echo "3. Consider adding Debian-specific adjustments to setup.sh"
|
||||||
|
|
||||||
|
# Add specific Debian package name mappings
|
||||||
|
echo -e "\nOn Debian, you may need these package name adjustments:"
|
||||||
|
echo " - bat → batcat"
|
||||||
|
echo " - (add more as needed)"
|
||||||
|
|
||||||
|
echo "Debian package name mappings may be required" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Enhanced testing for bootstrapped environment
|
||||||
|
check_bootstrapped_environment() {
|
||||||
|
echo -e "\n${BLUE}=== Checking for bootstrapped environment ===${NC}"
|
||||||
|
echo "=== Checking for bootstrapped environment ===" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
if [ -d "$HOME/shell" ] && [ -f "$HOME/shell/bootstrap.sh" ]; then
|
||||||
|
echo -e "${GREEN}Environment appears to be bootstrapped:${NC}"
|
||||||
|
echo "Environment is bootstrapped" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Check the shell repository structure
|
||||||
|
if [ -d "$HOME/shell/setup" ] && [ -f "$HOME/shell/setup/setup.sh" ]; then
|
||||||
|
echo -e " - ${GREEN}Setup directory and script present${NC}"
|
||||||
|
echo "Setup directory and script: Present" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Check if setup.sh is executable
|
||||||
|
if [ -x "$HOME/shell/setup/setup.sh" ]; then
|
||||||
|
echo -e " - ${GREEN}Setup script is executable${NC}"
|
||||||
|
echo "Setup script is executable: Yes" >> "$LOG_FILE"
|
||||||
|
else
|
||||||
|
echo -e " - ${RED}Setup script is not executable${NC}"
|
||||||
|
echo "Setup script is executable: No" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e " - ${RED}Setup directory or setup.sh missing${NC}"
|
||||||
|
echo "Setup directory or setup.sh: Missing" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check packages.list
|
||||||
|
if [ -f "$HOME/shell/setup/packages.list" ]; then
|
||||||
|
echo -e " - ${GREEN}Packages list present${NC}"
|
||||||
|
echo "Packages list: Present" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Count packages in list
|
||||||
|
pkg_count=$(grep -v '^//' "$HOME/shell/setup/packages.list" | grep -v -e '^$' | wc -l)
|
||||||
|
echo -e " - ${GREEN}Package list contains $pkg_count packages${NC}"
|
||||||
|
echo "Package list count: $pkg_count" >> "$LOG_FILE"
|
||||||
|
else
|
||||||
|
echo -e " - ${RED}Packages list missing${NC}"
|
||||||
|
echo "Packages list: Missing" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check dotfiles directory
|
||||||
|
if [ -d "$HOME/shell/dotfiles" ]; then
|
||||||
|
echo -e " - ${GREEN}Dotfiles directory present${NC}"
|
||||||
|
echo "Dotfiles directory: Present" >> "$LOG_FILE"
|
||||||
|
|
||||||
|
# Check if dotfiles are properly symlinked
|
||||||
|
dotfiles_linked=true
|
||||||
|
for dotfile in "$HOME/.zshrc" "$HOME/.nanorc" "$HOME/.profile" "$HOME/.gitconfig"; do
|
||||||
|
if [ -L "$dotfile" ]; then
|
||||||
|
target=$(readlink -f "$dotfile" 2>/dev/null)
|
||||||
|
if [[ "$target" == *"shell/dotfiles"* ]]; then
|
||||||
|
continue
|
||||||
|
else
|
||||||
|
dotfiles_linked=false
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
dotfiles_linked=false
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if $dotfiles_linked; then
|
||||||
|
echo -e " - ${GREEN}Dotfiles are properly symlinked${NC}"
|
||||||
|
echo "Dotfiles symlinked: Yes" >> "$LOG_FILE"
|
||||||
|
else
|
||||||
|
echo -e " - ${YELLOW}Some dotfiles are not properly symlinked${NC}"
|
||||||
|
echo "Dotfiles symlinked: No" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e " - ${RED}Dotfiles directory missing${NC}"
|
||||||
|
echo "Dotfiles directory: Missing" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}No bootstrapped environment detected${NC}"
|
||||||
|
echo "No bootstrapped environment detected" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Call the check if we're not in a simple test environment
|
||||||
|
if [ -d "$HOME/shell" ] && [ -f "$HOME/shell/bootstrap.sh" ]; then
|
||||||
|
check_bootstrapped_environment
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Restore .zshrc if we backed it up
|
||||||
|
if [ -f "$HOME/.zshrc.test_backup" ]; then
|
||||||
|
echo -e "\n${YELLOW}Restoring original .zshrc${NC}"
|
||||||
|
mv "$HOME/.zshrc.test_backup" "$HOME/.zshrc"
|
||||||
|
echo "Restored original .zshrc" >> "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "\n${GREEN}Test completed!${NC}"
|
||||||
|
echo "Test completed at $(date)" >> "$LOG_FILE"
|
||||||
Reference in New Issue
Block a user