Files
oslstats/justfile
2026-03-08 18:12:03 +11:00

210 lines
5.8 KiB
Makefile

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" <<EOSQL
DO \$\$
DECLARE
r RECORD;
BEGIN
-- Reassign tables
FOR r IN SELECT tablename FROM pg_tables WHERE schemaname = 'public'
LOOP
EXECUTE format('ALTER TABLE public.%I OWNER TO ${DB_USER}', r.tablename);
END LOOP;
-- Reassign sequences
FOR r IN SELECT sequence_name FROM information_schema.sequences WHERE sequence_schema = 'public'
LOOP
EXECUTE format('ALTER SEQUENCE public.%I OWNER TO ${DB_USER}', r.sequence_name);
END LOOP;
-- Reassign views
FOR r IN SELECT viewname FROM pg_views WHERE schemaname = 'public'
LOOP
EXECUTE format('ALTER VIEW public.%I OWNER TO ${DB_USER}', r.viewname);
END LOOP;
END \$\$;
EOSQL
echo "[INFO] Ownership reassigned"
# Step 4: Summary
echo "[INFO] Step 4/4: Verifying table count..."
TABLE_COUNT=$(psql -h "$DB_HOST" -p "$DB_PORT" -U "$DB_USER" -d "$DB_NAME" -t -c \
"SELECT count(*) FROM pg_tables WHERE schemaname = 'public';")
echo "[INFO] Found${TABLE_COUNT} tables in restored database"
echo ""
echo "✅ Database restored successfully from: {{backup_file}}"
echo ""
echo "📋 Next steps:"
echo " 1. Run 'just migrate up all' to apply any dev-only migrations"
echo " 2. Run 'just dev' to start the development server"