entrypoint := 'oslstats' cwd := justfile_directory() cmd := cwd / 'cmd' bin := cwd / 'bin' css_dir := cwd / 'internal/embedfs/web/css' set quiet := true [private] default: @just --list --unsorted # BUILD RECIPES # Build the target binary [group('build')] build target=entrypoint: templ tailwind (_build target) _build target=entrypoint: tidy (generate target) go build -ldflags="-w -s" -o {{bin}}/{{target}} {{cmd}}/{{target}} # Generate tailwind output file [group('build')] [arg('watch', pattern='--watch|')] tailwind watch='': tailwindcss -i {{css_dir}}/input.css -o {{css_dir}}/output.css {{watch}} # Generate go source files [group('build')] generate target=entrypoint: go generate {{cmd}}/{{target}} # Generate templ files [group('build')] [arg('watch', pattern='--watch|')] templ watch='': templ generate {{watch}} # RUN RECIPES # Run the target binary [group('run')] run target=entrypoint: (build target) ./bin/{{target}} [private] _air: air # Run the main program in development mode (with air & hot reloading) [group('run')] [parallel] dev: (templ '--watch') (tailwind '--watch') _air # GO RECIPES # Tidy go mod file [group('go')] tidy: go mod tidy # Get or update h/golib packages [group('go')] [arg('update', pattern='-u|')] golib package update='': && tidy go get {{update}} git.haelnorr.com/h/golib/{{package}} # ENV RECIPES # Generate a new env file [group('env')] genenv out='.env': _build {{bin}}/{{entrypoint}} --genenv {{out}} # Show env file documentation [group('env')] envdoc: _build {{bin}}/{{entrypoint}} --envdoc # Show current env file values [group('env')] showenv: _build {{bin}}/{{entrypoint}} --showenv # DB RECIPES # Migrate the database [group('db')] [arg('command', pattern='up|down|new|status', help="up|down|new|status")] [script] migrate command subcommand='' env='.env': _build env={{env}} subcommand={{subcommand}} if [[ "{{command}}" = "status" ]]; then env=$subcommand subcommand='' fi if [[ $env = "" ]]; then env=.env fi ENVFILE=$env just _migrate-{{command}} $subcommand [private] _migrate-up steps='1': && _migrate-status {{bin}}/{{entrypoint}} --migrate-up {{steps}} --envfile $ENVFILE [private] _migrate-down steps='1': && _migrate-status {{bin}}/{{entrypoint}} --migrate-rollback {{steps}} --envfile $ENVFILE [private] _migrate-status: {{bin}}/{{entrypoint}} --migrate-status --envfile $ENVFILE [private] _migrate-new name: && _build _migrate-status {{bin}}/{{entrypoint}} --migrate-create {{name}} # Hard reset the database [group('db')] reset-db env='.env': _build echo "⚠️ WARNING - This will DELETE ALL DATA!" {{bin}}/{{entrypoint}} --reset-db --envfile {{env}} # Restore database from a production backup (.sql) [group('db')] [confirm("⚠️ This will DELETE ALL DATA in the dev database and replace it with the backup. Continue?")] [script] restore-db backup_file env='.env': set -euo pipefail # Source env vars set -a source ./{{env}} set +a DB_USER="${DB_USER}" DB_PASSWORD="${DB_PASSWORD}" DB_HOST="${DB_HOST}" DB_PORT="${DB_PORT:-5432}" DB_NAME="${DB_NAME}" PROD_USER="oslstats" export PGPASSWORD="$DB_PASSWORD" echo "[INFO] Restoring database from: {{backup_file}}" echo "[INFO] Target: $DB_NAME on $DB_HOST:$DB_PORT as $DB_USER" echo "" # Step 1: Drop and recreate the database echo "[INFO] Step 1/4: Dropping and recreating database..." psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres -c \ "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = '$DB_NAME' AND pid <> pg_backend_pid();" \ > /dev/null 2>&1 || true psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres -c "DROP DATABASE IF EXISTS \"$DB_NAME\";" psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d postgres -c "CREATE DATABASE \"$DB_NAME\" OWNER \"$DB_USER\";" echo "[INFO] Database recreated" # Step 2: Preprocess and restore the dump (remap ownership) echo "[INFO] Step 2/4: Restoring backup (remapping owner $PROD_USER → $DB_USER)..." sed \ -e "s/OWNER TO ${PROD_USER}/OWNER TO ${DB_USER}/g" \ -e "s/Owner: ${PROD_USER}/Owner: ${DB_USER}/g" \ -e "/^ALTER DEFAULT PRIVILEGES/d" \ -e "s/GRANT ALL ON \(.*\) TO ${PROD_USER}/GRANT ALL ON \1 TO ${DB_USER}/g" \ "{{backup_file}}" | psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" --quiet --single-transaction echo "[INFO] Backup restored" # Step 3: Reassign all ownership as safety net echo "[INFO] Step 3/4: Reassigning remaining ownership to $DB_USER..." psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" <