ci: cancel superseded workflow runs Group each push and pull-request workflow run by workflow and ref. A new push to a pull request cancels that PR's older run. On branches, a newer queued run replaces an older queued one, and a running job finishes. Co-Authored-By: Claude Opus 5.5 <[email protected]>
edda
Project foundation for the Edda Go application.
Prerequisites
- Go 1.24+
- Docker + Docker Compose
- Task
Repository layout
cmd/tui– TUI entrypointcmd/server– server entrypointinternal/*– core application packagespkg/api– exported API typesmigrations/– goose SQL migrations
Quick start
- Start local dependencies:
docker compose up -d - Copy the example env file and adjust values:
cp .env.example .env - Run database migrations:
task migrate - Generate sqlc code:
task generate - Run tests:
task test - Build the binaries:
task build
Production app deploy
docker-compose.yml is the single Compose file for both local Postgres and the deployed app containers.
Production app deploy/rollback uses the repo-owned env contract from .env.production.example.
Copy it to a chmod 600 env file, replace placeholders, and keep EDDA_API_CONTAINER_NAME / EDDA_WEB_CONTAINER_NAME pointed at the dedicated Edda api / web compose containers on the shared projects network.
On the NUC deployment these are gm-api and gm-web, with host ports 3036 and 3037.
Deploy the app containers without touching the external Caddy/edge host:
make deploy ENV_FILE=.env RELEASE_TAG=$(git rev-parse --short HEAD)
Useful deployment commands:
make compose-config # validate the canonical Compose config
make app-build # build edda-api/edda-web images
make app-up # recreate api/web from already-built images
make app-status # show current api/web image, health, and ports
make app-logs # follow api/web logs
make migrate-prod # run production migrations only
make db-backup # create a timestamped DB backup
make smoke # run public production smoke checks
make rollback-sim # simulate rollback from latest make deploy artifacts
make deploy writes rollback state, a pre-deploy DB backup, migration status, and post-cutover inspect output under .sisyphus/evidence/nuc-deploy-<timestamp>/.
The older all-in-one script still exists for hosts where Caddy is local to Docker:
bash scripts/deploy_prod.sh .env
If you need to capture the prior image refs without running deploy, write the same rollback manifest artifact directly:
If your host uses non-default app container names, export the same EDDA_API_CONTAINER_NAME / EDDA_WEB_CONTAINER_NAME values from your production env first.
bash scripts/capture_prod_release.sh <release-tag> .sisyphus/evidence/rollback-manifest.env
That manifest is the input consumed by rollback:
EDDA_ROLLBACK_MODE=simulate bash scripts/rollback_prod.sh .env .sisyphus/evidence/rollback-manifest.env .sisyphus/evidence/pre-deploy.dump
Configuration
Configuration is loaded by koanf in this order (later overrides earlier):
- Built-in defaults (see
internal/config/config.go). - Optional YAML file passed to
config.Load(path)(advanced; unused by default). ANTHROPIC_API_KEY, thenGM_CLAUDE_API_KEY(Claude key fallbacks).GM_-prefixed env vars — the canonical surface.
The env contract is fully documented in two files:
.env.example— every supportedGM_*knob with comments. Copy to.envfor local dev..env.production.example— production overlay; documents only what differs from.env.example(release tag, container names, app ports, bind address, locked LLM endpoints).
Naming rule: GM_<UPPER_SECTION>_<UPPER_KEY> maps to <section>.<key> in the koanf tree. For example, GM_LLM_OLLAMA_APIKEY → llm.ollama.apikey.
License
Licensed under GPL-3.0-or-later. See LICENSE.
Brand assets
The product identity and selected public exports are recorded in the brand handoff and source hashes. Regenerate from SUBCULT Studio with python3 studio/scripts/export_remaining_brand.py edda /path/to/this/repository; use --check to verify the export without writing.
Frontend builds deploy automatically from verified main CI to the existing Dozor service. See automatic frontend deployment for key custody, runtime checks and the separate backend migration procedure.
