Skip to content

webui: add CI dist-freshness gate for committed frontend build (#80) - #98

Merged
IceRhymers merged 1 commit into
integration/search-hardening-and-ci-integrityfrom
feat/80-webui-dist-freshness-gate
Jul 24, 2026
Merged

webui: add CI dist-freshness gate for committed frontend build (#80)#98
IceRhymers merged 1 commit into
integration/search-hardening-and-ci-integrityfrom
feat/80-webui-dist-freshness-gate

Conversation

@IceRhymers

Copy link
Copy Markdown
Owner

Summary

Adds a CI gate that fails whenever the committed webui/frontend/dist/ is stale relative to frontend source/config, with zero change to the no-Node deploy model.

  • New make webui-verify-dist target: rebuilds the frontend (npm ci && npm run build), then checks git status --porcelain -- webui/frontend/dist. Fails with a diagnostic (status + diff --stat) if non-empty.
  • New CI step "Dist freshness (issue webui: add CI dist-freshness gate for committed frontend build #80)" in the webui job of .github/workflows/ci.yml, run after "Frontend tests" at repo root.
  • Updates the three doc locations that claimed "there is no build-time check that dist/ and src/ are in sync": webui/AGENTS.md:29, webui/frontend/AGENTS.md:28, webui/frontend/README.md:22.
  • Adds a make webui-verify-dist line to the root README dev-commands section.

Deliberate deviation from the issue's literal git diff --exit-code: uses git status --porcelain -- <path> instead, because .gitignore re-includes webui/frontend/dist/ (!webui/frontend/dist/) and vite emits content-hashed filenames — a source change typically produces a new untracked chunk alongside a deleted old one. git diff --exit-code only catches modified/deleted tracked files and misses the untracked new chunk; git status --porcelain catches all three cases. Empirically confirmed in this PR's negative self-test (see below).

Out of scope (per plan): no engines pinning in package.json, no Node in deploy, no changes to webui/main.py, no pre-commit hooks.

Refs #80

Test plan

  • make lint — green (ruff check, ruff format --check, mypy incl. webui) after uv sync --all-groups --all-extras
  • make test — green: 1057 passed, 237 deselected
  • make webui-test — green: 12 test files, 207 tests passed
  • Positive self-test: make webui-verify-dist on the clean branch → exit 0, git status --porcelain -- webui/frontend/dist clean
  • Negative self-test: temporarily edited a visible string in webui/frontend/src/App.tsx, ran make webui-verify-dist → failed (exit 1), correctly listed a deleted tracked chunk (D), a modified index.html (M), and a new untracked hashed chunk (??) — confirming the porcelain-vs-diff deviation catches what git diff --exit-code would miss. Reverted the edit, rebuilt, re-ran → exit 0, dist clean again (original hash restored).
  • Real acceptance evidence: this PR itself triggers the new CI step; a green webui job on this PR is the gate working on real CI.
  • Node-20 pre-merge verification: no Node version manager (mise/nvm/asdf/volta/n) is available in this execution environment to test against Node 20 locally. Per the plan's contingency: reproducibility was verified locally on Node 25 (fresh rebuild reproduces the committed dist byte-for-byte); Node 20 conformance will be confirmed by this PR's own webui CI job (Node 20 per ci.yml). A red first CI run here should be treated as a real determinism finding to fix before merge, not a flake.
  • Independent code-review pass (code-reviewer agent) completed: APPROVE, zero CRITICAL/HIGH findings. One non-blocking MEDIUM (cross-Node-version build nondeterminism — inherent to this approach, covered by the Node-20 verification note above) and three optional LOW style suggestions (redundant npm ci, target not chained off webui-build, empty diff --stat on untracked-only staleness) — accepted as-is per the plan's explicit "self-contained target" design choice.

Notes

Add a `webui-verify-dist` Makefile target that rebuilds the frontend
and fails if the committed dist/ diverges from src/, wired into CI's
webui job. Uses `git status --porcelain` (not `git diff --exit-code`)
so untracked new hashed chunks are caught, not just modified/deleted
files. Updates the three docs that claimed no such check existed.

Refs #80
@IceRhymers
IceRhymers merged commit 9c4f679 into integration/search-hardening-and-ci-integrity Jul 24, 2026
4 checks passed
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.

1 participant