#!/bin/bash # Efficient development container workflow - persistent container for debugging set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" # Container configuration CONTAINER_NAME="zero-os-dev" BUILDER_IMAGE="zero-os-builder:latest" HOST_SSH_DIR="${SSH_MOUNT_DIR:-${HOME}/.ssh}" # Default to verbose, streaming logs for dev flows unless explicitly disabled export DEBUG="${DEBUG:-1}" # Source common functions source "${SCRIPT_DIR}/lib/common.sh" function show_usage() { cat </dev/null; then log_info "Found builder image: ${img}" BUILDER_IMAGE="$img" return 0 fi done log_warn "Builder image not found locally; building: ${BUILDER_IMAGE}" safe_execute podman build -t "${BUILDER_IMAGE}" -f "${PROJECT_ROOT}/Dockerfile" "${PROJECT_ROOT}" if podman image exists "$BUILDER_IMAGE" 2>/dev/null; then log_info "Builder image built successfully: ${BUILDER_IMAGE}" return 0 fi # As a fallback, also tag with localhost to satisfy Podman short-name policy local local_tag="localhost/${BUILDER_IMAGE}" log_info "Tagging builder image as ${local_tag}" safe_execute podman tag "${BUILDER_IMAGE}" "${local_tag}" || true if podman image exists "$local_tag" 2>/dev/null; then BUILDER_IMAGE="$local_tag" fi } function dev_container_start() { section_header "Starting Development Container" # Ensure builder image exists (handles clean --all case and short-name policy) ensure_builder_image # Check if container already exists if podman container exists "$CONTAINER_NAME" 2>/dev/null; then if podman container inspect "$CONTAINER_NAME" --format '{{.State.Status}}' | grep -q "running"; then log_info "Development container already running" return 0 else log_info "Starting existing development container" safe_execute podman start "$CONTAINER_NAME" return 0 fi fi log_info "Creating new development container: ${CONTAINER_NAME}" # Create persistent container with all necessary mounts and environment local podman_args=( run -d --name "$CONTAINER_NAME" --privileged -v "${PROJECT_ROOT}:/workspace" -v "$HOME/.ssh:root/.ssh" -w /workspace -e DEBUG=1 -e ALPINE_VERSION=3.22 -e KERNEL_VERSION=6.12.44 -e RUST_TARGET=x86_64-unknown-linux-musl -e OPTIMIZATION_LEVEL=max ) if [[ -d "$HOST_SSH_DIR" ]]; then log_info "Mounting SSH directory: ${HOST_SSH_DIR} -> /root/.ssh (read-only)" podman_args+=(-v "${HOST_SSH_DIR}:/root/.ssh:ro") else log_warn "SSH directory not found at ${HOST_SSH_DIR}; skipping SSH mount" fi podman_args+=( "$BUILDER_IMAGE" sleep infinity ) safe_execute podman "${podman_args[@]}" log_info "Development container started successfully" log_info "Container name: ${CONTAINER_NAME}" log_info "Access with: $0 shell" } function dev_container_stop() { section_header "Stopping Development Container" if podman container exists "$CONTAINER_NAME" 2>/dev/null; then log_info "Stopping development container: ${CONTAINER_NAME}" safe_execute podman stop "$CONTAINER_NAME" log_info "Development container stopped" else log_info "Development container not found" fi } function dev_container_shell() { section_header "Entering Development Container Shell" if ! podman container exists "$CONTAINER_NAME" 2>/dev/null; then log_info "Development container not found, starting..." dev_container_start fi if ! podman container inspect "$CONTAINER_NAME" --format '{{.State.Status}}' | grep -q "running"; then log_info "Starting stopped development container" safe_execute podman start "$CONTAINER_NAME" fi log_info "Entering container shell (exit with 'exit' or Ctrl+D)" # Use direct execution for interactive shell (don't use safe_execute) exec podman exec -it "$CONTAINER_NAME" /bin/bash } function dev_container_build() { section_header "Running Build in Development Container" if ! podman container exists "$CONTAINER_NAME" 2>/dev/null; then log_info "Development container not found, starting..." dev_container_start fi if ! podman container inspect "$CONTAINER_NAME" --format '{{.State.Status}}' | grep -q "running"; then log_info "Starting stopped development container" safe_execute podman start "$CONTAINER_NAME" fi log_info "Running build in persistent container (real-time output)" log_info "Command: podman exec $CONTAINER_NAME ./scripts/build.sh $*" # Use direct execution to show real-time output (bypass safe_execute) podman exec "$CONTAINER_NAME" ./scripts/build.sh "$@" local exit_code=$? if [[ $exit_code -eq 0 ]]; then log_info "Build completed successfully in container" else log_error "Build failed in container with exit code: $exit_code" fi return $exit_code } function dev_container_clean() { section_header "Cleaning Development Container" if podman container exists "$CONTAINER_NAME" 2>/dev/null; then log_info "Removing existing development container" safe_execute podman rm -f "$CONTAINER_NAME" fi log_info "Starting fresh development container" dev_container_start } function dev_container_status() { section_header "Development Container Status" if podman container exists "$CONTAINER_NAME" 2>/dev/null; then local status=$(podman container inspect "$CONTAINER_NAME" --format '{{.State.Status}}') local created=$(podman container inspect "$CONTAINER_NAME" --format '{{.Created}}') log_info "Container: ${CONTAINER_NAME}" log_info "Status: ${status}" log_info "Created: ${created}" if [[ "$status" == "running" ]]; then log_info "✓ Ready for development" else log_info "⚠ Container stopped - use '$0 start' to start" fi else log_info "Development container not found" log_info "Use '$0 start' to create" fi } function dev_container_logs() { section_header "Development Container Logs" if podman container exists "$CONTAINER_NAME" 2>/dev/null; then safe_execute podman logs "$CONTAINER_NAME" else log_error "Development container not found" return 1 fi } # Main function function main() { local command="${1:-help}" case "$command" in start) dev_container_start ;; stop) dev_container_stop ;; shell) dev_container_shell ;; build) shift dev_container_build "$@" ;; clean) dev_container_clean ;; status) dev_container_status ;; logs) dev_container_logs ;; help | --help | -h) show_usage ;; *) log_error "Unknown command: $command" show_usage exit 1 ;; esac } main "$@"