Skip to content

Commit 8351567

Browse files
a-effortjonpspri
andauthored
Fix/4041 Nav bug & dependency documentation (#4043)
* build(ui): add build-ui Makefile target and gitignore Vite output The Vite bundle (mcpgateway/static/bundle-*.js) is a build artifact generated from mcpgateway/admin_ui/ source. Treat it the same as static/vendor/ — built locally, not committed. - Add `make build-ui` target (uses `npm ci` for reproducible installs) guarded by `command -v npm` check - Wire build-ui into install-dev so a fresh checkout is runnable - Gitignore bundle-*.js and .vite/ alongside existing vendor/ entry - Exclude bundle paths from ESLint (minified, not authored code) - Exclude bundle paths from detect-secrets (false-positive prevention) Closes #4041 Signed-off-by: Anna Effort <anna.effort@datastax.com> Signed-off-by: Mihai Criveti <crivetimihai@gmail.com> * docs: document Admin UI build step for contributors Add the required `make build-ui` (or `npm ci && npm run vite:build`) step to README.md, AGENTS.md, and docs/docs/development/building.md so contributors know to build the Admin UI bundle after cloning. Signed-off-by: Anna Effort <anna.effort@datastax.com> Signed-off-by: Mihai Criveti <crivetimihai@gmail.com> * build(ui): fail fast when Admin UI build prerequisites are missing Make `make build-ui` exit non-zero with an actionable message when npm is absent (with a SKIP_UI_BUILD=1 escape hatch for headless deployments), so `make install-dev` surfaces missing prerequisites at install time instead of leaving /admin to fail at runtime with "No bundle-*.js found". Provision Node via the official devcontainers feature so Codespaces / devcontainer setup still completes end-to-end under the new fail-fast behavior, and document the prerequisite + bypass in the building guide. Signed-off-by: Jonathan Springer <jps@s390x.com> --------- Signed-off-by: Anna Effort <anna.effort@datastax.com> Signed-off-by: Mihai Criveti <crivetimihai@gmail.com> Signed-off-by: Jonathan Springer <jps@s390x.com> Co-authored-by: Jonathan Springer <jps@s390x.com>
1 parent ddecc7c commit 8351567

8 files changed

Lines changed: 90 additions & 20 deletions

File tree

.devcontainer/devcontainer.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,11 @@
44
"dockerfile": "Dockerfile",
55
"context": ".."
66
},
7-
"features": {},
7+
"features": {
8+
"ghcr.io/devcontainers/features/node:1": {
9+
"version": "lts"
10+
}
11+
},
812
"postCreateCommand": ".devcontainer/postCreateCommand.sh",
913
"customizations": {
1014
"vscode": {

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -272,8 +272,10 @@ uv.lock
272272
certs/
273273
jwt/
274274

275-
# Static assets (downloaded during container build)
275+
# Static assets (downloaded or built during container build)
276276
mcpgateway/static/vendor/
277+
mcpgateway/static/bundle-*.js
278+
mcpgateway/static/.vite/
277279
public/
278280

279281
# Export & SBOM files

.secrets.baseline

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"files": "^.secrets.baseline|package-lock.json|Cargo.lock|scripts/sign_image.sh|scripts/zap|sonar-project.properties|uv.lock|^.secrets.baseline$",
44
"lines": null
55
},
6-
"generated_at": "2026-04-11T14:12:29Z",
6+
"generated_at": "2026-04-11T14:31:54Z",
77
"plugins_used": [
88
{
99
"name": "AWSKeyDetector"
@@ -200,39 +200,39 @@
200200
"hashed_secret": "f4793151b0607198d4de9b1ca458d3e25adf1cb7",
201201
"is_secret": false,
202202
"is_verified": false,
203-
"line_number": 111,
203+
"line_number": 112,
204204
"type": "Secret Keyword",
205205
"verified_result": null
206206
},
207207
{
208208
"hashed_secret": "fa9beb99e4029ad5a6615399e7bbae21356086b3",
209209
"is_secret": false,
210210
"is_verified": false,
211-
"line_number": 187,
211+
"line_number": 188,
212212
"type": "Secret Keyword",
213213
"verified_result": null
214214
},
215215
{
216216
"hashed_secret": "7b4455a56fbf1d198e45e04c437488514645a82c",
217217
"is_secret": false,
218218
"is_verified": false,
219-
"line_number": 189,
219+
"line_number": 190,
220220
"type": "Secret Keyword",
221221
"verified_result": null
222222
},
223223
{
224224
"hashed_secret": "90bd1b48e958257948487b90bee080ba5ed00caa",
225225
"is_secret": false,
226226
"is_verified": false,
227-
"line_number": 261,
227+
"line_number": 262,
228228
"type": "Hex High Entropy String",
229229
"verified_result": null
230230
},
231231
{
232232
"hashed_secret": "48ffbad96aa9c2b33f9486f5a3c2108198acb518",
233233
"is_secret": false,
234234
"is_verified": false,
235-
"line_number": 262,
235+
"line_number": 263,
236236
"type": "Hex High Entropy String",
237237
"verified_result": null
238238
}
@@ -344,79 +344,79 @@
344344
"hashed_secret": "844c398e469ef3fb919da3778944365ab2175fb7",
345345
"is_secret": false,
346346
"is_verified": false,
347-
"line_number": 441,
347+
"line_number": 469,
348348
"type": "Secret Keyword",
349349
"verified_result": null
350350
},
351351
{
352352
"hashed_secret": "319037749ce37e577db0b3628c7f90e333544391",
353353
"is_secret": false,
354354
"is_verified": false,
355-
"line_number": 865,
355+
"line_number": 893,
356356
"type": "Secret Keyword",
357357
"verified_result": null
358358
},
359359
{
360360
"hashed_secret": "6ae2832e494d1098e8901fe156083e39399a24f1",
361361
"is_secret": false,
362362
"is_verified": false,
363-
"line_number": 867,
363+
"line_number": 895,
364364
"type": "Secret Keyword",
365365
"verified_result": null
366366
},
367367
{
368368
"hashed_secret": "43fc45734b96bcb1b6cef373e949eb3524ae199b",
369369
"is_secret": false,
370370
"is_verified": false,
371-
"line_number": 1558,
371+
"line_number": 1586,
372372
"type": "Secret Keyword",
373373
"verified_result": null
374374
},
375375
{
376376
"hashed_secret": "9d989e8d27dc9e0ec3389fc855f142c3d40f0c50",
377377
"is_secret": false,
378378
"is_verified": false,
379-
"line_number": 1769,
379+
"line_number": 1797,
380380
"type": "Secret Keyword",
381381
"verified_result": null
382382
},
383383
{
384384
"hashed_secret": "d3ac7a4ef1a838b4134f2f6e7f3c0d249d74b674",
385385
"is_secret": false,
386386
"is_verified": false,
387-
"line_number": 6113,
387+
"line_number": 6141,
388388
"type": "Secret Keyword",
389389
"verified_result": null
390390
},
391391
{
392392
"hashed_secret": "5932862bcd24dd27d0dc0407ec94fe9d6ea24aeb",
393393
"is_secret": false,
394394
"is_verified": false,
395-
"line_number": 6610,
395+
"line_number": 6638,
396396
"type": "Secret Keyword",
397397
"verified_result": null
398398
},
399399
{
400400
"hashed_secret": "c77c805e32f173e4321ee9187de9c29cb3804513",
401401
"is_secret": false,
402402
"is_verified": false,
403-
"line_number": 6622,
403+
"line_number": 6650,
404404
"type": "Secret Keyword",
405405
"verified_result": null
406406
},
407407
{
408408
"hashed_secret": "8fe3df8a68ddd0d4ab2214186cbb8e38ccd0e06a",
409409
"is_secret": false,
410410
"is_verified": false,
411-
"line_number": 6694,
411+
"line_number": 6722,
412412
"type": "Secret Keyword",
413413
"verified_result": null
414414
},
415415
{
416416
"hashed_secret": "93ac8946882128457cd9e283b30ca851945e6690",
417417
"is_secret": false,
418418
"is_verified": false,
419-
"line_number": 7765,
419+
"line_number": 7793,
420420
"type": "Secret Keyword",
421421
"verified_result": null
422422
}

AGENTS.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,9 @@ llms/ # End-user LLM guidance (not for code agents)
4848
```bash
4949
cp .env.example .env && make install-dev check-env # Complete setup
5050
make venv # Create virtual environment with uv
51-
make install-dev # Install with dev dependencies
51+
make install-dev # Install with dev dependencies (includes build-ui)
5252
make check-env # Verify .env against .env.example
53+
make build-ui # Rebuild Admin UI JS bundle (requires npm)
5354
```
5455

5556
### Development

Makefile

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,34 @@ install-db: venv
272272
.PHONY: install-dev
273273
install-dev: venv
274274
@/bin/bash -c "source $(VENV_DIR)/bin/activate && $(UV_BIN) pip install --group dev '.[plugins]'"
275+
@if [ "$(ENABLE_RUST_BUILD)" = "1" ]; then \
276+
echo "🦀 Building Rust plugins..."; \
277+
$(MAKE) rust-dev || echo "⚠️ Rust plugins not available (optional)"; \
278+
else \
279+
echo "⏭️ Rust builds disabled (set ENABLE_RUST_BUILD=1 to enable)"; \
280+
fi
281+
@$(MAKE) build-ui
282+
283+
# help: build-ui - Build Admin UI JS bundle with Vite (requires npm; set SKIP_UI_BUILD=1 to bypass)
284+
.PHONY: build-ui
285+
build-ui:
286+
@if [ "$(SKIP_UI_BUILD)" = "1" ]; then \
287+
echo "⏭️ SKIP_UI_BUILD=1 — skipping Admin UI build (the Admin UI will not load at runtime)"; \
288+
elif command -v npm >/dev/null 2>&1; then \
289+
echo "🔨 Building Admin UI bundle..."; \
290+
if [ -f package-lock.json ]; then \
291+
npm ci --no-audit --no-fund; \
292+
else \
293+
echo "ℹ️ package-lock.json not found — falling back to 'npm install'"; \
294+
npm install --no-audit --no-fund; \
295+
fi && \
296+
npm run vite:build; \
297+
else \
298+
echo "❌ npm not found — install Node.js (https://nodejs.org) to build the Admin UI."; \
299+
echo " Without the bundle, /admin will fail to load at runtime."; \
300+
echo " To bypass this step intentionally, re-run with SKIP_UI_BUILD=1."; \
301+
exit 1; \
302+
fi
275303

276304
.PHONY: update
277305
update:

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,7 @@ For detailed setup, workflows, and GitHub Codespaces instructions, see **[Develo
655655
## Installation
656656

657657
```bash
658-
make venv install # create .venv + install deps
658+
make venv install-dev # create .venv + install deps + build Admin UI
659659
make serve # gunicorn on :4444
660660
```
661661

docs/docs/development/building.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,37 @@ The Admin UI uses plain JavaScript (not TypeScript). Frontend tooling requires N
101101
npm install # install frontend dev dependencies
102102
```
103103

104+
### Building the Admin UI Bundle
105+
106+
The Admin UI JavaScript is bundled with Vite. The bundle is **not committed** to the repository — it must be built locally. `make install-dev` invokes `make build-ui` automatically, and the step is required: without a bundle, `/admin` will fail to load at runtime with `No bundle-*.js found`. Rebuild after any changes to files under `mcpgateway/admin_ui/`.
107+
108+
**Node.js is a prerequisite.** If `npm` is missing, `make build-ui` (and therefore `make install-dev`) fails fast rather than leaving a broken install. Install Node.js from <https://nodejs.org> before running setup.
109+
110+
```bash
111+
make build-ui # build mcpgateway/static/bundle-<hash>.js (requires npm)
112+
```
113+
114+
If you genuinely do not need the Admin UI (for example, a headless API-only deployment where `MCPGATEWAY_UI_ENABLED=false`), bypass the step with:
115+
116+
```bash
117+
SKIP_UI_BUILD=1 make install-dev
118+
```
119+
120+
Or build manually:
121+
122+
```bash
123+
npm ci # install dependencies from lockfile (falls back to `npm install` if lockfile absent)
124+
npm run vite:build # produce mcpgateway/static/bundle-<hash>.js
125+
```
126+
127+
The server reads `mcpgateway/static/.vite/manifest.json` at startup to locate the hashed bundle filename.
128+
129+
For iterative development you can use watch mode:
130+
131+
```bash
132+
npx vite build --watch
133+
```
134+
104135
### Linting & Formatting
105136

106137
```bash

eslint.config.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
const neostandard = require("neostandard");
33

44
module.exports = [
5+
// Ignore compiled build artefacts — these are minified and not authored code
6+
{
7+
ignores: ["mcpgateway/static/bundle-*.js", "mcpgateway/static/.vite/**"],
8+
},
59
...neostandard({
610
env: ["browser"],
711
ignores: neostandard.resolveIgnoresFromGitignore(),

0 commit comments

Comments
 (0)