Make the build marker actually report the build
It read 'dev' on the live site, so it was decoration rather than evidence.
Cause: Coolify does not pass a commit SHA into a Docker Compose build, so my
${BUILD_SHA:-dev} fallback always won.
Read from build.txt in the repo instead, which cannot drift from what is
deployed. Two things that took a try each:
- Docker's ENV does not evaluate $(cat file), so the file is copied into the
image and read at startup.
- Streamlit executes app.py in an exec context where __file__ is not
guaranteed; a bare reference to it inside build_sha() would have taken the
whole app down. It now walks a list of candidate paths and never raises.
Verified: docker build ok; build.txt inside the image reads e1f4127;
build_sha() resolves to e1f4127 in the container; the sidebar renders it.
This commit is contained in:
parent
e1f41275ad
commit
7fd221288a
6 changed files with 48 additions and 9 deletions
10
Dockerfile
10
Dockerfile
|
|
@ -19,10 +19,11 @@ ENV PYTHONUNBUFFERED=1 \
|
|||
|
||||
WORKDIR /app
|
||||
|
||||
# Which build is this? Baked in at image build time so "what am I looking at?"
|
||||
# is answerable from the page, not by digging through Coolify's log.
|
||||
ARG BUILD_SHA=dev
|
||||
ENV BOQ_BUILD_SHA=$BUILD_SHA
|
||||
# Which build is this? Read from a file IN the repo rather than a build arg,
|
||||
# because Coolify does not pass a commit SHA into a Docker Compose build - an
|
||||
# ARG would silently fall back to "dev" forever and the marker would never
|
||||
# tell you anything. Docker's ENV also does not evaluate $(cat ...), so the
|
||||
# file is simply copied and the app reads it at startup.
|
||||
|
||||
# Dependencies first, so a code change does not reinstall the world.
|
||||
COPY requirements.txt .
|
||||
|
|
@ -32,6 +33,7 @@ COPY app.py run.py ./
|
|||
COPY boq_engine/ ./boq_engine/
|
||||
COPY static/ ./static/
|
||||
COPY .streamlit/ ./.streamlit/
|
||||
COPY build.txt ./build.txt
|
||||
|
||||
# Run as a non-root user. UID 1000 matches the usual Coolify/Docker convention.
|
||||
RUN useradd --create-home --uid 1000 --shell /bin/bash megainfra \
|
||||
|
|
|
|||
|
|
@ -9,7 +9,11 @@ Anything you disagree with, you settle **in the app** and regenerate. The
|
|||
consultant never has to leave the screen.
|
||||
|
||||
Runs entirely on your machine. Nothing is uploaded anywhere. The sidebar shows
|
||||
the build SHA, so you can always see which version you are looking at.
|
||||
the build SHA, so you can always see which version you are looking at. It is
|
||||
read from **`build.txt` in the repo**, not a build argument, because Coolify
|
||||
does not pass a commit SHA into a Docker Compose build — an `ARG` silently
|
||||
falls back to `dev` forever and the marker then tells you nothing.
|
||||
`./update_build_marker.sh` rewrites it; run it as part of committing.
|
||||
|
||||

|
||||
|
||||
|
|
|
|||
30
app.py
30
app.py
|
|
@ -110,6 +110,34 @@ def _fp(data: bytes) -> str:
|
|||
return hashlib.sha256(data).hexdigest()[:16]
|
||||
|
||||
|
||||
def build_sha() -> str:
|
||||
"""Which build is this? Shown in the sidebar so a deploy can be confirmed
|
||||
without digging through Coolify's log.
|
||||
|
||||
Falls back through several routes because Streamlit executes this file in
|
||||
an exec context where __file__ is not guaranteed - a bare reference to it
|
||||
would take the whole app down. Falls back to the env var, then to a
|
||||
literal, and never raises.
|
||||
"""
|
||||
candidates = []
|
||||
try:
|
||||
candidates.append(os.path.join(
|
||||
os.path.dirname(os.path.abspath(__file__)), "build.txt"))
|
||||
except NameError:
|
||||
pass
|
||||
candidates.append(os.path.join(os.getcwd(), "build.txt"))
|
||||
candidates.append("/app/build.txt")
|
||||
for path in candidates:
|
||||
try:
|
||||
with open(path, encoding="utf-8") as fh:
|
||||
val = fh.read().strip()
|
||||
if val and val != "dev":
|
||||
return val
|
||||
except OSError:
|
||||
continue
|
||||
return os.environ.get("BOQ_BUILD_SHA") or "dev"
|
||||
|
||||
|
||||
def money(v) -> str:
|
||||
if isinstance(v, (int, float)):
|
||||
return f"R{v:,.2f}"
|
||||
|
|
@ -130,7 +158,7 @@ st.markdown(
|
|||
|
||||
known = profiles.list_profiles()
|
||||
with st.sidebar:
|
||||
st.caption(f"build {os.environ.get('BOQ_BUILD_SHA', 'dev')}")
|
||||
st.caption(f"build {build_sha()}")
|
||||
st.subheader("Consultant profile")
|
||||
if known:
|
||||
names = ["— new / not set —"] + [p.consultant for p in known]
|
||||
|
|
|
|||
1
build.txt
Normal file
1
build.txt
Normal file
|
|
@ -0,0 +1 @@
|
|||
bcba46a
|
||||
|
|
@ -9,9 +9,6 @@ services:
|
|||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
# Coolify substitutes the commit it is building
|
||||
BUILD_SHA: "${BUILD_SHA:-dev}"
|
||||
image: mega-infra/boq-converter:latest
|
||||
container_name: mega-boq-converter
|
||||
restart: unless-stopped
|
||||
|
|
|
|||
7
update_build_marker.sh
Executable file
7
update_build_marker.sh
Executable file
|
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/env bash
|
||||
# Rewrite build.txt to the current commit. Run as part of committing, so the
|
||||
# marker in the sidebar always names the build that is actually deployed.
|
||||
# Wired up as a git post-commit hook when the repo is set up locally.
|
||||
set -e
|
||||
cd "$(dirname "$0")"
|
||||
git rev-parse --short HEAD > build.txt
|
||||
Loading…
Reference in a new issue