Skip to content

feat(stacks): Add Evidence — SQL+markdown BI for analytics engineers#616

Merged
stefanko-ch merged 5 commits into
mainfrom
feat/stacks/evidence
May 27, 2026
Merged

feat(stacks): Add Evidence — SQL+markdown BI for analytics engineers#616
stefanko-ch merged 5 commits into
mainfrom
feat/stacks/evidence

Conversation

@stefanko-ch

Copy link
Copy Markdown
Owner

Summary

Adds Evidence — an open-source "BI as code" framework where each page is a Markdown file with embedded SQL blocks that render to charts, tables, and inline values. Pages diff as plain text, which makes Evidence the natural complement to the existing code-server / Gitea / Woodpecker-CI workflow.

  • New stack evidence (port 3007 → container 3000, category analytics)
  • Ships the evidencedev/devenv runtime preloaded with a sample project that queries the in-stack Postgres
  • No Tofu-managed secrets — Evidence pipes through the existing postgres_password; operator-added sources reference whatever credentials the operator wires into stacks/evidence/.env
  • Stack count 72 → 73

Closes #615

Why this shape

No new Tofu secret. The sample project consumes the existing postgres_password via env-var interpolation in sources/nexus_postgres/connection.yaml. Operator-added data sources reference Infisical-managed credentials from any other stack. No double-managing.

Port 3007. 3000–3006 already taken by Metabase / Uptime-Kuma / Wetty / Hoppscotch / Dagster / Wiki.js / Big-AGI. 3007 is the closest free slot to Evidence's default 3000.

Image evidencedev/devenv:latest. Acceptable under the CLAUDE.md exception for non-critical standalone tools (Evidence is a presentation layer with no persistent state beyond cache) and Evidence does not publish stable devenv tags. Multi-arch verified (amd64 + arm64).

No fail-fast guard. Evidence renders pages even without a working data source (it just shows query errors inline). The operator may legitimately be wiring an external warehouse instead of the in-stack Postgres. Empty postgres_password surfaces as a per-query "auth failed" message, not a crashed container.

Test plan

  • gh workflow run spin-up.yml --ref feat/stacks/evidence deploys cleanly
  • https://evidence.YOUR_DOMAIN renders the sample page behind CF Access
  • Sample query against the in-stack Postgres returns the table list (or "no rows", indicating connection works but DB is empty — both healthy)
  • Editing stacks/evidence/project/pages/index.md on the server hot-reloads in the browser
  • docker exec evidence npm run sources && docker exec evidence npm run build produces a project/build/ directory (static export path)

No initial-setup.yaml needed — Evidence does not introduce a new secret, so the Tofu state has no new resources beyond the standard subdomain + tunnel + access bindings handled by the generic service-loop.

Files

  • stacks/evidence/docker-compose.yml + sample project (project/package.json, evidence.config.yaml, pages/index.md, sources/nexus_postgres/{connection.yaml,database_overview.sql}, .gitignore)
  • services.yaml entry
  • src/nexus_deploy/service_env.py_render_evidence + EnvSpec registration
  • tests/unit/test_service_env.py — 3 new tests
  • README.md — badge + table row + count
  • docs/stacks/README.md — image-versions table + stack-doc list
  • docs/stacks/evidence.md — full per-stack docs

Evidence is an open-source "BI as code" framework: each page is a
Markdown file with embedded SQL blocks that render to charts, tables,
and inline values. Projects live as plain text and diff in Git, which
makes Evidence a natural complement to the existing code-server /
Gitea / Woodpecker-CI workflow — write a page on a branch, review the
rendered diff, merge.

This stack ships the `evidencedev/devenv` runtime preloaded with a
sample project that queries the in-stack Postgres via env-var
interpolation. Operators extend `stacks/evidence/project/sources/`
to add ClickHouse, Trino, DuckDB/pg_ducklake, Iceberg/Lakekeeper,
or any external warehouse.

Port 3007 → 3000 (3000–3006 are already taken by Metabase /
Uptime-Kuma / Wetty / Hoppscotch / Dagster / Wiki.js / Big-AGI).
Category `analytics` alongside Metabase and Superset.

No Tofu-managed secrets — Evidence pipes through the existing
postgres_password for the bundled sample query; operator-added
sources reference whatever credentials the operator wires into
stacks/evidence/.env.

`evidencedev/devenv:latest` is acceptable under the CLAUDE.md
exception for non-critical standalone tools (Evidence is a
presentation layer with no persistent state beyond cache) and
Evidence does not publish stable devenv tags.

Closes #615
Copilot AI review requested due to automatic review settings May 24, 2026 07:03
@github-actions

github-actions Bot commented May 24, 2026

Copy link
Copy Markdown
Contributor

coverage

Coverage report — nexus_deploy
FileStmtsMissCoverMissing
__init__.py50100% 
_remote.py150100% 
cli.py40100% 
compose_restart.py400100% 
compose_runner.py760100% 
config.py1360100% 
firewall.py2060100% 
gitea.py5875590%691–692, 697, 720–721, 733–734, 770–771, 783–784, 802–803, 828–829, 851–852, 863–864, 919–920, 928–929, 934, 940–941, 965–966, 999–1000, 1003, 1034–1035, 1076–1077, 1082–1083, 1123–1124, 1155–1156, 1179–1180, 1185–1186, 1285–1286, 1291–1292, 1766, 1770, 1791, 1819–1820, 1907
hetzner_capacity.py1260100% 
infisical.py2030100% 
kestra.py176398%223, 427, 768
orchestrator.py6207388%456, 616, 628, 798–799, 804–805, 837–839, 848, 853–855, 866, 903–904, 909–910, 930, 965–966, 971–972, 980, 1005–1006, 1014, 1036–1037, 1042–1043, 1095–1096, 1101–1102, 1335, 1338, 1408, 1414–1415, 1420–1421, 1455, 1562–1563, 1568–1569, 1618–1619, 1624–1625, 1684, 1699, 1756, 1761–1762, 1767–1768, 1775, 1781, 1948, 1955, 1967–1968, 1973–1974, 1980, 1986, 2059–2060, 2081–2082
pipeline.py2071393%165–166, 350, 388, 468, 485, 580–581, 626–627, 717–718, 765
r2_tokens.py113298%87, 150
s3_persistence.py199199%315
s3_restore.py1030100% 
secret_sync.py990100% 
seeder.py980100% 
service_env.py3793391%1062, 1064–1066, 1074–1075, 1403–1406, 1411–1417, 1446–1450, 1466–1470, 1492, 1494, 1516–1517, 1524, 1633
services.py310199%1939
setup.py1651392%238, 308–311, 319, 323–328, 344
ssh.py560100% 
stack_sync.py960100% 
tfvars.py440100% 
tofu.py860100% 
workspace_coords.py1010100% 
TOTAL425019495% 

@codecov

codecov Bot commented May 24, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Evidence stack to Nexus-Stack, providing a Markdown + embedded-SQL “BI as code” runtime (Evidence devenv) with a bundled sample project that queries the in-stack Postgres, plus deploy-time env rendering and documentation updates.

Changes:

  • Introduces stacks/evidence/ (docker-compose + sample Evidence project with Postgres source + example page/query).
  • Registers the stack in services.yaml and wires deploy-time env generation via src/nexus_deploy/service_env.py (plus unit tests).
  • Updates top-level and stack documentation (README, stacks index, new docs/stacks/evidence.md).

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
stacks/evidence/docker-compose.yml New Evidence service definition (ports, env, volume mount, healthcheck).
stacks/evidence/project/pages/index.md Sample Evidence landing page demonstrating SQL-in-Markdown + DataTable.
stacks/evidence/project/sources/nexus_postgres/connection.yaml Evidence Postgres source configured via env-var interpolation.
stacks/evidence/project/sources/nexus_postgres/database_overview.sql Sample query for table list + row-count estimates.
stacks/evidence/project/package.json Sample project scripts and Evidence driver dependencies.
stacks/evidence/project/evidence.config.yaml Evidence config defaults (appearance, basePath).
stacks/evidence/project/.gitignore Ignores node/evidence build artifacts in the sample project.
src/nexus_deploy/service_env.py Adds _render_evidence and registers it in the EnvSpec list.
tests/unit/test_service_env.py Adds unit tests for Evidence env rendering (domain + password piping).
services.yaml Registers the new evidence service (subdomain, port, category, image, descriptions).
README.md Updates stack count and adds Evidence badge + table entry.
docs/stacks/README.md Adds Evidence to images table and stack-doc list.
docs/stacks/evidence.md New stack documentation page for Evidence.

Comment thread stacks/evidence/docker-compose.yml
Comment thread stacks/evidence/project/pages/index.md Outdated
Comment thread docs/stacks/evidence.md Outdated
Comment thread docs/stacks/evidence.md Outdated
- Add `env_file: .env` to evidence compose so operator-added data-source
  credentials in stacks/evidence/.env reach the container for
  ${VAR} interpolation in sources/<name>/connection.yaml.
- Convert the inline-code line-wrapped `docker exec` chain in the
  sample page to a fenced code block — inline spans don't always
  render reliably across a newline.
- Use the on-server absolute path (/opt/docker-server/stacks/evidence/
  project/...) in the Usage and "Building a static site" sections of
  docs/stacks/evidence.md so the doc matches the "on the server"
  framing it uses elsewhere.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Comment thread stacks/evidence/project/sources/nexus_postgres/connection.yaml Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 3 comments.

Comment thread stacks/evidence/docker-compose.yml
Comment thread services.yaml
Comment thread docs/stacks/README.md
Copilot rightly flagged that PR #616 introduces `evidencedev/devenv:latest`
without an explicit CLAUDE.md exemption. Verified upstream
(\`docker hub v2/repositories/evidencedev/devenv/tags\`): only two
tags exist, \`:latest\` (updated 2024-12-13) and \`:ubuntu\` (2023-10-01).
No semver tags published. Digest pinning is technically possible but
adds zero predictability — every refresh would still require a manual
update with no semantic-version migration path, same as the other
entries already on the allow-list.

Extends the exception to include `evidence`, and adds the underlying
rationale (presentation-layer / dev-tool with no persistent state,
upstream publishes no semver) so future stack additions have a
test for the exemption rather than just an opaque list.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Comment thread stacks/evidence/project/sources/nexus_postgres/connection.yaml Outdated
Remove misleading reference to a 'credentials.yaml' file in the
Evidence source comment — Evidence's source structure is just
connection.yaml (with ${VAR} interpolation for any credentials)
plus .sql query files. Legacy versions had a separate
credentials.yaml; current upstream uses inline env-var
interpolation in connection.yaml itself.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.

Comment thread src/nexus_deploy/service_env.py
Comment thread tests/unit/test_service_env.py Outdated
The renderer was emitting `EVIDENCE_DOMAIN=https://...` — a value that
contains the URL scheme. The rest of the codebase consistently reserves
`*_DOMAIN` for bare hostnames (HEDGEDOC_DOMAIN, LAKEKEEPER_DOMAIN) and
uses `*_URL`/`*_BASE_URL` when the value includes the scheme (KESTRA_URL,
CB_SERVER_URL, NC_PUBLIC_URL). Evidence was the only exception, and the
compose file even had to bridge it via `EVIDENCE_BASE_URL: ${EVIDENCE_DOMAIN}`
to match the actual upstream variable name.

Rename to align with both internal convention and upstream's own naming;
drop the now-redundant `EVIDENCE_BASE_URL` line from compose since
env_file already passes the value through.

Also fixes the multi-tenant subdomain test, whose docstring claimed
`evidence-user1.example.com` while the assertion was
`evidence-example.com` (the test only changed the separator, not the
base domain). Test input now includes `domain="user1.example.com"` so
the assertion actually demonstrates the documented behaviour.
@stefanko-ch stefanko-ch merged commit ac9ef64 into main May 27, 2026
8 checks passed
@stefanko-ch stefanko-ch deleted the feat/stacks/evidence branch May 27, 2026 05:58
stefanko-ch pushed a commit that referenced this pull request May 28, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.68.0](v0.67.0...v0.68.0)
(2026-05-28)


### 🚀 Features

* **stacks:** Add Evidence — SQL+markdown BI for analytics engineers
([#616](#616))
([ac9ef64](ac9ef64))


### 🐛 Bug Fixes

* **hedgedoc:** Seeded admin account + R2 snapshot/restore persistence
([#619](#619))
([a04d529](a04d529))
* **pipeline:** Pre-create ollama-internal network when LiteLLM enabled
([#617](#617))
([3ea36be](3ea36be))
* **stacks:** Raise Metabase JVM heap to prevent OOM
([#620](#620))
([70bb786](70bb786))
* **stacks:** Remove hardcoded credential fallbacks (audit C1-C3)
([#623](#623))
([3002629](3002629))
* **stacks:** Resolve host-port 8888 collision (adminer ⇔ seaweedfs)
([#624](#624))
([6831d2c](6831d2c))
* **tofu:** Validate cloudflare_account_id, cloudflare_zone_id, domain
shapes ([#622](#622))
([47f25c6](47f25c6))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(stacks): Add Evidence — SQL+markdown BI for analytics engineers

2 participants