Use dynamic versioning
All checks were successful
/ test (push) Successful in 31s
/ build (push) Successful in 32s

This commit is contained in:
phil 2025-03-16 19:02:10 +01:00
parent d54bb178dd
commit a3a2efe471
5 changed files with 85 additions and 68 deletions

View file

@ -1,5 +1,4 @@
.venv .venv
.git
dist dist
.pytest_cache .pytest_cache
.mypy_cache .mypy_cache

View file

@ -30,6 +30,8 @@ jobs:
echo '${{ toJSON(env) }}' echo '${{ toJSON(env) }}'
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install app with 'uv pip install' - name: Install app with 'uv pip install'
run: uv pip install --python=$UV_PROJECT_ENVIRONMENT --no-deps . run: uv pip install --python=$UV_PROJECT_ENVIRONMENT --no-deps .
@ -48,40 +50,35 @@ jobs:
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Get the version from git - name: Install the latest version of uv
id: version uses: astral-sh/setup-uv@v4
run: echo "version=$(git describe --dirty --tags)" >> $GITHUB_OUTPUT with:
version: "0.6.6"
- name: Check if the container should be built - name: Install
id: builder run: uv sync
env:
RUN: ${{ toJSON(inputs.build || !contains(steps.version.outputs.version, '-g')) }}
run: |
echo "run=$RUN" >> $GITHUB_OUTPUT
echo "Run build: $RUN"
- name: Info - version and test if the git version is clean (then python package and image container should be built)
env:
VERSION: ${{ steps.version.outputs.version }}
RUN: ${{ steps.builder.outputs.run }}
FORCE: ${{ toJSON(inputs.build) }}
run: |
echo "Version $VERSION, force (manual input): $FORCE, run the build: $RUN"
- name: Set the version in pyproject.toml (workaround for uv not supporting dynamic version) - name: Get version
if: fromJSON(steps.builder.outputs.run) run: echo "VERSION=$(.venv/bin/dunamai from any --style semver)" >> $GITHUB_ENV
env:
VERSION: ${{ steps.version.outputs.version }} - name: Version
run: sed "s/0.0.0/${VERSION}/" -i pyproject.toml run: echo $VERSION
- name: Get distance from tag
run: echo "DISTANCE=$(.venv/bin/dunamai from any --format '{distance}')" >> $GITHUB_ENV
- name: Distance
run: echo $DISTANCE
- name: Workaround for bug of podman-login - name: Workaround for bug of podman-login
if: fromJSON(steps.builder.outputs.run) if: env.DISTANCE == '0'
run: | run: |
mkdir -p $HOME/.docker mkdir -p $HOME/.docker
echo "{ \"auths\": {} }" > $HOME/.docker/config.json echo "{ \"auths\": {} }" > $HOME/.docker/config.json
- name: Log in to the container registry (with another workaround) - name: Log in to the container registry (with another workaround)
if: fromJSON(steps.builder.outputs.run) if: env.DISTANCE == '0'
uses: actions/podman-login@v1 uses: actions/podman-login@v1
with: with:
registry: ${{ vars.REGISTRY }} registry: ${{ vars.REGISTRY }}
@ -90,37 +87,31 @@ jobs:
auth_file_path: /tmp/auth.json auth_file_path: /tmp/auth.json
- name: Build the container image - name: Build the container image
if: fromJSON(steps.builder.outputs.run) if: env.DISTANCE == '0'
uses: actions/buildah-build@v1 uses: actions/buildah-build@v1
with: with:
image: gisaf-backend image: gisaf-backend
oci: true oci: true
labels: gisaf-backend labels: gisaf-backend
tags: latest ${{ steps.version.outputs.version }} tags: "latest ${{ env.VERSION }}"
containerfiles: | containerfiles: |
./Containerfile ./Containerfile
build-args: |
APP_VERSION=${{ steps.version.outputs.version }}
- name: Push the image to the registry - name: Push the image to the registry
if: fromJSON(steps.builder.outputs.run) if: env.DISTANCE == '0'
uses: actions/push-to-registry@v2 uses: actions/push-to-registry@v2
with: with:
registry: "docker://${{ vars.REGISTRY }}/${{ vars.ORGANISATION }}" registry: "docker://${{ vars.REGISTRY }}/${{ vars.ORGANISATION }}"
image: gisaf-backend image: gisaf-backend
tags: latest ${{ steps.version.outputs.version }} tags: "latest ${{ env.VERSION }}"
- name: Install uv - name: Build wheel
uses: astral-sh/setup-uv@v4 if: env.DISTANCE == '0'
with:
version: "0.5.9"
- name: Build python package
if: fromJSON(steps.builder.outputs.run)
run: uv build --wheel run: uv build --wheel
- name: Publish Python package (home) - name: Publish Python package (home)
if: fromJSON(steps.builder.outputs.run) if: env.DISTANCE == '0'
env: env:
LOCAL_PYPI_TOKEN: ${{ secrets.LOCAL_PYPI_TOKEN }} LOCAL_PYPI_TOKEN: ${{ secrets.LOCAL_PYPI_TOKEN }}
run: uv publish --publish-url https://code.philo.ydns.eu/api/packages/philorg/pypi --token $LOCAL_PYPI_TOKEN run: uv publish --publish-url https://code.philo.ydns.eu/api/packages/philorg/pypi --token $LOCAL_PYPI_TOKEN
continue-on-error: true

View file

@ -1,19 +1,17 @@
# Build: podman build -t code.philo.ydns.eu/philorg/gisaf-backend -f Containerfile # Build: podman build -t code.philo.ydns.eu/philorg/gisaf-backend -f Containerfile
FROM code.philo.ydns.eu/philorg/gisaf-backend-deps FROM docker.io/library/python:latest
ENV PYTHONPATH $UV_PROJECT_ENVIRONMENT/lib/python3.12/site-packages COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /usr/local/bin/
ENV GISAF__BACKEND__PORT 8898 ENV GISAF__BACKEND__PORT 8898
ENV GISAF__BACKEND__BIND__ADDR 0.0.0.0 ENV GISAF__BACKEND__BIND__ADDR 0.0.0.0
ARG APP_VERSION=0.0.0
COPY . /src COPY . /app
RUN uv pip install \ # Sync the project into a new environment, using the frozen lockfile
--python=$UV_PROJECT_ENVIRONMENT \ WORKDIR /app
--no-deps \
/src RUN uv pip install --system .
RUN echo $APP_VERSION > /app/version.txt
CMD uvicorn gisaf.application:app --port ${GISAF__BACKEND__PORT} --host ${GISAF__BACKEND__BIND__ADDR} CMD uvicorn gisaf.application:app --port ${GISAF__BACKEND__PORT} --host ${GISAF__BACKEND__BIND__ADDR}

View file

@ -1,7 +1,7 @@
[project] [project]
name = "gisaf-backend" name = "gisaf-backend"
version = "0.0.0"
description = "Gisaf backend" description = "Gisaf backend"
dynamic = ["version"]
authors = [{ name = "phil", email = "phil.dev@philome.mooo.com" }] authors = [{ name = "phil", email = "phil.dev@philome.mooo.com" }]
dependencies = [ dependencies = [
"aiopath>=0.7.1", "aiopath>=0.7.1",
@ -40,20 +40,9 @@ readme = "README.md"
[project.scripts] [project.scripts]
gisaf = "gisaf.cli:cli" gisaf = "gisaf.cli:cli"
[project.optional-dependencies] [dependency-groups]
contextily = ["contextily>=1.4.0"] dev = [
mqtt = ["aiomqtt>=1.2.1"] "dunamai>=1.23.0",
all = ["gisaf-backend[contextily]", "gisaf-backend[mqtt]"]
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["src/gisaf"]
[tool.uv]
dev-dependencies = [
"ipdb>=0.13.13", "ipdb>=0.13.13",
"pandas-stubs>=2.1.4.231218", "pandas-stubs>=2.1.4.231218",
"pretty-errors>=1.2.25", "pretty-errors>=1.2.25",
@ -64,3 +53,27 @@ dev-dependencies = [
"types-passlib>=1.7.7.20240311", "types-passlib>=1.7.7.20240311",
"pytest>=8.3.4", "pytest>=8.3.4",
] ]
[project.optional-dependencies]
contextily = ["contextily>=1.4.0"]
mqtt = ["aiomqtt>=1.2.1"]
all = ["gisaf-backend[contextily]", "gisaf-backend[mqtt]"]
[build-system]
requires = ["hatchling", "uv-dynamic-versioning"]
build-backend = "hatchling.build"
[tool.hatch.version]
source = "uv-dynamic-versioning"
[tool.hatch.build.targets.wheel]
packages = ["src/gisaf"]
[tool.uv-dynamic-versioning]
style = "semver"
[tool.uv]
package = true
[tool.black]
line-length = 98

26
uv.lock generated
View file

@ -1,4 +1,5 @@
version = 1 version = 1
revision = 1
requires-python = ">=3.12" requires-python = ">=3.12"
[[package]] [[package]]
@ -276,7 +277,7 @@ name = "click"
version = "8.1.7" version = "8.1.7"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "colorama", marker = "platform_system == 'Windows'" }, { name = "colorama", marker = "sys_platform == 'win32'" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 } sdist = { url = "https://files.pythonhosted.org/packages/96/d3/f04c7bfcf5c1862a2a5b845c6b2b360488cf47af55dfa79c98f6a6bf98b5/click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de", size = 336121 }
wheels = [ wheels = [
@ -425,6 +426,18 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/d5/50/83c593b07763e1161326b3b8c6686f0f4b0f24d5526546bee538c89837d6/decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186", size = 9073 }, { url = "https://files.pythonhosted.org/packages/d5/50/83c593b07763e1161326b3b8c6686f0f4b0f24d5526546bee538c89837d6/decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186", size = 9073 },
] ]
[[package]]
name = "dunamai"
version = "1.23.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "packaging" },
]
sdist = { url = "https://files.pythonhosted.org/packages/06/4e/a5c8c337a1d9ac0384298ade02d322741fb5998041a5ea74d1cd2a4a1d47/dunamai-1.23.0.tar.gz", hash = "sha256:a163746de7ea5acb6dacdab3a6ad621ebc612ed1e528aaa8beedb8887fccd2c4", size = 44681 }
wheels = [
{ url = "https://files.pythonhosted.org/packages/21/4c/963169386309fec4f96fd61210ac0a0666887d0fb0a50205395674d20b71/dunamai-1.23.0-py3-none-any.whl", hash = "sha256:a0906d876e92441793c6a423e16a4802752e723e9c9a5aabdc5535df02dbe041", size = 26342 },
]
[[package]] [[package]]
name = "ecdsa" name = "ecdsa"
version = "0.19.0" version = "0.19.0"
@ -538,7 +551,6 @@ wheels = [
[[package]] [[package]]
name = "gisaf-backend" name = "gisaf-backend"
version = "0.0.0"
source = { editable = "." } source = { editable = "." }
dependencies = [ dependencies = [
{ name = "aiopath" }, { name = "aiopath" },
@ -587,6 +599,7 @@ mqtt = [
[package.dev-dependencies] [package.dev-dependencies]
dev = [ dev = [
{ name = "asyncpg-stubs" }, { name = "asyncpg-stubs" },
{ name = "dunamai" },
{ name = "ipdb" }, { name = "ipdb" },
{ name = "pandas-stubs" }, { name = "pandas-stubs" },
{ name = "pretty-errors" }, { name = "pretty-errors" },
@ -599,17 +612,17 @@ dev = [
[package.metadata] [package.metadata]
requires-dist = [ requires-dist = [
{ name = "aiomqtt", marker = "extra == 'all'", specifier = ">=1.2.1" },
{ name = "aiomqtt", marker = "extra == 'mqtt'", specifier = ">=1.2.1" }, { name = "aiomqtt", marker = "extra == 'mqtt'", specifier = ">=1.2.1" },
{ name = "aiopath", specifier = ">=0.7.1" }, { name = "aiopath", specifier = ">=0.7.1" },
{ name = "aiosqlite", specifier = ">=0.19.0" }, { name = "aiosqlite", specifier = ">=0.19.0" },
{ name = "apscheduler", specifier = ">=3.10.4" }, { name = "apscheduler", specifier = ">=3.10.4" },
{ name = "asyncpg", specifier = ">=0.28.0" }, { name = "asyncpg", specifier = ">=0.28.0" },
{ name = "contextily", marker = "extra == 'all'", specifier = ">=1.4.0" },
{ name = "contextily", marker = "extra == 'contextily'", specifier = ">=1.4.0" }, { name = "contextily", marker = "extra == 'contextily'", specifier = ">=1.4.0" },
{ name = "fastapi", specifier = ">=0.111" }, { name = "fastapi", specifier = ">=0.111" },
{ name = "geoalchemy2", specifier = ">=0.14.2" }, { name = "geoalchemy2", specifier = ">=0.14.2" },
{ name = "geopandas", specifier = ">=1.0.1" }, { name = "geopandas", specifier = ">=1.0.1" },
{ name = "gisaf-backend", extras = ["contextily"], marker = "extra == 'all'" },
{ name = "gisaf-backend", extras = ["mqtt"], marker = "extra == 'all'" },
{ name = "httpx", specifier = ">=0.28.1" }, { name = "httpx", specifier = ">=0.28.1" },
{ name = "itsdangerous", specifier = ">=2.1.2" }, { name = "itsdangerous", specifier = ">=2.1.2" },
{ name = "matplotlib", specifier = ">=3.8.3" }, { name = "matplotlib", specifier = ">=3.8.3" },
@ -633,10 +646,12 @@ requires-dist = [
{ name = "uvicorn", specifier = ">=0.23.2" }, { name = "uvicorn", specifier = ">=0.23.2" },
{ name = "websockets", specifier = ">=12.0" }, { name = "websockets", specifier = ">=12.0" },
] ]
provides-extras = ["all", "contextily", "mqtt"]
[package.metadata.requires-dev] [package.metadata.requires-dev]
dev = [ dev = [
{ name = "asyncpg-stubs", specifier = ">=0.29.1" }, { name = "asyncpg-stubs", specifier = ">=0.29.1" },
{ name = "dunamai", specifier = ">=1.23.0" },
{ name = "ipdb", specifier = ">=0.13.13" }, { name = "ipdb", specifier = ">=0.13.13" },
{ name = "pandas-stubs", specifier = ">=2.1.4.231218" }, { name = "pandas-stubs", specifier = ">=2.1.4.231218" },
{ name = "pretty-errors", specifier = ">=1.2.25" }, { name = "pretty-errors", specifier = ">=1.2.25" },
@ -1207,6 +1222,7 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/ce/ac/5b1ea50fc08a9df82de7e1771537557f07c2632231bbab652c7e22597908/psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:bb89f0a835bcfc1d42ccd5f41f04870c1b936d8507c6df12b7737febc40f0909", size = 2822712 }, { url = "https://files.pythonhosted.org/packages/ce/ac/5b1ea50fc08a9df82de7e1771537557f07c2632231bbab652c7e22597908/psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:bb89f0a835bcfc1d42ccd5f41f04870c1b936d8507c6df12b7737febc40f0909", size = 2822712 },
{ url = "https://files.pythonhosted.org/packages/c4/fc/504d4503b2abc4570fac3ca56eb8fed5e437bf9c9ef13f36b6621db8ef00/psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f0c2d907a1e102526dd2986df638343388b94c33860ff3bbe1384130828714b1", size = 2920155 }, { url = "https://files.pythonhosted.org/packages/c4/fc/504d4503b2abc4570fac3ca56eb8fed5e437bf9c9ef13f36b6621db8ef00/psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:f0c2d907a1e102526dd2986df638343388b94c33860ff3bbe1384130828714b1", size = 2920155 },
{ url = "https://files.pythonhosted.org/packages/b2/d1/323581e9273ad2c0dbd1902f3fb50c441da86e894b6e25a73c3fda32c57e/psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f8157bed2f51db683f31306aa497311b560f2265998122abe1dce6428bd86567", size = 2959356 }, { url = "https://files.pythonhosted.org/packages/b2/d1/323581e9273ad2c0dbd1902f3fb50c441da86e894b6e25a73c3fda32c57e/psycopg2_binary-2.9.10-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f8157bed2f51db683f31306aa497311b560f2265998122abe1dce6428bd86567", size = 2959356 },
{ url = "https://files.pythonhosted.org/packages/08/50/d13ea0a054189ae1bc21af1d85b6f8bb9bbc5572991055d70ad9006fe2d6/psycopg2_binary-2.9.10-cp313-cp313-win_amd64.whl", hash = "sha256:27422aa5f11fbcd9b18da48373eb67081243662f9b46e6fd07c3eb46e4535142", size = 2569224 },
] ]
[[package]] [[package]]
@ -1786,7 +1802,7 @@ name = "tzlocal"
version = "5.2" version = "5.2"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "tzdata", marker = "platform_system == 'Windows'" }, { name = "tzdata", marker = "sys_platform == 'win32'" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/04/d3/c19d65ae67636fe63953b20c2e4a8ced4497ea232c43ff8d01db16de8dc0/tzlocal-5.2.tar.gz", hash = "sha256:8d399205578f1a9342816409cc1e46a93ebd5755e39ea2d85334bea911bf0e6e", size = 30201 } sdist = { url = "https://files.pythonhosted.org/packages/04/d3/c19d65ae67636fe63953b20c2e4a8ced4497ea232c43ff8d01db16de8dc0/tzlocal-5.2.tar.gz", hash = "sha256:8d399205578f1a9342816409cc1e46a93ebd5755e39ea2d85334bea911bf0e6e", size = 30201 }
wheels = [ wheels = [