From 3284d1bf35b7d6c4c82a58dd43ae536869721203 Mon Sep 17 00:00:00 2001 From: Phil Edwards Date: Thu, 20 Nov 2025 16:59:19 -0500 Subject: [PATCH 1/3] Add script for mix-and-match backend + frontend Add helper script for running backend and frontend on 2 different branches --- scripts/disjoint.sh | 95 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100755 scripts/disjoint.sh diff --git a/scripts/disjoint.sh b/scripts/disjoint.sh new file mode 100755 index 0000000000..3a220f99d7 --- /dev/null +++ b/scripts/disjoint.sh @@ -0,0 +1,95 @@ +#!/usr/bin/env bash + +# +# Disjoint / Split mode +# +# Run KPI in 2 separate parts, one for frontend and one for backend, +# so the frontend and backend can be on different git branches. +# +# Run this script with two parameters: +# +# disjoint.sh -b -f +# +# This will: +# +# - Copy webpack-stats.json output from the frontend to the backend +# - Re-copy continually (watch for changes to the frontend) until ^C. +# +# Before running, you'll need to do these steps manually: +# +# 1. Clone kpi in two different locations. +# 2. From , start your backend server +# 3. From , start the frontend in watch mode (npm run watch) +# + +backend="" +frontend="" + +## +## Argument parsing +## + +usage="Usage: $0 -b -f " +help_deps="file watcher requires uvx or npx" + +# Parse -b and -f flags +OPTIND=1 +while getopts "h?b:f:" opt; do + case "$opt" in + b) backend=$(realpath "$OPTARG");; + f) frontend=$(realpath "$OPTARG");; + h|\?) + echo "$usage" + exit 0;; + esac +done + +# Exit with usage if -b or -f is missing +if [[ -z $frontend || -z $backend ]]; then + echo "$usage"; exit 1; fi +if [[ "$frontend" == "$backend" ]]; then + echo "frontend and backend directory should not be the same"; exit 1; fi + +echo " backend: $backend" +echo " frontend: $frontend" + + +## +## Copy once +## + +copy_cmd="cp ${frontend}/webpack-stats.json ${backend}/webpack-stats.json" +if [[ ! -f "${frontend}/webpack-stats.json" ]] +then echo "! Make sure to start the frontend ($frontend) with \`npm run watch\`" +else $copy_cmd; fi + +## +## Watch & copy until ^C +## + +pattern='webpack-stats.json' +cd "$frontend" || exit 1 + +# Watcher: if uvx is available, use 'watchdog' +if command -v uvx >/dev/null 2>&1; then + echo 'Watching "webpack-stats.json" ..'; set -x + uvx --from watchdog@6.0.0 \ + watchmedo \ + shell-command -w \ + --patterns="$pattern" \ + --command="$copy_cmd" + exit 0 +fi + +# Watcher: if npx is available, use 'chokidar-cli' +npx() { + if command -v bunx >/dev/null 2>&1; then echo "bunx" + elif command -v npx >/dev/null 2>&1; then echo "npx" + else echo "$help_deps"; exit 1; fi # last strategy; exit if unavailable +} +set -x +$(npx) --package=chokidar-cli@3.0.0 \ + chokidar \ + "$pattern" \ + --command="$copy_cmd" +exit 0 From 718ef4db8884cee0452b53f52c697bb2ec0a698b Mon Sep 17 00:00:00 2001 From: Phil Edwards Date: Mon, 24 Nov 2025 09:28:09 -0500 Subject: [PATCH 2/3] More descriptive script name --- scripts/{disjoint.sh => split-frontend.sh} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename scripts/{disjoint.sh => split-frontend.sh} (97%) diff --git a/scripts/disjoint.sh b/scripts/split-frontend.sh similarity index 97% rename from scripts/disjoint.sh rename to scripts/split-frontend.sh index 3a220f99d7..6f09819b42 100755 --- a/scripts/disjoint.sh +++ b/scripts/split-frontend.sh @@ -8,7 +8,7 @@ # # Run this script with two parameters: # -# disjoint.sh -b -f +# split-frontend.sh -b -f # # This will: # From 92b8cf9560364388a02c992a3464d75600e795c1 Mon Sep 17 00:00:00 2001 From: Phil Edwards Date: Mon, 24 Nov 2025 15:03:20 -0500 Subject: [PATCH 3/3] Fix npx invocation, warn for file ownership --- scripts/split-frontend.sh | 57 ++++++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/scripts/split-frontend.sh b/scripts/split-frontend.sh index 6f09819b42..077ba0b503 100755 --- a/scripts/split-frontend.sh +++ b/scripts/split-frontend.sh @@ -50,18 +50,42 @@ if [[ -z $frontend || -z $backend ]]; then if [[ "$frontend" == "$backend" ]]; then echo "frontend and backend directory should not be the same"; exit 1; fi +echo "" echo " backend: $backend" echo " frontend: $frontend" +echo "" + +set -euo pipefail ## ## Copy once ## - copy_cmd="cp ${frontend}/webpack-stats.json ${backend}/webpack-stats.json" + if [[ ! -f "${frontend}/webpack-stats.json" ]] then echo "! Make sure to start the frontend ($frontend) with \`npm run watch\`" -else $copy_cmd; fi +else + + echo "+ $copy_cmd" + echo "" + + # Warn if we encounter permissions problem + set +e + { error_output=$($copy_cmd 2>&1 >&3 3>&-); } 3>&1 + if [[ $? -ne 0 ]]; then + echo " ! Problem copying webpack-stats.json" + if [[ $error_output =~ "denied" ]]; then + echo " ! You may need to change ownership if these files are owned by 'root'." + echo " " + echo " sudo chown -Rv $(id -un):$(id -gn) ${backend}" + echo " " + echo "$(ls -al $backend | grep 'root')" + exit 1 + fi + fi + set -e +fi ## ## Watch & copy until ^C @@ -70,9 +94,10 @@ else $copy_cmd; fi pattern='webpack-stats.json' cd "$frontend" || exit 1 -# Watcher: if uvx is available, use 'watchdog' +## Watcher: if uvx is available, use 'watchdog' if command -v uvx >/dev/null 2>&1; then - echo 'Watching "webpack-stats.json" ..'; set -x + echo 'Watching "webpack-stats.json" ..' + set -x uvx --from watchdog@6.0.0 \ watchmedo \ shell-command -w \ @@ -81,15 +106,15 @@ if command -v uvx >/dev/null 2>&1; then exit 0 fi -# Watcher: if npx is available, use 'chokidar-cli' -npx() { - if command -v bunx >/dev/null 2>&1; then echo "bunx" - elif command -v npx >/dev/null 2>&1; then echo "npx" - else echo "$help_deps"; exit 1; fi # last strategy; exit if unavailable -} -set -x -$(npx) --package=chokidar-cli@3.0.0 \ - chokidar \ - "$pattern" \ - --command="$copy_cmd" -exit 0 +## Watcher: if npx is available, use 'chokidar-cli' +if command -v npx >/dev/null 2>&1; then + set -x + npx --package=chokidar-cli@3.0.0 -- \ + chokidar \ + "${pattern}" \ + --command="${copy_cmd}" + exit 0 +fi + +# Fallback: If none of the above watchers are available, print a warning. +echo "$help_deps"; exit 1