From f9780c2b22d07635411c244e6f2a235c6ab63696 Mon Sep 17 00:00:00 2001 From: deacon Date: Sun, 15 Mar 2026 13:19:58 -0400 Subject: [PATCH 1/3] chore: replace npm install with npm ci in server.py --build flag Use npm ci for deterministic builds from package-lock.json, with fallback to npm install when package-lock.json is missing. --- server.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/server.py b/server.py index 2c2d0702d..dddfe9595 100644 --- a/server.py +++ b/server.py @@ -285,7 +285,12 @@ def list_str(values): if args.build: if os.path.exists(f"{MAGMA_PATH}") and len(os.listdir(MAGMA_PATH)) > 0: logging.info("Building VueJS front-end.") - subprocess.run(["npm", "install"], cwd=MAGMA_PATH, check=True) + package_lock = os.path.join(MAGMA_PATH, "package-lock.json") + if os.path.exists(package_lock): + subprocess.run(["npm", "ci"], cwd=MAGMA_PATH, check=True) + else: + logging.warning("package-lock.json not found, falling back to npm install") + subprocess.run(["npm", "install"], cwd=MAGMA_PATH, check=True) subprocess.run(["npm", "run", "build"], cwd=MAGMA_PATH, check=True) logging.info("VueJS front-end build complete.") else: From ea1898aedd8c44bb0eca321cf05ea0691c8a4589 Mon Sep 17 00:00:00 2001 From: deacon Date: Mon, 16 Mar 2026 00:33:21 -0400 Subject: [PATCH 2/3] fix: address Copilot review feedback - Use os.path.isfile() instead of os.path.exists() for package-lock.json check to avoid false positives from directories with that name - Raise FileNotFoundError instead of falling back to npm install when package-lock.json is missing, preserving reproducible-build guarantee --- server.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/server.py b/server.py index dddfe9595..01793271f 100644 --- a/server.py +++ b/server.py @@ -286,11 +286,14 @@ def list_str(values): if os.path.exists(f"{MAGMA_PATH}") and len(os.listdir(MAGMA_PATH)) > 0: logging.info("Building VueJS front-end.") package_lock = os.path.join(MAGMA_PATH, "package-lock.json") - if os.path.exists(package_lock): + if os.path.isfile(package_lock): subprocess.run(["npm", "ci"], cwd=MAGMA_PATH, check=True) else: - logging.warning("package-lock.json not found, falling back to npm install") - subprocess.run(["npm", "install"], cwd=MAGMA_PATH, check=True) + raise FileNotFoundError( + f"package-lock.json not found at {package_lock}. " + "A lockfile is required for reproducible builds. " + "Commit package-lock.json or run 'npm install' locally to generate it." + ) subprocess.run(["npm", "run", "build"], cwd=MAGMA_PATH, check=True) logging.info("VueJS front-end build complete.") else: From 96e4089dcf4a4bd94feca261de9f358e8bc53322 Mon Sep 17 00:00:00 2001 From: deacon Date: Mon, 16 Mar 2026 09:57:48 -0400 Subject: [PATCH 3/3] Replace FileNotFoundError with warning log when package-lock.json missing Raising FileNotFoundError on --build crashes the server when the frontend is optional. Instead, log a warning and gracefully skip the frontend build step. --- server.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/server.py b/server.py index 01793271f..1b4978143 100644 --- a/server.py +++ b/server.py @@ -288,14 +288,15 @@ def list_str(values): package_lock = os.path.join(MAGMA_PATH, "package-lock.json") if os.path.isfile(package_lock): subprocess.run(["npm", "ci"], cwd=MAGMA_PATH, check=True) + subprocess.run(["npm", "run", "build"], cwd=MAGMA_PATH, check=True) + logging.info("VueJS front-end build complete.") else: - raise FileNotFoundError( - f"package-lock.json not found at {package_lock}. " + logging.warning( + f"[bright_yellow]package-lock.json not found at {package_lock}. " "A lockfile is required for reproducible builds. " - "Commit package-lock.json or run 'npm install' locally to generate it." + "Skipping frontend build. Commit package-lock.json or run " + "'npm install' locally to generate it.[/bright_yellow]" ) - subprocess.run(["npm", "run", "build"], cwd=MAGMA_PATH, check=True) - logging.info("VueJS front-end build complete.") else: logging.warning( f"[bright_yellow]The `--build` flag was supplied, but the Caldera v5 Vue UI is not present."