nandi/frqpublic Fork 0
d0cf0eb
Commits
Clone
git clone https://git.rickub.com/nandi/frq.git
git clone ssh://git@rickub.com/nandi/frq.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

This file is read twice, and the second time there is no environment

The deploy went green and the URL hung: it connected and then sent
nothing, for as long as anything waited.

Modal imports `app.py` again inside the container, to find `serve` by
name. So everything at module level runs in both places — and the
environment is not the same in both. `FRQ_WEB_IMAGE` is set by whoever
deploys and by nobody in the container, so the `raise` that was there to
stop a deploy without a tag killed every container on start instead. The
port never opened, the proxy waited, and the deploy that reported
success had deployed something that could not run.

`modal.is_local()` is the distinction, and is exported for exactly this.
The check stays where it was and now only fires where it means
something; in the container the tag is beside the point, since the image
is already the one that was deployed, so a placeholder stands in and is
never built.

This is the thing the loader avoided by pickling the function body
instead of importing it — `serialized=True`, with a comment about the
re-import — and the rewrite dropped the trick and then walked into what
it was for.

Deployed and checked rather than reasoned about: the URL answers 200 in
0.4s and serves the page, `frq_core.js` and `frq_host.js`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
nandi committed 2026-09-20T10:06:48-07:00 Browse files
d0cf0eb parent: bd10e81
modified .modal/web/app.py +13 -4
@@ -20,10 +20,19 @@ import subprocess
2020
2121 import modal
2222
23-# The tag CI just built and pushed. No default: unset, this fails here rather
24-# than deploying whatever was current the last time somebody ran it.
23+# This file is read twice: here, by `modal deploy`, and again inside the
24+# container, where Modal imports it to find `serve` by name. Everything at
25+# module level therefore runs in both places — and the environment is not the
26+# same in both. `FRQ_WEB_IMAGE` is set by whoever deploys and by nobody in the
27+# container, so a bare `raise` here killed every container on start, the port
28+# never opened, and the URL hung while the deploy reported success.
29+#
30+# The tag CI just built and pushed. No default when deploying: unset, this
31+# fails rather than serving whatever was current the last time somebody ran
32+# it. In the container the tag is beside the point — the image is already the
33+# one that was deployed — so a placeholder stands in and is never built.
2534 IMAGE = os.environ.get("FRQ_WEB_IMAGE", "")
26-if not IMAGE:
35+if modal.is_local() and not IMAGE:
2736 raise SystemExit(
2837 "FRQ_WEB_IMAGE is unset. It is the image to serve, e.g.\n"
2938 " FRQ_WEB_IMAGE=registry.rickub.com/nandi/frq-web:<sha> \\\n"
@@ -41,7 +50,7 @@ if not IMAGE:
4150 # To go the other way, set the image private on rickub and pass
4251 # `secret=modal.Secret.from_name("rickub-registry")` below, naming a Secret
4352 # with REGISTRY_USERNAME / REGISTRY_PASSWORD for a pull-only token.
44-image = modal.Image.from_registry(IMAGE)
53+image = modal.Image.from_registry(IMAGE or "python:3.13-slim")
4554
4655 # Named, and the name is what makes a second deploy replace the running one
4756 # rather than stand another beside it.
@@ -20,10 +20,19 @@ import subprocess
20 20
21 import modal21 import modal
22 22
23-# The tag CI just built and pushed. No default: unset, this fails here rather23+# This file is read twice: here, by `modal deploy`, and again inside the
24-# than deploying whatever was current the last time somebody ran it.24+# container, where Modal imports it to find `serve` by name. Everything at
25+# module level therefore runs in both places — and the environment is not the
26+# same in both. `FRQ_WEB_IMAGE` is set by whoever deploys and by nobody in the
27+# container, so a bare `raise` here killed every container on start, the port
28+# never opened, and the URL hung while the deploy reported success.
29+#
30+# The tag CI just built and pushed. No default when deploying: unset, this
31+# fails rather than serving whatever was current the last time somebody ran
32+# it. In the container the tag is beside the point — the image is already the
33+# one that was deployed — so a placeholder stands in and is never built.
25 IMAGE = os.environ.get("FRQ_WEB_IMAGE", "")34 IMAGE = os.environ.get("FRQ_WEB_IMAGE", "")
26-if not IMAGE:35+if modal.is_local() and not IMAGE:
27 raise SystemExit(36 raise SystemExit(
28 "FRQ_WEB_IMAGE is unset. It is the image to serve, e.g.\n"37 "FRQ_WEB_IMAGE is unset. It is the image to serve, e.g.\n"
29 " FRQ_WEB_IMAGE=registry.rickub.com/nandi/frq-web:<sha> \\\n"38 " FRQ_WEB_IMAGE=registry.rickub.com/nandi/frq-web:<sha> \\\n"
@@ -41,7 +50,7 @@ if not IMAGE:
41 # To go the other way, set the image private on rickub and pass50 # To go the other way, set the image private on rickub and pass
42 # `secret=modal.Secret.from_name("rickub-registry")` below, naming a Secret51 # `secret=modal.Secret.from_name("rickub-registry")` below, naming a Secret
43 # with REGISTRY_USERNAME / REGISTRY_PASSWORD for a pull-only token.52 # with REGISTRY_USERNAME / REGISTRY_PASSWORD for a pull-only token.
44-image = modal.Image.from_registry(IMAGE)53+image = modal.Image.from_registry(IMAGE or "python:3.13-slim")
45 54
46 # Named, and the name is what makes a second deploy replace the running one55 # Named, and the name is what makes a second deploy replace the running one
47 # rather than stand another beside it.56 # rather than stand another beside it.