@@ -158,9 +158,24 @@ web_service_running() {
158158 docker compose exec -T web true > /dev/null 2>&1
159159}
160160
161- web_container_id () {
161+ web_container_ref () {
162162 cd " ${REPO_ROOT} "
163- docker compose ps -q web 2> /dev/null | head -n 1
163+ local id name
164+ id=" $( docker compose ps -q web 2> /dev/null | head -n 1 | tr -d ' [:space:]' ) "
165+ if [[ -n " ${id} " ]]; then
166+ echo " ${id} "
167+ return
168+ fi
169+ name=" $( docker compose ps --format ' {{.Name}}' web 2> /dev/null | head -n 1 | tr -d ' [:space:]' ) "
170+ if [[ -n " ${name} " ]]; then
171+ echo " ${name} "
172+ return
173+ fi
174+ echo " hpcperfstats_web_1"
175+ }
176+
177+ web_container_id () {
178+ web_container_ref
164179}
165180
166181compose_backend_is_podman () {
@@ -252,49 +267,81 @@ reset_container_dir_via_compose() {
252267copy_host_tar_into_web () {
253268 local host_tar=" $1 "
254269 local container_tar=" $2 "
255- local cid =" $3 "
270+ local container_ref =" $3 "
256271
257272 cd " ${REPO_ROOT} "
258- if docker compose cp " ${host_tar} " " web:${container_tar} " 2> /dev/null; then
259- echo " rebuild_frontend.sh: staged deploy tar → web via compose cp" >&2
273+ if compose_backend_is_podman; then
274+ if ! podman_cli_available; then
275+ echo " rebuild_frontend.sh: podman-compose detected but podman not on PATH" >&2
276+ return 1
277+ fi
278+ podman cp " ${host_tar} " " ${container_ref} :${container_tar} "
279+ echo " rebuild_frontend.sh: staged deploy tar → web via podman cp (${container_ref} )"
260280 return 0
261281 fi
262282
263- if [[ -n " ${cid} " ]] && podman_cli_available; then
264- podman cp " ${host_tar} " " ${cid} :${container_tar} "
265- echo " rebuild_frontend.sh: staged deploy tar → web via podman cp" >&2
283+ if docker compose cp " ${host_tar} " " web:${container_tar} " ; then
284+ echo " rebuild_frontend.sh: staged deploy tar → web via compose cp"
266285 return 0
267286 fi
268287
269288 echo " rebuild_frontend.sh: failed to copy deploy tar into web container" >&2
270289 return 1
271290}
272291
292+ verify_staged_tar_in_web () {
293+ local container_tar=" $1 "
294+ docker compose exec -T web bash -lc " test -s '${container_tar} '"
295+ }
296+
273297copy_tree_via_staged_tar () {
274298 local dest=" $1 "
275- local cid host_tar container_tar
276-
277- cid=" $( web_container_id) "
278- if [[ -z " ${cid} " ]]; then
279- echo " rebuild_frontend.sh: web container id not found (is the web service running?)" >&2
280- exit 1
281- fi
299+ local container_ref host_tar container_tar
282300
301+ container_ref=" $( web_container_ref) "
283302 host_tar=" $( mktemp /tmp/hps-frontend-deploy.XXXXXX.tar) "
284303 container_tar=" /tmp/hps-frontend-deploy.${$} .${RANDOM} .tar"
285304
305+ echo " rebuild_frontend.sh: creating deploy tar from ${STATIC_FRONTEND} ..."
286306 tar -C " ${STATIC_FRONTEND} " -cf " ${host_tar} " .
287- if ! copy_host_tar_into_web " ${host_tar} " " ${container_tar} " " ${cid } " ; then
307+ if ! copy_host_tar_into_web " ${host_tar} " " ${container_tar} " " ${container_ref } " ; then
288308 rm -f " ${host_tar} "
289309 exit 1
290310 fi
291311 rm -f " ${host_tar} "
292312
293- # Extract inside web via compose exec so writes land on the staticfiles_data volume.
313+ echo " rebuild_frontend.sh: verifying staged tar in web container ..."
314+ if ! verify_staged_tar_in_web " ${container_tar} " ; then
315+ echo " rebuild_frontend.sh: staged tar missing or empty in web: ${container_tar} " >&2
316+ exit 1
317+ fi
318+
319+ echo " rebuild_frontend.sh: extracting staged tar into web:${dest} ..."
294320 docker compose exec -T web bash -lc \
295321 " rm -rf '${dest} ' && mkdir -p '${dest} ' && tar -xf '${container_tar} ' -C '${dest} ' && rm -f '${container_tar} '"
296322}
297323
324+ run_collectstatic_into_volume () {
325+ echo " rebuild_frontend.sh: running collectstatic into ${CONTAINER_STATIC_ROOT_FRONTEND} ..."
326+ docker compose exec -T web bash -lc \
327+ " rm -rf '${CONTAINER_STATIC_ROOT_FRONTEND} ' && /usr/local/bin/python3 hpcperfstats/site/manage.py collectstatic --noinput"
328+ }
329+
330+ deploy_frontend_via_collectstatic () {
331+ echo " rebuild_frontend.sh: podman-compose deploy — stage image source tree, then collectstatic to nginx volume"
332+ copy_tree_via_staged_tar " ${CONTAINER_STATIC_FRONTEND} "
333+ run_collectstatic_into_volume
334+ }
335+
336+ print_podman_deploy_fallback () {
337+ cat << EOF >&2
338+ rebuild_frontend.sh: manual podman fallback (from git checkout):
339+ tar -cf /tmp/hps-frontend.tar -C hpcperfstats/site/hpcperfstats_site/static/frontend .
340+ podman cp /tmp/hps-frontend.tar hpcperfstats_web_1:/tmp/hps-frontend.tar
341+ docker compose exec web bash -lc 'rm -rf ${CONTAINER_STATIC_FRONTEND} && mkdir -p ${CONTAINER_STATIC_FRONTEND} && tar -xf /tmp/hps-frontend.tar -C ${CONTAINER_STATIC_FRONTEND} && rm -f /tmp/hps-frontend.tar && rm -rf ${CONTAINER_STATIC_ROOT_FRONTEND} && /usr/local/bin/python3 hpcperfstats/site/manage.py collectstatic --noinput'
342+ EOF
343+ }
344+
298345copy_tree_via_compose_cp () {
299346 local dest=" $1 "
300347 reset_container_dir_via_compose " ${dest} "
@@ -315,15 +362,20 @@ copy_tree_into_container() {
315362 exit 1
316363 fi
317364
318- # podman-compose: stdin tar and direct tree cp are unreliable for named volumes ; stage a
319- # tar on /tmp in the container, then extract with compose exec onto the volume mount .
320- echo " rebuild_frontend.sh: copying via staged tar + compose exec extract → ${dest} " >&2
365+ # podman-compose: stdin tar / compose cp / direct volume copy are unreliable ; stage the
366+ # image source tree and refresh STATIC_ROOT/frontend with collectstatic (same as startup) .
367+ echo " rebuild_frontend.sh: copying via staged tar + compose exec extract → ${dest} "
321368 copy_tree_via_staged_tar " ${dest} "
322369}
323370
324371copy_frontend_into_web () {
325372 cd " ${REPO_ROOT} "
326373
374+ if compose_backend_is_podman; then
375+ deploy_frontend_via_collectstatic
376+ return
377+ fi
378+
327379 # nginx (proxy) reads STATIC_ROOT/frontend from the shared staticfiles_data volume.
328380 copy_tree_into_container " ${CONTAINER_STATIC_ROOT_FRONTEND} "
329381
@@ -433,6 +485,8 @@ deploy_to_compose() {
433485 return 0
434486 fi
435487
488+ trap ' echo "rebuild_frontend.sh: deploy step failed." >&2; compose_backend_is_podman && print_podman_deploy_fallback; exit 1' ERR
489+
436490 echo " Copying built assets into web:${CONTAINER_STATIC_ROOT_FRONTEND} (nginx staticfiles volume) ..."
437491 copy_frontend_into_web
438492 verify_container_frontend_matches_host
@@ -444,6 +498,8 @@ deploy_to_compose() {
444498 print_container_deploy_fingerprint " proxy nginx volume" proxy " ${PROXY_STATIC_ROOT_FRONTEND} /machine/index.html"
445499 print_deploy_fingerprint " host build (expected)" " ${STATIC_FRONTEND} /machine/index.html"
446500
501+ trap - ERR
502+
447503 echo " Frontend deploy complete. Use the proxy service (ports 80/443), not web:8000 — Gunicorn does not serve /machine/."
448504 echo " Hard-refresh the browser and confirm the deploy fingerprint above matches page-*.js in DevTools Network."
449505}
0 commit comments