From 565879dd521a2b871a8d6cf0e4c8cf51f7acf703 Mon Sep 17 00:00:00 2001 From: Brian Bjarke Jensen Date: Fri, 10 Jul 2026 14:29:22 +0200 Subject: [PATCH] Unify dev tooling via uv so pre-commit, CI, and the update bot stay aligned. Route Python hooks through uv run with versions pinned in uv.lock, add explicit Ruff settings, and extend the dependency bot to run pre-commit autoupdate. Co-authored-by: Cursor --- .gitea/workflows/dependency-update-bot.yml | 26 ++++++++++++++ .pre-commit-config.yaml | 36 ++++++++++--------- pyproject.toml | 20 ++++++++--- .../adapters/connection_aware_adapter.py | 2 +- python_repositories/adapters/minio_adapter.py | 1 + python_repositories/adapters/redis_adapter.py | 1 + python_repositories/config/minio_config.py | 2 +- python_repositories/config/redis_config.py | 2 +- .../interfaces/json_repository_interface.py | 2 +- scripts/ci/create-deps-update-pr.sh | 12 +++++-- tests/integration/conftest.py | 4 +-- tests/integration/examples_test.py | 2 +- tests/integration/minio_adapter_test.py | 4 +-- tests/unit/adapters_test.py | 4 +-- tests/unit/conftest.py | 2 +- tests/unit/connection_aware_interface_test.py | 1 + tests/unit/context_aware_interface_test.py | 1 + tests/unit/json_repository_interface_test.py | 1 + tests/unit/minio_adapter_test.py | 2 +- .../unit/object_repository_interface_test.py | 1 + uv.lock | 10 +++--- 21 files changed, 94 insertions(+), 42 deletions(-) diff --git a/.gitea/workflows/dependency-update-bot.yml b/.gitea/workflows/dependency-update-bot.yml index 041c511..8ce5820 100644 --- a/.gitea/workflows/dependency-update-bot.yml +++ b/.gitea/workflows/dependency-update-bot.yml @@ -14,12 +14,38 @@ jobs: with: token: ${{ secrets.CI_RUNNER_TOKEN }} + - name: Sync dependencies + env: + UV_LINK_MODE: copy + UV_INDEX_GITEA_USERNAME: ci-bot + UV_INDEX_GITEA_PASSWORD: ${{ secrets.CI_RUNNER_TOKEN }} + run: uv sync --all-extras + - name: Upgrade dependencies env: UV_INDEX_GITEA_USERNAME: ci-bot UV_INDEX_GITEA_PASSWORD: ${{ secrets.CI_RUNNER_TOKEN }} run: uv lock --upgrade + - name: Update pre-commit hook revs + env: + UV_INDEX_GITEA_USERNAME: ci-bot + UV_INDEX_GITEA_PASSWORD: ${{ secrets.CI_RUNNER_TOKEN }} + run: uv run pre-commit autoupdate + + - name: Sync upgraded dependencies + env: + UV_LINK_MODE: copy + UV_INDEX_GITEA_USERNAME: ci-bot + UV_INDEX_GITEA_PASSWORD: ${{ secrets.CI_RUNNER_TOKEN }} + run: uv sync --all-extras + + - name: Smoke check + run: | + uv run ruff check . + uv run ruff format --check . + uv run mypy . + - name: Commit and push changes env: API_URL: ${{ vars.API_URL }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8b3462b..499df27 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -11,28 +11,30 @@ repos: - id: name-tests-test - id: check-merge-conflict - # Python linting and formatting with Ruff - - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.12.8 + # Python tooling via uv (versions pinned in uv.lock) + - repo: local hooks: - id: ruff-check - args: [--fix] + name: ruff check + entry: uv run ruff check --fix + language: system + types: [python] - id: ruff-format - - # Static type checking with mypy - - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.8.0 - hooks: + name: ruff format + entry: uv run ruff format + language: system + types: [python] - id: mypy - additional_dependencies: - - types-redis - - # Python syntax modernization with pyupgrade - - repo: https://github.com/asottile/pyupgrade - rev: v3.20.0 - hooks: + name: mypy + entry: uv run mypy . + language: system + types: [python] + pass_filenames: false - id: pyupgrade - args: ["--py312-plus"] + name: pyupgrade + entry: uv run pyupgrade --py312-plus + language: system + types: [python] # Formatting for Markdown, JSON, and YAML with Prettier - repo: https://github.com/pre-commit/mirrors-prettier diff --git a/pyproject.toml b/pyproject.toml index d4eccd9..40f2c24 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -60,6 +60,18 @@ name = "gitea" url = "https://gitea.lille-vemmelund.dk/api/packages/brian/pypi/simple/" explicit = true +[tool.ruff] +line-length = 88 +target-version = "py312" + +[tool.ruff.lint] +extend-select = ["I"] + +[tool.ruff.lint.isort] +known-first-party = ["python_repositories", "tests"] +combine-as-imports = true +force-sort-within-sections = true + [tool.mypy] python_version = "3.12" warn_return_any = true # nudge to use stricter types @@ -87,12 +99,12 @@ ignore_missing_imports = true [dependency-groups] dev = [ - "mypy>=1.17.1", - "pre-commit>=4.3.0", + "mypy>=2.1.0", + "pre-commit>=4.6.0", "pytest>=8.4.1", "pytest-cov>=7.0.0", - "pyupgrade>=3.20.0", - "ruff>=0.12.11", + "pyupgrade>=3.21.2", + "ruff>=0.15.20", "safety>=3.6.0", "testcontainers>=4.13.0", "types-redis>=4.6.0.20241004", diff --git a/python_repositories/adapters/connection_aware_adapter.py b/python_repositories/adapters/connection_aware_adapter.py index 48bb0be..2c0334f 100644 --- a/python_repositories/adapters/connection_aware_adapter.py +++ b/python_repositories/adapters/connection_aware_adapter.py @@ -2,8 +2,8 @@ from __future__ import annotations -import time from abc import abstractmethod +import time from typing import Self import structlog diff --git a/python_repositories/adapters/minio_adapter.py b/python_repositories/adapters/minio_adapter.py index bb281ef..561299c 100644 --- a/python_repositories/adapters/minio_adapter.py +++ b/python_repositories/adapters/minio_adapter.py @@ -1,6 +1,7 @@ """Definition of MinioAdapter class.""" from __future__ import annotations + from io import BytesIO from python_repositories.adapters.connection_aware_adapter import ( diff --git a/python_repositories/adapters/redis_adapter.py b/python_repositories/adapters/redis_adapter.py index efe4dbb..70d279e 100644 --- a/python_repositories/adapters/redis_adapter.py +++ b/python_repositories/adapters/redis_adapter.py @@ -1,6 +1,7 @@ """Definition of RedisAdapter class.""" from __future__ import annotations + from collections.abc import Iterator from typing import Any, cast diff --git a/python_repositories/config/minio_config.py b/python_repositories/config/minio_config.py index 050d04d..0bdb9e5 100644 --- a/python_repositories/config/minio_config.py +++ b/python_repositories/config/minio_config.py @@ -2,8 +2,8 @@ from __future__ import annotations -import os from dataclasses import dataclass +import os from python_utils import check_env diff --git a/python_repositories/config/redis_config.py b/python_repositories/config/redis_config.py index 85a3050..0bf330e 100644 --- a/python_repositories/config/redis_config.py +++ b/python_repositories/config/redis_config.py @@ -2,8 +2,8 @@ from __future__ import annotations -import os from dataclasses import dataclass +import os from python_utils import check_env diff --git a/python_repositories/interfaces/json_repository_interface.py b/python_repositories/interfaces/json_repository_interface.py index cc0325b..45c70e7 100644 --- a/python_repositories/interfaces/json_repository_interface.py +++ b/python_repositories/interfaces/json_repository_interface.py @@ -1,7 +1,7 @@ """Definition of JsonRepositoryInterface abstract base class.""" -from collections.abc import Iterator from abc import ABC, abstractmethod +from collections.abc import Iterator from typing import Any diff --git a/scripts/ci/create-deps-update-pr.sh b/scripts/ci/create-deps-update-pr.sh index 70a9551..60421d7 100755 --- a/scripts/ci/create-deps-update-pr.sh +++ b/scripts/ci/create-deps-update-pr.sh @@ -11,15 +11,16 @@ set -euo pipefail BRANCH="${BRANCH:-renovate/auto-deps-update}" BASE_BRANCH="${BASE_BRANCH:-main}" LOCKFILE="${LOCKFILE:-uv.lock}" +PRE_COMMIT_CONFIG="${PRE_COMMIT_CONFIG:-.pre-commit-config.yaml}" -if git diff --quiet "$LOCKFILE"; then +if git diff --quiet "$LOCKFILE" && git diff --quiet "$PRE_COMMIT_CONFIG"; then echo "No dependency updates available." exit 0 fi git config user.name "CI Bot" git config user.email "ci-bot@example.com" -git add "$LOCKFILE" +git add "$LOCKFILE" "$PRE_COMMIT_CONFIG" git commit -m "chore(deps): update dependencies [automated]" git remote set-url origin "https://x-access-token:${CI_RUNNER_TOKEN}@${GITHUB_SERVER_URL#https://}/${GITHUB_REPOSITORY}.git" @@ -48,7 +49,12 @@ print( json.dumps( { "title": "chore(deps): update dependencies", - "body": "This PR was created automatically to update dependencies.", + "body": ( + "This PR was created automatically to update dependencies.\n\n" + "- `uv.lock`: upgraded Python dependencies\n" + "- `.pre-commit-config.yaml`: updated remote hook revs via " + "`pre-commit autoupdate`" + ), "head": os.environ["BRANCH"], "base": os.environ["BASE_BRANCH"], } diff --git a/tests/integration/conftest.py b/tests/integration/conftest.py index 42ce54d..4aacb1e 100644 --- a/tests/integration/conftest.py +++ b/tests/integration/conftest.py @@ -1,13 +1,13 @@ """Integration tests configuration.""" -import logging from collections.abc import Generator +import logging from typing import Any, cast +from minio import Minio import pytest import redis import structlog -from minio import Minio from testcontainers.core.container import DockerContainer from testcontainers.core.waiting_utils import WaitStrategy, WaitStrategyTarget from testcontainers.minio import MinioContainer diff --git a/tests/integration/examples_test.py b/tests/integration/examples_test.py index e1f9c51..db08e4a 100644 --- a/tests/integration/examples_test.py +++ b/tests/integration/examples_test.py @@ -5,8 +5,8 @@ from io import BytesIO import os import random -import pytest from minio import Minio +import pytest from python_repositories.examples.artifact_object_repository import ( ArtifactObjectRepository, diff --git a/tests/integration/minio_adapter_test.py b/tests/integration/minio_adapter_test.py index 4b5343c..f03f695 100644 --- a/tests/integration/minio_adapter_test.py +++ b/tests/integration/minio_adapter_test.py @@ -2,13 +2,13 @@ from collections.abc import Generator from dataclasses import replace +from io import BytesIO import logging import random -from io import BytesIO from unittest.mock import MagicMock -import pytest from minio import Minio, S3Error +import pytest from urllib3.response import BaseHTTPResponse from python_repositories.adapters.minio_adapter import MinioAdapter diff --git a/tests/unit/adapters_test.py b/tests/unit/adapters_test.py index 22b14dc..2b1bb90 100644 --- a/tests/unit/adapters_test.py +++ b/tests/unit/adapters_test.py @@ -3,12 +3,12 @@ from __future__ import annotations import builtins +from collections.abc import Callable, Mapping, Sequence import importlib import os +from pathlib import Path import subprocess import sys -from collections.abc import Callable, Mapping, Sequence -from pathlib import Path from types import ModuleType from unittest.mock import patch diff --git a/tests/unit/conftest.py b/tests/unit/conftest.py index 92c7ff5..ee89fb2 100644 --- a/tests/unit/conftest.py +++ b/tests/unit/conftest.py @@ -4,9 +4,9 @@ from __future__ import annotations from unittest.mock import MagicMock +from minio import Minio import pytest import redis -from minio import Minio from python_repositories.adapters.minio_adapter import MinioAdapter from python_repositories.adapters.redis_adapter import RedisAdapter diff --git a/tests/unit/connection_aware_interface_test.py b/tests/unit/connection_aware_interface_test.py index f805faf..560260c 100644 --- a/tests/unit/connection_aware_interface_test.py +++ b/tests/unit/connection_aware_interface_test.py @@ -1,6 +1,7 @@ """Unit tests for ConnectionAwareInterface.""" import pytest + from python_repositories.interfaces.connection_aware_interface import ( ConnectionAwareInterface, ) diff --git a/tests/unit/context_aware_interface_test.py b/tests/unit/context_aware_interface_test.py index 8bffcfd..925f322 100644 --- a/tests/unit/context_aware_interface_test.py +++ b/tests/unit/context_aware_interface_test.py @@ -3,6 +3,7 @@ from __future__ import annotations import pytest + from python_repositories.interfaces.context_aware_interface import ContextAwareInterface diff --git a/tests/unit/json_repository_interface_test.py b/tests/unit/json_repository_interface_test.py index bf7c55f..208b4f9 100644 --- a/tests/unit/json_repository_interface_test.py +++ b/tests/unit/json_repository_interface_test.py @@ -3,6 +3,7 @@ from typing import Any import pytest + from python_repositories.interfaces.json_repository_interface import ( JsonRepositoryInterface, ) diff --git a/tests/unit/minio_adapter_test.py b/tests/unit/minio_adapter_test.py index 739ce3b..308f66d 100644 --- a/tests/unit/minio_adapter_test.py +++ b/tests/unit/minio_adapter_test.py @@ -5,8 +5,8 @@ from __future__ import annotations from dataclasses import replace from unittest.mock import MagicMock -import pytest from minio import Minio, S3Error +import pytest from urllib3.response import BaseHTTPResponse from python_repositories.adapters.minio_adapter import MinioAdapter diff --git a/tests/unit/object_repository_interface_test.py b/tests/unit/object_repository_interface_test.py index 4e567a4..4cebd2d 100644 --- a/tests/unit/object_repository_interface_test.py +++ b/tests/unit/object_repository_interface_test.py @@ -3,6 +3,7 @@ from io import BytesIO import pytest + from python_repositories.interfaces.object_repository_interface import ( ObjectRepositoryInterface, ) diff --git a/uv.lock b/uv.lock index 4c7dc03..9229361 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 2 +revision = 3 requires-python = ">=3.12" resolution-markers = [ "python_full_version >= '3.15'", @@ -1097,12 +1097,12 @@ provides-extras = ["redis", "minio"] [package.metadata.requires-dev] dev = [ - { name = "mypy", specifier = ">=1.17.1" }, - { name = "pre-commit", specifier = ">=4.3.0" }, + { name = "mypy", specifier = ">=2.1.0" }, + { name = "pre-commit", specifier = ">=4.6.0" }, { name = "pytest", specifier = ">=8.4.1" }, { name = "pytest-cov", specifier = ">=7.0.0" }, - { name = "pyupgrade", specifier = ">=3.20.0" }, - { name = "ruff", specifier = ">=0.12.11" }, + { name = "pyupgrade", specifier = ">=3.21.2" }, + { name = "ruff", specifier = ">=0.15.20" }, { name = "safety", specifier = ">=3.6.0" }, { name = "testcontainers", specifier = ">=4.13.0" }, { name = "types-redis", specifier = ">=4.6.0.20241004" }, -- 2.54.0