class Discharger::SetupRunner::Commands::PgToolsCommand
def can_execute?
def can_execute? config.respond_to?(:database) && config.database&.name.present? end
def container_name
def container_name config.database.name end
def create_envrc_if_needed
def create_envrc_if_needed envrc_path = File.join(app_root, ".envrc") if File.exist?(envrc_path) # Don't overwrite existing .envrc, but suggest adding PATH if not present unless File.read(envrc_path).include?("bin/pg-tools") log "Note: Add 'PATH_add bin/pg-tools' to existing .envrc for shell access" end else File.write(envrc_path, "PATH_add bin/pg-tools\n") log "Created .envrc (run 'direnv allow' to enable for shell access)" end end
def create_pg_tools_directory
def create_pg_tools_directory FileUtils.mkdir_p(File.join(app_root, "bin", "pg-tools")) end
def create_wrapper(tool)
def create_wrapper(tool) wrapper_path = File.join(app_root, "bin", "pg-tools", tool) File.write(wrapper_path, wrapper_content(tool)) FileUtils.chmod(0o755, wrapper_path) log "Created bin/pg-tools/#{tool}" end
def description
def description "Setting up PostgreSQL tools wrappers" end
def execute
def execute create_pg_tools_directory TOOLS.each { |tool| create_wrapper(tool) } create_envrc_if_needed end
def generic_wrapper_content(tool)
def generic_wrapper_content(tool) <<~BASH #!/usr/bin/env bash set -e CONTAINER="#{container_name}" # Docker first: use container's #{tool} if running if docker ps --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER}$"; then echo "Using #{tool} from Docker container: $CONTAINER" >&2 # Parse arguments to handle --file option specially # When running in Docker, host paths don't exist in the container # so we pipe file content via stdin instead INPUT_FILE="" HAS_USER="" ARGS=() while [[ $# -gt 0 ]]; do case $1 in --file) INPUT_FILE="$2" shift 2 ;; --file=*) INPUT_FILE="${1#*=}" shift ;; -f) INPUT_FILE="$2" shift 2 ;; -U|--username|--username=*) HAS_USER="1" ARGS+=("$1") shift ;; *) ARGS+=("$1") shift ;; esac done # Default to postgres user if not specified (container runs as root) if [[ -z "$HAS_USER" ]]; then ARGS=("-U" "postgres" "${ARGS[@]}") fi if [[ -n "$INPUT_FILE" ]]; then docker exec -i "$CONTAINER" #{tool} "${ARGS[@]}" < "$INPUT_FILE" else exec docker exec -i "$CONTAINER" #{tool} "${ARGS[@]}" fi exit 0 fi # Fallback to system #{tool} (skip this wrapper in PATH to avoid infinite loop) SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" CLEAN_PATH="${PATH//$SCRIPT_DIR:/}" CLEAN_PATH="${CLEAN_PATH%:$SCRIPT_DIR}" FALLBACK=$(PATH="$CLEAN_PATH" command -v #{tool} 2>/dev/null) if [[ -n "$FALLBACK" ]]; then exec "$FALLBACK" "$@" fi echo "Error: #{tool} not found. Start Docker or install PostgreSQL client tools." >&2 exit 1 BASH end
def pg_dump_wrapper_content
def pg_dump_wrapper_content <<~BASH #!/usr/bin/env bash set -e CONTAINER="#{container_name}" # Docker first: use container's pg_dump if running if docker ps --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER}$"; then echo "Using pg_dump from Docker container: $CONTAINER" >&2 # Parse arguments to handle --file option specially # When running in Docker, we need to output to stdout and redirect locally OUTPUT_FILE="" HAS_USER="" ARGS=() while [[ $# -gt 0 ]]; do case $1 in --file) OUTPUT_FILE="$2" shift 2 ;; --file=*) OUTPUT_FILE="${1#*=}" shift ;; -f) OUTPUT_FILE="$2" shift 2 ;; -U|--username|--username=*) HAS_USER="1" ARGS+=("$1") shift ;; *) ARGS+=("$1") shift ;; esac done # Default to postgres user if not specified (container runs as root) if [[ -z "$HAS_USER" ]]; then ARGS=("-U" "postgres" "${ARGS[@]}") fi if [[ -n "$OUTPUT_FILE" ]]; then # Run pg_dump in container, output to stdout, redirect to local file docker exec -i "$CONTAINER" pg_dump "${ARGS[@]}" > "$OUTPUT_FILE" else # No file output, just exec normally exec docker exec -i "$CONTAINER" pg_dump "${ARGS[@]}" fi exit 0 fi # Fallback to system pg_dump (skip this wrapper in PATH to avoid infinite loop) SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" CLEAN_PATH="${PATH//$SCRIPT_DIR:/}" CLEAN_PATH="${CLEAN_PATH%:$SCRIPT_DIR}" FALLBACK=$(PATH="$CLEAN_PATH" command -v pg_dump 2>/dev/null) if [[ -n "$FALLBACK" ]]; then exec "$FALLBACK" "$@" fi echo "Error: pg_dump not found. Start Docker or install PostgreSQL client tools." >&2 exit 1 BASH end
def wrapper_content(tool)
def wrapper_content(tool) if tool == "pg_dump" pg_dump_wrapper_content else generic_wrapper_content(tool) end end