From 5db454f8c85bb7f6747b88cbf28f3b58bbc371f2 Mon Sep 17 00:00:00 2001 From: Walter Oggioni Date: Thu, 22 Oct 2026 04:03:08 +0000 Subject: [PATCH] build: derive package version from git via setuptools-scm Replace hatchling and the static version with setuptools + setuptools-scm, following Kaya's pre-uv packaging setup: dynamic version, generated _version.py, and release/* tag prefix. The Docker builder now includes git and the .git directory so the image is versioned from the checkout. CI checks out full history and tags for the tag-triggered builds. --- .dockerignore | 6 +++++- .gitea/workflows/build.yaml | 4 ++++ .gitignore | 6 ++++++ Dockerfile | 7 ++++++- README.md | 5 +++++ pyproject.toml | 16 +++++++++++----- src/xmcp/__init__.py | 4 +++- uv.lock | 1 - 8 files changed, 40 insertions(+), 9 deletions(-) diff --git a/.dockerignore b/.dockerignore index 7a69e0c..fe9f4ce 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,3 @@ -.git/ .gitignore .venv/ __pycache__/ @@ -15,3 +14,8 @@ Dockerfile !README.md xmcp.yml xmcp.example.yml + +# Generated at build time +src/xmcp/_version.py +*.egg-info/ +dist/ diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml index 38b1884..29c1b0f 100644 --- a/.gitea/workflows/build.yaml +++ b/.gitea/workflows/build.yaml @@ -11,6 +11,10 @@ jobs: steps: - name: Checkout sources uses: actions/checkout@v6 + with: + # setuptools-scm needs tags and history to derive the package version. + fetch-depth: 0 + fetch-tags: true - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to Gitea container registry diff --git a/.gitignore b/.gitignore index cdeeb50..a181a95 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,9 @@ xmcp.yml xmcp.local.yml .env .env.* + +# Generated version metadata and build artifacts +src/xmcp/_version.py +*.egg-info/ +build/ +dist/ diff --git a/Dockerfile b/Dockerfile index a432d46..dc0a1d4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,6 +6,9 @@ FROM python:3.14-alpine3.24 AS builder COPY --from=ghcr.io/astral-sh/uv:0.13.1 /uv /uvx /bin/ +# setuptools-scm derives the package version from git history and tags. +RUN apk add --no-cache git + ENV UV_COMPILE_BYTECODE=1 \ UV_LINK_MODE=copy \ UV_PYTHON_DOWNLOADS=never @@ -17,9 +20,11 @@ COPY pyproject.toml uv.lock .python-version ./ RUN --mount=type=cache,target=/root/.cache/uv \ uv sync --frozen --no-dev --no-install-project -# Then install the project itself as a regular wheel. +# Then install the project itself as a regular wheel. The git metadata is +# required by setuptools-scm to derive the package version. COPY README.md ./ COPY src ./src +COPY .git ./.git RUN --mount=type=cache,target=/root/.cache/uv \ uv sync --frozen --no-dev --no-editable diff --git a/README.md b/README.md index 6211ee4..a1abeed 100644 --- a/README.md +++ b/README.md @@ -220,6 +220,11 @@ git push origin release/0.2.0 This publishes `gitea.woggioni.net/woggioni/xmcp:0.2.0` and `gitea.woggioni.net/woggioni/xmcp:latest`. +The Python package version is derived from the pushed `release/*` tag with +[setuptools-scm](https://setuptools-scm.readthedocs.io): `release/0.2.0` +produces package version `0.2.0`. Builds from untagged commits carry a PEP 440 +development version (for example `0.2.1.dev3+gabc1234`). + ## Project layout ``` diff --git a/pyproject.toml b/pyproject.toml index bc055ce..f236d8a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "xmcp" -version = "0.2.0" +dynamic = ["version"] description = "MCP server generated from an OpenAPI specification, built with FastMCP" readme = "README.md" requires-python = ">=3.14" @@ -14,8 +14,14 @@ dependencies = [ xmcp = "xmcp.server:main" [build-system] -requires = ["hatchling"] -build-backend = "hatchling.build" +requires = ["setuptools>=61.0", "setuptools-scm>=8"] +build-backend = "setuptools.build_meta" -[tool.hatch.build.targets.wheel] -packages = ["src/xmcp"] +[tool.setuptools.packages.find] +where = ["src"] + +[tool.setuptools_scm] +version_file = "src/xmcp/_version.py" + +[tool.setuptools_scm.tag] +prefix = "release/" diff --git a/src/xmcp/__init__.py b/src/xmcp/__init__.py index 4b2eed4..8d8ea60 100644 --- a/src/xmcp/__init__.py +++ b/src/xmcp/__init__.py @@ -1,3 +1,5 @@ """xmcp: an MCP server generated from an OpenAPI specification with FastMCP.""" -__version__ = "0.2.0" +from ._version import __version__ + +__all__ = ["__version__"] diff --git a/uv.lock b/uv.lock index dd36227..5978dde 100644 --- a/uv.lock +++ b/uv.lock @@ -1231,7 +1231,6 @@ wheels = [ [[package]] name = "xmcp" -version = "0.2.0" source = { editable = "." } dependencies = [ { name = "fastmcp" },