Skip to content

Commit 586efb5

Browse files
authored
fix: get version info in Docker image (#29)
1 parent 179cd5e commit 586efb5

File tree

7 files changed

+110
-20
lines changed

7 files changed

+110
-20
lines changed

.github/workflows/container.yml

+3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ jobs:
2323
steps:
2424
- name: Checkout branch
2525
uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 # v4.2.0
26+
with:
27+
fetch-depth: 0
2628

2729
- name: Login into GHCR
2830
if: github.ref_name == 'main'
@@ -44,6 +46,7 @@ jobs:
4446
id: build-and-push
4547
uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 # v6.9.0
4648
with:
49+
context: .
4750
push: ${{ github.ref_name == 'main' }}
4851
file: Dockerfile
4952
tags: ${{ steps.meta.outputs.tags }}

Dockerfile

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ FROM ubuntu:24.04 AS production
1313
COPY --from=build /app/.pixi/envs/default /app/.pixi/envs/default
1414
COPY --from=build /app/app.py /app
1515
COPY --from=build /app/app_config.toml /app
16+
COPY --from=build /app/version_info.json /app
1617
COPY --from=build --chmod=0555 /entrypoint.sh /
1718

1819
WORKDIR /app

conda_metadata_app/app_config.py

-18
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import os
88
from collections.abc import Iterable
99
from enum import StrEnum
10-
from subprocess import CalledProcessError, check_output
1110
from typing import Literal, Self
1211

1312
from pydantic import (
@@ -428,22 +427,5 @@ def export_json_schema() -> None:
428427
f.write("\n")
429428

430429

431-
def app_version() -> str:
432-
try:
433-
return check_output(
434-
[
435-
"git",
436-
"--no-pager",
437-
"log",
438-
"-1",
439-
"--pretty=format:`%h (%cd)`",
440-
"--date=format:%Y-%m-%d %H:%M:%S",
441-
],
442-
text=True,
443-
).strip()
444-
except CalledProcessError:
445-
return ""
446-
447-
448430
if __name__ == "__main__":
449431
export_json_schema()

conda_metadata_app/pages/main_page.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@
3434
MetadataRetrieval,
3535
PackageDiscoveryChoice,
3636
Secret,
37-
app_version,
3837
)
38+
from conda_metadata_app.version_info import get_version_info
3939
from conda_metadata_app.version_order import VersionOrder
4040

4141
if not os.environ.get("CACHE_DIR"):
@@ -71,7 +71,7 @@
7171
initial_sidebar_state="expanded",
7272
menu_items={
7373
"about": f"""
74-
**📦 conda-metadata-app `{app_version()}`**
74+
**📦 conda-metadata-app `{get_version_info() or "(Version N/A)"}`**
7575
7676
Browse metadata from conda packages in conda-forge, bioconda and others.
7777
"""

conda_metadata_app/version_info.py

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
"""
2+
This module provides a way to retrieve version information about conda-metadata-app.
3+
"""
4+
5+
import datetime
6+
import subprocess
7+
8+
from pydantic import BaseModel, Field
9+
from streamlit.logger import get_logger
10+
11+
VERSION_INFO_FILE = "version_info.json"
12+
13+
LOGGER = get_logger(__name__)
14+
15+
16+
class VersionInfo(BaseModel):
17+
git_hash: str = Field(pattern=r"^[0-9a-f]{40}$")
18+
timestamp: datetime.datetime
19+
20+
@property
21+
def short_git_hash(self):
22+
return self.git_hash[:7]
23+
24+
def timestamp_string(self):
25+
return self.timestamp.strftime("%Y-%m-%d %H:%M:%S")
26+
27+
def __str__(self):
28+
return f"{self.short_git_hash} ({self.timestamp_string()})"
29+
30+
31+
def get_version_info_from_git() -> VersionInfo:
32+
"""
33+
Returns version information from the `.git` directory.
34+
This requires you to have the `git` command line tool installed.
35+
36+
You should only use this function from a Streamlit Cloud deployment or
37+
during the Docker build process, as neither git nor the `.git` directory
38+
will be available in the final Docker image!
39+
40+
:raises FileNotFoundError: If git is not available.
41+
:raises subprocess.CalledProcessError: If the git command fails.
42+
"""
43+
git_info = subprocess.check_output(
44+
[
45+
"git",
46+
"--no-pager",
47+
"log",
48+
"-1",
49+
"--pretty=format:%H-%cd",
50+
"--date=unix",
51+
],
52+
text=True,
53+
).strip()
54+
55+
git_hash, timestamp = git_info.split("-")
56+
57+
return VersionInfo(
58+
git_hash=git_hash,
59+
timestamp=datetime.datetime.fromtimestamp(int(timestamp), datetime.UTC),
60+
)
61+
62+
63+
def save_version_info_from_git() -> None:
64+
"""
65+
Saves the version information from git to version_info.json.
66+
See the `get_version_info_from_git` function for more information.
67+
"""
68+
version_info = get_version_info_from_git()
69+
70+
with open(VERSION_INFO_FILE, "w") as f:
71+
f.write(version_info.model_dump_json(indent=2))
72+
73+
74+
def get_version_info() -> VersionInfo | None:
75+
"""
76+
Get the version information of the current app installation.
77+
This works as follows:
78+
1. Retrieve the version information from the `version_info.json` file (relevant for Docker image).
79+
2. If the file does not exist, retrieve the version information from git (relevant for Streamlit Cloud).
80+
81+
:return: The version information or None if it could not be retrieved.
82+
"""
83+
try:
84+
with open(VERSION_INFO_FILE) as f:
85+
return VersionInfo.model_validate_json(f.read())
86+
except FileNotFoundError:
87+
pass
88+
89+
# fall back to retrieving the version information from git
90+
try:
91+
return get_version_info_from_git()
92+
except (FileNotFoundError, subprocess.CalledProcessError):
93+
LOGGER.warning(
94+
"Unable to retrieve version information from git after finding that version.info.json is not available.",
95+
exc_info=True,
96+
)
97+
return None
98+
99+
100+
if __name__ == "__main__":
101+
save_version_info_from_git()

docker/install.sh

+2
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@ pixi run -e default postinstall-production
88
echo "#!/bin/sh" > /entrypoint.sh
99
pixi shell-hook -e default -s bash >> /entrypoint.sh
1010
echo 'exec "$@"' >> /entrypoint.sh
11+
12+
pixi run -e default save-version-info

pixi.toml

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ platforms = ["linux-64", "win-64", "osx-arm64", "osx-64", "linux-aarch64"]
1010
dev = "python -m streamlit run --server.runOnSave=true app.py"
1111
deploy = "python -m streamlit run --server.headless=true --global.developmentMode=false app.py"
1212
schema = "python -m conda_metadata_app.app_config"
13+
save-version-info = "python -m conda_metadata_app.version_info"
1314
postinstall-production = "pip install --no-deps --disable-pip-version-check dist/conda_metadata_app-*.whl"
1415

1516

0 commit comments

Comments
 (0)