Skip to content

Commit 1ef9b11

Browse files
fix frontend bujilder
1 parent 27511d7 commit 1ef9b11

2 files changed

Lines changed: 146 additions & 29 deletions

File tree

scripts/rebuild_frontend.sh

Lines changed: 131 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ STATIC_FRONTEND="${REPO_ROOT}/hpcperfstats/site/hpcperfstats_site/static/fronten
2020
CONTAINER_STATIC_FRONTEND="/home/hpcperfstats/hpcperfstats/site/hpcperfstats_site/static/frontend"
2121
CONTAINER_STATIC_ROOT="${CONTAINER_STATIC_ROOT:-/home/hpcperfstats/staticfiles}"
2222
CONTAINER_STATIC_ROOT_FRONTEND="${CONTAINER_STATIC_ROOT}/frontend"
23+
PROXY_STATIC_ROOT_FRONTEND="/srv/static/frontend"
2324
NODE_IMAGE="node:26.3.0-alpine3.23"
2425

2526
# Next static export shells nginx serves (see services-conf/nginx-static-files.conf).
@@ -148,6 +149,7 @@ build_in_docker() {
148149

149150
verify_build_output() {
150151
verify_spa_shells "${STATIC_FRONTEND}"
152+
print_deploy_fingerprint "host build" "${STATIC_FRONTEND}/machine/index.html"
151153
echo "Built frontend static export: ${STATIC_FRONTEND}"
152154
}
153155

@@ -179,6 +181,56 @@ file_sha256() {
179181
fi
180182
}
181183

184+
frontend_build_fingerprint() {
185+
local index_html="$1"
186+
if [[ ! -f "${index_html}" ]]; then
187+
echo "unknown"
188+
return
189+
fi
190+
local fingerprint
191+
fingerprint="$(grep -oE 'page-[0-9a-f]+\.js' "${index_html}" | head -n 1 || true)"
192+
if [[ -n "${fingerprint}" ]]; then
193+
echo "${fingerprint}"
194+
return
195+
fi
196+
grep -oE '<!--[^>]{8,}-->' "${index_html}" | head -n 1 | tr -d '<!->' || echo "unknown"
197+
}
198+
199+
print_deploy_fingerprint() {
200+
local label="$1"
201+
local index_html="$2"
202+
local fingerprint
203+
fingerprint="$(frontend_build_fingerprint "${index_html}")"
204+
echo "Deploy fingerprint (${label}): ${fingerprint}"
205+
}
206+
207+
print_container_deploy_fingerprint() {
208+
local label="$1"
209+
local service="$2"
210+
local container_path="$3"
211+
local fingerprint
212+
fingerprint="$(
213+
docker compose exec -T "${service}" sh -lc \
214+
"grep -oE 'page-[0-9a-f]+\\.js' '${container_path}' 2>/dev/null | head -n 1 || echo unknown"
215+
)"
216+
echo "Deploy fingerprint (${label}): ${fingerprint}"
217+
}
218+
219+
count_files_under() {
220+
local root="$1"
221+
find "${root}" -type f 2>/dev/null | wc -l | tr -d ' '
222+
}
223+
224+
count_files_in_web_container() {
225+
local container_dir="$1"
226+
docker compose exec -T web bash -lc "find '${container_dir}' -type f 2>/dev/null | wc -l | tr -d ' '"
227+
}
228+
229+
count_files_in_proxy_container() {
230+
local container_dir="$1"
231+
docker compose exec -T proxy sh -lc "find '${container_dir}' -type f 2>/dev/null | wc -l | tr -d ' '"
232+
}
233+
182234
reset_container_dir() {
183235
local cid="$1"
184236
local target_dir="$2"
@@ -195,19 +247,13 @@ copy_tree_via_compose_cp() {
195247
docker compose cp "${STATIC_FRONTEND}/." "web:${dest}/"
196248
}
197249

198-
copy_tree_via_podman_cp() {
199-
local cid="$1"
200-
local dest="$2"
201-
podman cp "${STATIC_FRONTEND}/." "${cid}:${dest}/"
202-
}
203-
204250
copy_tree_via_podman_exec_tar() {
205251
local cid="$1"
206252
local dest="$2"
207253
tar -C "${STATIC_FRONTEND}" -cf - . | podman exec -i "${cid}" tar -xf - -C "${dest}"
208254
}
209255

210-
copy_frontend_tree_into_web() {
256+
copy_tree_into_container() {
211257
local cid="$1"
212258
local dest="$2"
213259

@@ -227,15 +273,9 @@ copy_frontend_tree_into_web() {
227273
exit 1
228274
fi
229275

230-
echo "rebuild_frontend.sh: compose cp unavailable; resetting ${dest}" >&2
231-
reset_container_dir "${cid}" "${dest}"
232-
233-
if copy_tree_via_podman_cp "${cid}" "${dest}"; then
234-
echo "rebuild_frontend.sh: copied frontend tree via podman cp → ${dest}" >&2
235-
return
236-
fi
237-
238-
echo "rebuild_frontend.sh: podman cp failed; trying podman exec -i tar pipe → ${dest}" >&2
276+
# podman cp can write to the container layer instead of a bind-mounted volume on some
277+
# podman-compose setups; streaming tar through podman exec -i targets the mount reliably.
278+
echo "rebuild_frontend.sh: copying via podman exec -i tar → ${dest}" >&2
239279
reset_container_dir "${cid}" "${dest}"
240280
copy_tree_via_podman_exec_tar "${cid}" "${dest}"
241281
}
@@ -247,11 +287,23 @@ copy_frontend_into_web() {
247287

248288
# nginx (proxy) reads STATIC_ROOT/frontend from the shared staticfiles_data volume.
249289
reset_container_dir "${cid}" "${CONTAINER_STATIC_ROOT_FRONTEND}"
250-
copy_frontend_tree_into_web "${cid}" "${CONTAINER_STATIC_ROOT_FRONTEND}"
290+
copy_tree_into_container "${cid}" "${CONTAINER_STATIC_ROOT_FRONTEND}"
251291

252292
# Keep image source tree in sync for future collectstatic / container rebuilds.
253293
reset_container_dir "${cid}" "${CONTAINER_STATIC_FRONTEND}"
254-
copy_frontend_tree_into_web "${cid}" "${CONTAINER_STATIC_FRONTEND}"
294+
copy_tree_into_container "${cid}" "${CONTAINER_STATIC_FRONTEND}"
295+
}
296+
297+
sha256_in_web_container() {
298+
local container_path="$1"
299+
docker compose exec -T web bash -lc \
300+
"if [[ ! -f '${container_path}' ]]; then exit 2; fi; sha256sum '${container_path}' | awk '{print \$1}'"
301+
}
302+
303+
sha256_in_proxy_container() {
304+
local container_path="$1"
305+
docker compose exec -T proxy sh -lc \
306+
"if [[ ! -f '${container_path}' ]]; then exit 2; fi; sha256sum '${container_path}' | awk '{print \$1}'"
255307
}
256308

257309
verify_container_path_matches_host() {
@@ -262,10 +314,7 @@ verify_container_path_matches_host() {
262314
local host_sha container_sha
263315

264316
host_sha="$(file_sha256 "${host_probe}")"
265-
container_sha="$(
266-
docker compose exec -T web bash -lc \
267-
"if [[ ! -f '${container_probe}' ]]; then exit 2; fi; sha256sum '${container_probe}' | awk '{print \$1}'"
268-
)"
317+
container_sha="$(sha256_in_web_container "${container_probe}")"
269318

270319
if [[ -z "${container_sha}" ]]; then
271320
echo "rebuild_frontend.sh: ${label} probe missing after copy: ${container_probe}" >&2
@@ -282,6 +331,59 @@ verify_container_path_matches_host() {
282331
echo "Verified ${label} matches host (${container_probe})"
283332
}
284333

334+
verify_container_file_count_matches_host() {
335+
local container_dir="$1"
336+
local label="$2"
337+
local host_count container_count
338+
339+
host_count="$(count_files_under "${STATIC_FRONTEND}")"
340+
container_count="$(count_files_in_web_container "${container_dir}")"
341+
342+
if [[ "${host_count}" != "${container_count}" ]]; then
343+
echo "rebuild_frontend.sh: ${label} file count mismatch (host ${host_count}, web ${container_count})" >&2
344+
return 1
345+
fi
346+
347+
echo "Verified ${label} file count matches host (${host_count} files)"
348+
}
349+
350+
verify_proxy_frontend_matches_web() {
351+
local web_probe="${CONTAINER_STATIC_ROOT_FRONTEND}/machine/index.html"
352+
local proxy_probe="${PROXY_STATIC_ROOT_FRONTEND}/machine/index.html"
353+
local web_sha proxy_sha
354+
355+
web_sha="$(sha256_in_web_container "${web_probe}")"
356+
proxy_sha="$(sha256_in_proxy_container "${proxy_probe}")"
357+
358+
if [[ -z "${proxy_sha}" ]]; then
359+
echo "rebuild_frontend.sh: proxy nginx volume missing ${proxy_probe}" >&2
360+
return 1
361+
fi
362+
363+
if [[ "${web_sha}" != "${proxy_sha}" ]]; then
364+
echo "rebuild_frontend.sh: proxy nginx volume does not match web STATIC_ROOT" >&2
365+
echo " web: ${web_sha} (${web_probe})" >&2
366+
echo " proxy: ${proxy_sha} (${proxy_probe})" >&2
367+
return 1
368+
fi
369+
370+
echo "Verified proxy nginx volume matches web (${proxy_probe})"
371+
}
372+
373+
verify_proxy_file_count_matches_web() {
374+
local web_count proxy_count
375+
376+
web_count="$(count_files_in_web_container "${CONTAINER_STATIC_ROOT_FRONTEND}")"
377+
proxy_count="$(count_files_in_proxy_container "${PROXY_STATIC_ROOT_FRONTEND}")"
378+
379+
if [[ "${web_count}" != "${proxy_count}" ]]; then
380+
echo "rebuild_frontend.sh: proxy file count mismatch (web ${web_count}, proxy ${proxy_count})" >&2
381+
return 1
382+
fi
383+
384+
echo "Verified proxy nginx volume file count matches web (${web_count} files)"
385+
}
386+
285387
verify_container_frontend_matches_host() {
286388
verify_container_path_matches_host "${CONTAINER_STATIC_ROOT_FRONTEND}" "STATIC_ROOT/frontend (nginx volume)"
287389
}
@@ -297,10 +399,15 @@ deploy_to_compose() {
297399
echo "Copying built assets into web:${CONTAINER_STATIC_ROOT_FRONTEND} (nginx staticfiles volume) ..."
298400
copy_frontend_into_web
299401
verify_container_frontend_matches_host
402+
verify_container_file_count_matches_host "${CONTAINER_STATIC_ROOT_FRONTEND}" "STATIC_ROOT/frontend (nginx volume)"
300403
verify_spa_shells_via_compose "${CONTAINER_STATIC_ROOT_FRONTEND}" "STATIC_ROOT/frontend"
404+
verify_proxy_frontend_matches_web
405+
verify_proxy_file_count_matches_web
406+
print_container_deploy_fingerprint "web STATIC_ROOT" web "${CONTAINER_STATIC_ROOT_FRONTEND}/machine/index.html"
407+
print_container_deploy_fingerprint "proxy nginx volume" proxy "${PROXY_STATIC_ROOT_FRONTEND}/machine/index.html"
301408

302-
echo "Frontend deploy complete. nginx serves updated /static/ and /machine/ assets."
303-
echo "Pipeline was not restarted. Hard-refresh the browser to load new bundle hashes."
409+
echo "Frontend deploy complete. Use the proxy service (ports 80/443), not web:8000 — Gunicorn does not serve /machine/."
410+
echo "Hard-refresh the browser and confirm the deploy fingerprint above matches page-*.js in DevTools Network."
304411
}
305412

306413
main() {

scripts/test_rebuild_frontend_verify.sh

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,30 @@ cleanup() {
1515
}
1616
trap cleanup EXIT
1717

18-
for fn in copy_frontend_into_web compose_cp_supported web_container_id verify_container_frontend_matches_host; do
18+
for fn in copy_frontend_into_web compose_cp_supported web_container_id verify_container_frontend_matches_host verify_proxy_frontend_matches_web print_container_deploy_fingerprint; do
1919
if ! declare -F "${fn}" >/dev/null; then
2020
echo "expected ${fn} to be defined in rebuild_frontend.sh" >&2
2121
exit 1
2222
fi
2323
done
2424

25-
if ! grep -q 'copy_tree_via_podman_cp' "${REBUILD_SCRIPT}"; then
26-
echo "expected podman cp fallback in rebuild_frontend.sh" >&2
25+
if ! grep -q 'copy_tree_via_podman_exec_tar' "${REBUILD_SCRIPT}"; then
26+
echo "expected podman exec -i tar deploy path in rebuild_frontend.sh" >&2
2727
exit 1
2828
fi
2929

30-
if ! grep -q 'podman exec -i' "${REBUILD_SCRIPT}"; then
31-
echo "expected podman exec -i tar fallback in rebuild_frontend.sh" >&2
30+
if ! grep -q 'podman exec -i tar →' "${REBUILD_SCRIPT}"; then
31+
echo "expected podman exec -i tar as primary podman deploy in rebuild_frontend.sh" >&2
32+
exit 1
33+
fi
34+
35+
if ! grep -q 'verify_proxy_frontend_matches_web' "${REBUILD_SCRIPT}"; then
36+
echo "expected proxy nginx volume verification in rebuild_frontend.sh" >&2
37+
exit 1
38+
fi
39+
40+
if ! grep -q 'PROXY_STATIC_ROOT_FRONTEND' "${REBUILD_SCRIPT}"; then
41+
echo "expected PROXY_STATIC_ROOT_FRONTEND in rebuild_frontend.sh" >&2
3242
exit 1
3343
fi
3444

0 commit comments

Comments
 (0)