#!/usr/bin/env bash # Docker Deployment Test — OpenClaw with Triad Resilience # # Tests the corruption detection + auto-recovery build in Docker # Usage: ./scripts/docker-deploy-test.sh [--build] [--test] [--cleanup] # # Requirements: Docker installed and running # # Steps: # 1. Build local image from current workspace # 2. Run gateway container with workspace mounted # 3. Execute corruption detection script # 4. Verify triad resilience features # 5. Test auto-recovery (optional) set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" WORKSPACE_ROOT="$(dirname "$SCRIPT_DIR")" IMAGE_NAME="${OPENCLAW_DOCKER_IMAGE:-openclaw:triad-resilience}" CONTAINER_NAME="openclaw-triad-test" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' usage() { cat </dev/null; then log_error "Docker not found in PATH" echo "" echo "Install Docker:" echo " Debian/Ubuntu: sudo apt-get install docker.io" echo " macOS: brew install --cask docker" echo " Or visit: https://docs.docker.com/get-docker/" exit 1 fi if ! docker info &>/dev/null; then log_error "Docker daemon not running or permission denied" echo "" echo "Troubleshooting:" echo " 1. Start Docker: sudo systemctl start docker" echo " 2. Add user to docker group: sudo usermod -aG docker \$USER" echo " 3. Logout and login again" exit 1 fi log_info "Docker available: $(docker --version)" } # Build Docker image build_image() { log_info "Building Docker image: $IMAGE_NAME" echo "" # Create Dockerfile in workspace root cat > "$WORKSPACE_ROOT/Dockerfile.triad" <<'DOCKERFILE' FROM node:24-bookworm-slim WORKDIR /app # Install git and sqlite3 for corruption detection RUN --mount=type=cache,id=apt-cache,target=/var/cache/apt,sharing=locked \ --mount=type=cache,id=apt-lists,target=/var/lib/apt,sharing=locked \ apt-get update -o Acquire::Retries=3 && \ apt-get install -y --no-install-recommends \ git \ sqlite3 \ curl \ && rm -rf /var/lib/apt/lists/* # Copy workspace COPY . /app/ # Install dependencies RUN npm ci --ignore-scripts 2>/dev/null || npm install --ignore-scripts # Build if needed RUN npm run build 2>/dev/null || true # Set workspace as working directory WORKDIR /app # Default command runs corruption check ENTRYPOINT ["node", "scripts/triad-corruption-check.mjs"] CMD [] DOCKERFILE echo "Building from Dockerfile.triad..." docker build \ -t "$IMAGE_NAME" \ -f "$WORKSPACE_ROOT/Dockerfile.triad" \ "$WORKSPACE_ROOT" # Cleanup temporary Dockerfile rm -f "$WORKSPACE_ROOT/Dockerfile.triad" log_info "Image built: $IMAGE_NAME" docker images "$IMAGE_NAME" --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" } # Run corruption detection test run_tests() { log_info "Running corruption detection tests in container" echo "" # Check if image exists if ! docker images "$IMAGE_NAME" --format '{{.Repository}}' | grep -q "$IMAGE_NAME"; then log_warn "Image not found. Run with --build first" echo " $0 --build" exit 1 fi # Run container with workspace mounted log_info "Mounting workspace and running corruption check..." docker run --rm \ -v "$WORKSPACE_ROOT:/app" \ -w /app \ "$IMAGE_NAME" \ --verbose 2>&1 || { log_error "Corruption detection failed" exit 1 } echo "" log_info "✅ Corruption detection test completed" } # Test auto-recovery test_recovery() { log_info "Testing auto-recovery procedure" echo "" # Create a test corruption scenario log_warn "Simulating config file corruption..." echo "CORRUPTED" >> "$WORKSPACE_ROOT/AGENTS.md" # Run corruption check (should detect) log_info "Running corruption check (expecting detection)..." if docker run --rm \ -v "$WORKSPACE_ROOT:/app" \ -w /app \ "$IMAGE_NAME" \ --auto-recover 2>&1; then log_error "Auto-recovery should have detected corruption" exit 1 fi # Restore AGENTS.md log_info "Restoring AGENTS.md..." cd "$WORKSPACE_ROOT" && git checkout AGENTS.md log_info "✅ Auto-recovery test completed" } # Cleanup cleanup() { log_info "Cleaning up test artifacts" # Stop and remove container if running docker stop "$CONTAINER_NAME" 2>/dev/null || true docker rm "$CONTAINER_NAME" 2>/dev/null || true # Remove image docker rmi "$IMAGE_NAME" 2>/dev/null || true # Remove temporary Dockerfile rm -f "$WORKSPACE_ROOT/Dockerfile.triad" log_info "Cleanup complete" } # Parse arguments BUILD=false TEST=false RECOVERY=false CLEANUP=false if [[ $# -eq 0 ]]; then usage exit 0 fi while [[ $# -gt 0 ]]; do case "$1" in --build) BUILD=true shift ;; --test) TEST=true shift ;; --recovery) RECOVERY=true shift ;; --cleanup) CLEANUP=true shift ;; --all) BUILD=true TEST=true CLEANUP=true shift ;; --help|-h) usage exit 0 ;; *) log_error "Unknown option: $1" usage exit 1 ;; esac done # Main execution check_docker if [[ "$BUILD" == true ]]; then build_image fi if [[ "$TEST" == true ]]; then run_tests fi if [[ "$RECOVERY" == true ]]; then test_recovery fi if [[ "$CLEANUP" == true ]]; then cleanup fi echo "" log_info "🦞 Triad resilience Docker test complete"