From 6e8a7186cfc74289b5e10dd762ecb6c9658c6cc6 Mon Sep 17 00:00:00 2001 From: Phil Skentelbery Date: Mon, 22 Dec 2025 20:37:11 -0700 Subject: [PATCH] fix: use absolute paths for database to ensure persistence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Critical bug fix: Path(__file__).parent.parent returns a relative path, causing the database to be created in different locations depending on the working directory. This caused data loss on container restarts. Changes: - Add .resolve() to BASE_DIR in src/config.py and migrations/env.py - Fix admin dashboard showing 0 for participant count (was hardcoded) - Fix exchange detail page to show actual participant list - Add startup diagnostics to entrypoint.sh for troubleshooting 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- entrypoint.sh | 17 +++++++++++++++++ migrations/env.py | 3 ++- src/config.py | 4 ++-- src/templates/admin/dashboard.html | 2 +- src/templates/admin/exchange_detail.html | 24 +++++++++++++++++++++++- 5 files changed, 45 insertions(+), 5 deletions(-) diff --git a/entrypoint.sh b/entrypoint.sh index 78028b3..ec4c224 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -4,6 +4,22 @@ set -e # Exit on any error # Ensure data directory exists mkdir -p /app/data +echo "=== Sneaky Klaus Container Startup ===" +echo "Data directory: /app/data" +echo "Database path: /app/data/sneaky-klaus.db" + +# Check if database exists +if [ -f /app/data/sneaky-klaus.db ]; then + echo "Existing database found ($(ls -lh /app/data/sneaky-klaus.db | awk '{print $5}'))" +else + echo "No existing database - will be created by migrations" +fi + +# List contents of data directory +echo "Data directory contents:" +ls -la /app/data/ || echo "(empty)" + +echo "" echo "Running database migrations..." if uv run alembic upgrade head; then echo "Database migrations completed successfully" @@ -13,5 +29,6 @@ else exit 1 fi +echo "" echo "Starting application server..." exec gunicorn --bind 0.0.0.0:8000 --workers 2 --threads 4 main:app diff --git a/migrations/env.py b/migrations/env.py index 1c8b403..22a6a17 100644 --- a/migrations/env.py +++ b/migrations/env.py @@ -24,7 +24,8 @@ if config.config_file_name is not None: # Create minimal Flask app for migrations (without session initialization) # This avoids Flask-Session trying to create tables before migrations run app = Flask(__name__) -BASE_DIR = Path(__file__).parent.parent +# Use resolve() to ensure absolute paths - critical for database persistence +BASE_DIR = Path(__file__).parent.parent.resolve() DATA_DIR = BASE_DIR / "data" DATA_DIR.mkdir(parents=True, exist_ok=True) diff --git a/src/config.py b/src/config.py index bc93a25..4f151a5 100644 --- a/src/config.py +++ b/src/config.py @@ -12,8 +12,8 @@ from pathlib import Path class Config: """Base configuration class with common settings.""" - # Base paths - BASE_DIR = Path(__file__).parent.parent + # Base paths - use resolve() to ensure absolute paths + BASE_DIR = Path(__file__).parent.parent.resolve() DATA_DIR = BASE_DIR / "data" # Security diff --git a/src/templates/admin/dashboard.html b/src/templates/admin/dashboard.html index 41585ea..2f3da14 100644 --- a/src/templates/admin/dashboard.html +++ b/src/templates/admin/dashboard.html @@ -51,7 +51,7 @@ {{ exchange.name }} {{ exchange.state }} - 0 / {{ exchange.max_participants }} + {{ exchange.participants|selectattr('withdrawn_at', 'none')|list|length }} / {{ exchange.max_participants }} {{ exchange.exchange_date.strftime('%Y-%m-%d') }} View diff --git a/src/templates/admin/exchange_detail.html b/src/templates/admin/exchange_detail.html index 2cdb7c2..4c2699e 100644 --- a/src/templates/admin/exchange_detail.html +++ b/src/templates/admin/exchange_detail.html @@ -37,8 +37,30 @@
-

Participants

+

Participants ({{ exchange.participants|selectattr('withdrawn_at', 'none')|list|length }} / {{ exchange.max_participants }})

+ {% set active_participants = exchange.participants|selectattr('withdrawn_at', 'none')|list %} + {% if active_participants %} + + + + + + + + + + {% for participant in active_participants|sort(attribute='name') %} + + + + + + {% endfor %} + +
NameEmailRegistered
{{ participant.name }}{{ participant.email }}{{ participant.created_at.strftime('%Y-%m-%d %H:%M') }}
+ {% else %}

No participants yet.

+ {% endif %}