diff --git a/.env b/.env new file mode 100644 index 00000000..c0d5ff4f --- /dev/null +++ b/.env @@ -0,0 +1,21 @@ +# Magic Civilization — base environment (tracked, non-secret only). +# +# This file is committed to git. Put only non-sensitive defaults here — +# hostnames, URLs, flags. Secrets (tokens, keys) belong in `.env.local` +# (gitignored) or `.env..local`. +# +# Loader lives in `scripts/run/common.sh` and cascades: +# .env → .env.local → .env. → .env..local +# Variables already set in the shell win over all files. +# +# New keys: document them in `.env.example` with a one-line comment. + +# ── Forgejo forge (non-secret: host URL only) ────────────────────── +FORGEJO_HOST=http://forge.black.local +FORGEJO_ORG=magicciv + +# ── Two-host workflow (edit host → run host) ─────────────────────── +AUTOPLAY_HOST=lilith@apricot.local +PROJECT_ROOT_REMOTE=~/Code/@projects/@magic-civilization +REMOTE_RUNNER=~/bin/run_ap3.sh +SCREENSHOT_HOST=natalie@plum.local diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..d3cd95c5 --- /dev/null +++ b/.env.example @@ -0,0 +1,34 @@ +# Magic Civilization — environment template. +# +# Copy to `.env.local` and fill in the secret values. `.env.local` is +# gitignored so your secrets stay out of git. The loader in +# `scripts/run/common.sh` cascades: +# +# .env → .env.local → .env. → .env..local +# +# Variables already set in your shell always win over every file. +# Only keys with a SECRET value belong in .env.local; non-secret +# defaults (hostnames, paths) stay in the tracked `.env`. + +# ── Forgejo forge ────────────────────────────────────────────────── +# HOST and ORG ship in the tracked `.env`. The runner token is per-host +# and ephemeral — mint via forge UI or `POST /api/v1/orgs//actions/runners/registration-token`. +FORGEJO_HOST=http://forge.black.local +FORGEJO_ORG=magicciv +FORGEJO_RUNNER_TOKEN= # required for `./run setup: --with-runner` +FORGEJO_RELEASE_TOKEN= # required for `.forgejo/workflows/release.yml` — PAT w/ write:repository + +# ── Two-host workflow (edit host → run host) ─────────────────────── +# These ship in tracked `.env` — override in .env.local only if your +# dev machine differs from the canonical mapping. +AUTOPLAY_HOST=lilith@apricot.local +PROJECT_ROOT_REMOTE=~/Code/@projects/@magic-civilization +REMOTE_RUNNER=~/bin/run_ap3.sh +SCREENSHOT_HOST=natalie@plum.local + +# ── Game runtime flags (read by Godot `EnvConfig` autoload) ──────── +# These are tracked in `.env.development` / `.env.production` and +# deployed with the build via `scripts/run/remote.sh`. Override here +# only for per-developer experimentation. +# FORCE_DISABLE_FOGOFWAR=false +# FORCE_UNLIMITED_RESEARCH=false diff --git a/.gitignore b/.gitignore index 76dd1395..36c61091 100644 --- a/.gitignore +++ b/.gitignore @@ -9,9 +9,20 @@ builds/* # Test output test_output/ -# Environment (dev overrides, secrets) -.env -.env.* +# Environment — tracked-safe layout (Next.js/Vite convention) +# +# Tracked (committed): +# .env — base defaults, non-secret only +# .env.example — documented template of all possible keys +# .env.development — mode defaults (development), non-secret only +# .env.production — mode defaults (production), non-secret only +# +# Gitignored (per-developer secrets; copy-from-.env.example): +# .env.local — user-local overrides (secrets go here) +# .env.development.local — dev-mode secrets +# .env.production.local — prod-mode secrets +.env.local +.env.*.local # OS .DS_Store diff --git a/public/games/age-of-dwarves/data/objectives.json b/public/games/age-of-dwarves/data/objectives.json index a0c930b8..559ba08f 100644 --- a/public/games/age-of-dwarves/data/objectives.json +++ b/public/games/age-of-dwarves/data/objectives.json @@ -1,10 +1,10 @@ { - "generated_at": "2026-04-17T19:07:01Z", + "generated_at": "2026-04-17T19:13:52Z", "totals": { - "missing": 2, - "done": 32, "partial": 10, + "missing": 2, "stub": 0, + "done": 32, "oos": 4, "total": 48 }, diff --git a/scripts/run/common.sh b/scripts/run/common.sh index 30999bd2..e865cf14 100644 --- a/scripts/run/common.sh +++ b/scripts/run/common.sh @@ -4,6 +4,64 @@ # Ensure cargo is in PATH (rustup installs to ~/.cargo/bin) [[ -f "$HOME/.cargo/env" ]] && source "$HOME/.cargo/env" +# ── Dotenv loader (Next.js/Vite precedence) ───────────────────────── +# Source order (later wins, so secrets override base): +# 1. .env (tracked, base) +# 2. .env.local (gitignored, user overrides) +# 3. .env. (tracked, mode defaults — development/production) +# 4. .env..local (gitignored, mode+user) +# Mode is $NODE_ENV, else "development". +# +# Variables already set in the shell ALWAYS win (never clobber). Lines +# are plain `KEY=VALUE`; inline comments (`#`) are stripped; surrounding +# single/double quotes on values are stripped. +_load_envfile() { + local f="$1" + [[ -r "$f" ]] || return 0 + local line key val + while IFS= read -r line || [[ -n "$line" ]]; do + # Strip leading whitespace + skip comments + blanks + line="${line#"${line%%[![:space:]]*}"}" + [[ -z "$line" || "$line" == \#* ]] && continue + # Split once on =, tolerate `export KEY=VAL` + line="${line#export }" + [[ "$line" != *=* ]] && continue + key="${line%%=*}" + val="${line#*=}" + # Strip surrounding quotes + [[ "$val" == \"*\" && "$val" == *\" ]] && val="${val:1:${#val}-2}" + [[ "$val" == \'*\' && "$val" == *\' ]] && val="${val:1:${#val}-2}" + # Don't clobber vars already set in the shell + [[ -z "${!key+x}" ]] && export "$key=$val" + done < "$f" +} + +_load_env_cascade() { + local mode="${NODE_ENV:-development}" + _load_envfile "$REPO_ROOT/.env" + _load_envfile "$REPO_ROOT/.env.local" + _load_envfile "$REPO_ROOT/.env.${mode}" + _load_envfile "$REPO_ROOT/.env.${mode}.local" +} + +# Require one or more env vars; fail the current command with a helpful +# message when any are missing. Usage: `require_env FORGEJO_HOST FORGEJO_RUNNER_TOKEN`. +require_env() { + local missing=() + for v in "$@"; do + [[ -z "${!v:-}" ]] && missing+=("$v") + done + if (( ${#missing[@]} > 0 )); then + echo -e "${RED}Missing required env:${NC} ${missing[*]}" >&2 + echo -e "${DIM} Set in .env.local (gitignored) — see .env.example for documented keys.${NC}" >&2 + return 2 + fi + return 0 +} + +# Run cascade at source time so every subcommand has vars available. +_load_env_cascade + RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' diff --git a/src/game/build_info.json b/src/game/build_info.json index 85c98943..61dda8ba 100644 --- a/src/game/build_info.json +++ b/src/game/build_info.json @@ -1,6 +1,6 @@ { "version": "0.1.0-ea", - "commit": "ad79a2beedd4", - "build_date": "2026-04-17T18:57:59Z", + "commit": "79e7351e4084", + "build_date": "2026-04-17T19:13:46Z", "godot_rust": "0.2" }