diff --git a/docker.nix b/docker.nix index 89f7d7b..e8a9a33 100644 --- a/docker.nix +++ b/docker.nix @@ -1,4 +1,4 @@ -{ pkgs, pythonEnv, python }: +{ pkgs, pythonEnv, python, buildDate ? "unknown", buildCommit ? "unknown" }: let # Build animaltrack as a package @@ -59,6 +59,8 @@ pkgs.dockerTools.buildImage { "PATH=${pkgs.lib.makeBinPath [ pkgs.busybox pkgs.bash pkgs.sqlite pythonEnv animaltrack ]}" "PYTHONPATH=${pythonEnv}/${pythonEnv.sitePackages}:${animaltrack}/${pythonEnv.sitePackages}" "PYTHONUNBUFFERED=1" + "BUILD_DATE=${buildDate}" + "BUILD_COMMIT=${buildCommit}" ]; ExposedPorts = { "5000/tcp" = {}; diff --git a/flake.nix b/flake.nix index 61057ac..cf5b77c 100644 --- a/flake.nix +++ b/flake.nix @@ -67,7 +67,12 @@ in { packages.${system} = { - dockerImage = import ./docker.nix { inherit pkgs pythonEnv python; }; + dockerImage = let + buildDate = let + d = self.lastModifiedDate or "00000000000000"; + in "${builtins.substring 0 4 d}-${builtins.substring 4 2 d}-${builtins.substring 6 2 d}"; + buildCommit = self.shortRev or self.dirtyShortRev or "unknown"; + in import ./docker.nix { inherit pkgs pythonEnv python buildDate buildCommit; }; }; devShells.${system}.default = pkgs.mkShell { diff --git a/src/animaltrack/build_info.py b/src/animaltrack/build_info.py new file mode 100644 index 0000000..195567b --- /dev/null +++ b/src/animaltrack/build_info.py @@ -0,0 +1,34 @@ +# ABOUTME: Provides build information (date + commit hash) for version display. +# ABOUTME: Reads from env vars (Docker) or git (development). + +import os +import subprocess + + +def get_build_info() -> str: + """Returns build info in '2025-01-08 fb59ef7' format. + + Checks BUILD_DATE and BUILD_COMMIT env vars first (set by Docker), + then falls back to reading git info at runtime (development). + Returns 'unknown' if neither source is available. + """ + build_date = os.environ.get("BUILD_DATE") + build_commit = os.environ.get("BUILD_COMMIT") + + if build_date and build_commit: + return f"{build_date} {build_commit}" + + # Try git at runtime (development mode) + try: + result = subprocess.run( + ["git", "log", "-1", "--format=%cs %h"], + capture_output=True, + text=True, + timeout=5, + ) + if result.returncode == 0 and result.stdout.strip(): + return result.stdout.strip() + except (subprocess.SubprocessError, FileNotFoundError, OSError): + pass + + return "unknown" diff --git a/src/animaltrack/web/templates/sidebar.py b/src/animaltrack/web/templates/sidebar.py index bd13bdd..bd2af8d 100644 --- a/src/animaltrack/web/templates/sidebar.py +++ b/src/animaltrack/web/templates/sidebar.py @@ -4,6 +4,7 @@ from fasthtml.common import A, Button, Div, Nav, Script, Span, Style from fasthtml.svg import Path, Svg +from animaltrack.build_info import get_build_info from animaltrack.models.reference import UserRole from animaltrack.web.templates.icons import EggIcon, FeedIcon, MoveIcon @@ -213,7 +214,8 @@ def Sidebar( # noqa: N802 return Nav( # Logo/Brand Div( - Span("ANIMALTRACK", cls="text-amber-600 font-bold tracking-wider text-sm"), + Div("ANIMALTRACK", cls="text-amber-600 font-bold tracking-wider text-sm"), + Div(get_build_info(), cls="text-stone-600 text-[10px] tracking-wide"), cls="px-4 py-4 border-b border-stone-800", ), # Primary navigation