Files
timetracker/entrypoint.sh
T
Claude 017e3a61a8 Harden staging and bring GitHub/Gitea CI to parity
Address issue #20 and the CI divergence between Gitea and GitHub.

Issue #20 (staging seeded from a prod snapshot):
- Read SECRET_KEY from the environment with the insecure dev key as
  fallback, so each deployment can have its own key.
- Add a `scrub_staging` management command that clears django_session and
  the django-q schedule/queue/results, removing copied prod sessions and
  the inherited convert_prices() schedule.
- Run the scrub from entrypoint.sh when STAGING=true, and wire STAGING plus
  a per-branch SECRET_KEY into the Gitea staging deploy.

CI parity (both systems kept, independent):
- Add the Node/pnpm/TypeScript build steps to the Gitea build workflow to
  match the GitHub test job.
- Add a GitHub staging workflow that deploys per-branch ephemeral instances
  to Fly.io (*.fly.dev) with a fresh database seeded from sample fixtures
  and its own SECRET_KEY, never production data. Tears the app down on
  branch delete and comments the URL on the open PR via github-script.
- Add fly.staging.toml and a LOAD_SAMPLE_DATA entrypoint hook for the
  fresh-database public staging.

https://claude.ai/code/session_01KYjUcNjLfZ8Hq1GAC8J4oZ
2026-06-14 13:15:19 +00:00

55 lines
1.7 KiB
Bash

#!/bin/bash
set -euo pipefail
PUID=${PUID:-1000}
PGID=${PGID:-100}
USERHOME=$(grep timetracker /etc/passwd | cut -d ":" -f6)
usermod -d "/root" timetracker
groupmod -o -g "$PGID" timetracker
usermod -o -u "$PUID" timetracker
usermod -d "${USERHOME}" timetracker
mkdir -p /home/timetracker/app/data /var/log/supervisor
chmod 755 /home/timetracker/app
chmod 755 /home/timetracker/app/.venv
chown "$PUID:$PGID" /home/timetracker/app/data
chown "$PUID:$PGID" /var/log/supervisor
python manage.py migrate
python manage.py collectstatic --clear --no-input
# Staging seeded from a production snapshot: remove copied sessions and the
# inherited django-q schedule/queue so staging neither shares prod's session
# cookies nor independently runs scheduled tasks (see issue #20).
if [ "${STAGING:-false}" = "true" ]; then
python manage.py scrub_staging
fi
# Public staging with a fresh database (e.g. Fly.io): load demo data instead
# of any production snapshot. Runs once while the games table is empty.
if [ "${LOAD_SAMPLE_DATA:-false}" = "true" ]; then
python manage.py shell -c "
from games.models import Game
from django.core.management import call_command
if not Game.objects.exists():
call_command('loaddata', 'sample.yaml')
print('Loaded sample data.')
"
fi
if [ "${CREATE_DEFAULT_SUPERUSER:-false}" = "true" ]; then
python manage.py shell -c "
from django.contrib.auth import get_user_model
User = get_user_model()
if not User.objects.filter(username='admin').exists():
User.objects.create_superuser('admin', '', 'admin')
print('Created default superuser: admin / admin')
"
fi
chown -R "$PUID:$PGID" /home/timetracker/app/data
exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisor.conf