Skip to content

Commit dc428ed

Browse files
committed
Add tests to confirm mlflow versions match for all dependencies.
* Update where needed.
1 parent 3a704a0 commit dc428ed

File tree

5 files changed

+207
-7
lines changed

5 files changed

+207
-7
lines changed

.github/workflows/tests.yml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ on:
88
workflow_dispatch:
99
inputs:
1010
branch:
11-
description: 'Branch'
11+
description: "Branch"
1212
required: true
1313
default: main
1414

@@ -27,13 +27,19 @@ jobs:
2727
with:
2828
python-version: "3.12"
2929

30+
- name: Verify MLflow versions match
31+
run: ./scripts/check_mlflow_versions.sh
32+
3033
- name: Start MLflow server (no jupyter)
3134
run: |
3235
./start_services.sh --no-jupyter -d
3336
3437
- name: Install poetry
3538
run: pipx install "poetry == 1.8.5"
3639

40+
- name: Check poetry lock file
41+
run: poetry check --lock
42+
3743
- name: Remove existing virtual environment
3844
run: |
3945
poetry env remove python || true
@@ -75,6 +81,5 @@ jobs:
7581
run: |
7682
docker exec modelplane-jupyter-1 poetry run python /app/test_notebooks.py
7783
78-
7984
- name: Stop MLflow server
8085
run: docker compose down

Dockerfile.mlflow

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,5 @@ FROM ghcr.io/mlflow/mlflow:v3.1.1
33
# The base image does not include various dependencies that are needed for
44
# the MLflow server. We assume a postgres backend, so we need psycopg2.
55
# We also need boto3 for S3 support, and google-cloud-storage for GCS support.
6-
# TODO: better way to install these (maybe using poetry.lock to grab consistent versions?)
7-
RUN pip install mlflow[auth]==3.1.1 psycopg2-binary==2.9.10 boto3==1.38.31 \
8-
google-cloud-storage==3.1.0
6+
RUN pip install mlflow[auth]==3.1.1 psycopg2-binary==2.9.11 boto3==1.40.42 \
7+
google-cloud-storage==3.4.0

poetry.lock

Lines changed: 114 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ python = ">=3.10,!=3.12.5,<3.13"
1414
click = "^8"
1515
dvc = {extras = ["gs"], version = "^3.60"}
1616
modelbench = {git = "https://github.com/mlcommons/modelbench.git", rev = "8bf3a7bedcf2ae4049373a46e73ca9be6961c8c6" }
17-
mlflow = "3.1.1"
17+
mlflow = { extras = ["auth"], version = "3.1.1" }
1818
python-dotenv = "^1"
1919
requests = "^2"
2020
prometheus-client = "*" # version controlled by dependencies
@@ -37,6 +37,11 @@ ipython = "<9"
3737
pytest = "^8"
3838
pytest-cov = "^6"
3939

40+
[tool.poetry.group.mlflow.dependencies]
41+
psycopg2-binary = "^2.9.10"
42+
boto3 = "^1.38.31"
43+
google-cloud-storage = "^3.1.0"
44+
4045
[tool.poetry.scripts]
4146
modelplane = "modelplane.cli:cli"
4247

scripts/check_mlflow_versions.sh

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#!/usr/bin/env bash
2+
set -uo pipefail
3+
4+
pyproject="pyproject.toml"
5+
dockerfile="Dockerfile.mlflow"
6+
poetry_lock="poetry.lock"
7+
8+
for file in "${pyproject}" "${dockerfile}" "${poetry_lock}"; do
9+
[[ -f "${file}" ]] || { echo "Missing ${file}" >&2; exit 1; }
10+
done
11+
12+
pyproject_mlflow_version="$(grep '^mlflow[[:space:]]*=' "${pyproject}" | head -n1 | sed -E 's/.*version[[:space:]]*=[[:space:]]*"([^"]+)".*/\1/')"
13+
if [[ -z "${pyproject_mlflow_version}" ]]; then
14+
echo "Unable to determine mlflow version from ${pyproject}" >&2
15+
exit 1
16+
fi
17+
18+
docker_image_version="$(head -n1 "${dockerfile}" | cut -d ':' -f2 | tr -d 'v')"
19+
if [[ -z "${docker_image_version}" ]]; then
20+
echo "Unable to determine base image version from ${dockerfile}" >&2
21+
exit 1
22+
fi
23+
docker_mlflow_version="$(grep -o 'mlflow\[auth\]==[^[:space:]]*' "${dockerfile}" | head -n1 | cut -d '=' -f3)"
24+
if [[ -z "${docker_mlflow_version}" ]]; then
25+
echo "Unable to determine mlflow version from ${dockerfile}" >&2
26+
exit 1
27+
fi
28+
29+
mismatches=0
30+
31+
if [[ "${pyproject_mlflow_version}" != "${docker_image_version}" ]]; then
32+
echo "Mismatch: pyproject mlflow (${pyproject_mlflow_version}) vs Docker base (${docker_image_version})" >&2
33+
mismatches=$((mismatches + 1))
34+
fi
35+
36+
if [[ "${pyproject_mlflow_version}" != "${docker_mlflow_version}" ]]; then
37+
echo "Mismatch: pyproject mlflow (${pyproject_mlflow_version}) vs Docker pip install (${docker_mlflow_version})" >&2
38+
mismatches=$((mismatches + 1))
39+
fi
40+
41+
lock_version() {
42+
local pkg="$1"
43+
local name_line
44+
name_line="$(grep -n "^name = \"${pkg}\"$" "${poetry_lock}" | head -n1)"
45+
[[ -z "${name_line}" ]] && return 1
46+
local line_number="${name_line%%:*}"
47+
sed -n "$((line_number + 1))p" "${poetry_lock}" | cut -d '"' -f2
48+
}
49+
50+
check_dep() {
51+
local pkg="$1"
52+
local token
53+
token="$(grep -o "${pkg}==[^[:space:]]*" "${dockerfile}" | head -n1)"
54+
local docker_version="${token##*==}"
55+
local lock_version_value="$(lock_version "${pkg}")"
56+
57+
if [[ -z "${docker_version}" || -z "${lock_version_value}" ]]; then
58+
echo "Unable to resolve ${pkg} in Dockerfile or poetry.lock" >&2
59+
mismatches=$((mismatches + 1))
60+
return
61+
fi
62+
63+
if [[ "${docker_version}" != "${lock_version_value}" ]]; then
64+
echo "Mismatch: ${pkg} Docker (${docker_version}) vs poetry.lock (${lock_version_value})" >&2
65+
mismatches=$((mismatches + 1))
66+
fi
67+
}
68+
69+
# Other dependencies from the dockerfile
70+
check_dep "psycopg2-binary"
71+
check_dep "boto3"
72+
check_dep "google-cloud-storage"
73+
74+
if [[ ${mismatches} -ne 0 ]]; then
75+
exit 1
76+
fi
77+
78+
echo "Dependency versions are consistent (${pyproject_mlflow_version})."

0 commit comments

Comments
 (0)