From 56526da2b21694dffa3767ebe6242f4a5c6c47b5 Mon Sep 17 00:00:00 2001 From: Thor Whalen <1906276+thorwhalen@users.noreply.github.com> Date: Mon, 3 Aug 2026 23:26:16 +0100 Subject: [PATCH 1/4] fix(deps): require enlace>=0.1.21 for the diagnoser extension point MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `enlace.diagnosers` entry-point group this package registers against (and `enlace.diagnose.iter_diagnosers`, which `diagnose_app` calls) first shipped in enlace 0.1.21. The declared floor was `enlace>=0.1.20`, one release too low, so a clean resolve could legitimately install 0.1.20 — where `diagnose_app` never invokes plugin diagnosers. That is exactly what happened in CI: the Validation (3.12) job resolved `enlace==0.1.20` and `test_runs_via_diagnose_app_entry_point` failed with AssertionError: assert 'docker_missing_dockerfile' in {} Reproduced locally in a clean venv: pinning enlace==0.1.20 fails that test (1 failed, 52 passed, 2 skipped); enlace==0.1.21 passes (53 passed, 2 skipped). Developer machines masked it because they carry a newer enlace. Claude-Session: https://claude.ai/code/session_01VipiLaG4xy7WctqY9w2475 --- pyproject.toml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 093d425..5c1c303 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,10 @@ requires-python = ">=3.10" keywords = ["enlace", "docker", "docker-compose", "asgi", "multi-app"] authors = [{ name = "Thor Whalen" }] dependencies = [ - "enlace>=0.1.20", + # 0.1.21 is the first release carrying the `enlace.diagnosers` extension + # point (enlace.diagnose.iter_diagnosers, called by diagnose_app). With + # 0.1.20 the diagnoser registered below is never invoked. + "enlace>=0.1.21", "httpx>=0.24.0", ] @@ -39,7 +42,7 @@ image = "enlace_docker.strategies:ImageStrategy" docker_attached = "enlace_docker.strategies:DockerAttachedStrategy" # Docker-aware checks for `enlace diagnose`, registered against enlace's -# diagnoser extension point (enlace >= 0.1.20). +# diagnoser extension point (enlace >= 0.1.21). [project.entry-points."enlace.diagnosers"] docker = "enlace_docker.diagnose:docker_diagnoser" From e98f0fcf70425eace1f92718aa35d5b74a38aa6e Mon Sep 17 00:00:00 2001 From: Thor Whalen <1906276+thorwhalen@users.noreply.github.com> Date: Mon, 3 Aug 2026 23:26:48 +0100 Subject: [PATCH 2/4] test(ci): widen testpaths to the package so doctests are actually collected wads CI runs `pytest --doctest-modules` with no path argument, so pytest's collection roots come entirely from `testpaths`. With `testpaths = ["enlace_docker/tests"]` the `--doctest-modules` flag was inert: no module docstring in the package could ever be collected, and CI reported green regardless. Pointing testpaths at the package directory keeps the existing test files (they live under enlace_docker/tests) and additionally exposes module docstrings to doctest collection. Verified in a clean venv with the exact CI command: 53 passed, 2 skipped -- unchanged, since no module currently has doctest examples. This is about future ones being honoured. Claude-Session: https://claude.ai/code/session_01VipiLaG4xy7WctqY9w2475 --- pyproject.toml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 5c1c303..0b258cf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -47,7 +47,11 @@ docker_attached = "enlace_docker.strategies:DockerAttachedStrategy" docker = "enlace_docker.diagnose:docker_diagnoser" [tool.pytest.ini_options] -testpaths = ["enlace_docker/tests"] +# The package dir, not just its tests/ subdir: wads CI runs +# `pytest --doctest-modules` with no path argument, so collection is driven +# entirely by testpaths. Pointing it at enlace_docker/tests would silently +# exclude every module docstring from doctest collection. +testpaths = ["enlace_docker"] asyncio_mode = "auto" [tool.ruff] From 16b50ca43fb483422a6d16c1ed5b2e36a7a7a890 Mon Sep 17 00:00:00 2001 From: Thor Whalen <1906276+thorwhalen@users.noreply.github.com> Date: Mon, 3 Aug 2026 23:28:13 +0100 Subject: [PATCH 3/4] chore(metadata): SPDX license expression, classifiers, .editorconfig Packaging metadata alignment with the rest of the ecosystem, no behaviour change: - `[project.license] text = "Apache-2.0"` -> `license = "Apache-2.0"`. The table form is deprecated under PEP 639; the built wheel now carries `License-Expression: Apache-2.0` plus an auto-included `License-File`. - Added the standard trove classifiers (the package previously published none). - Added the ecosystem-standard .editorconfig. Verified: `uv build` produces both sdist and wheel, `twine check` PASSED on both, and the wheel's entry_points.txt still carries all four `enlace.backend_strategies` entries plus the `enlace.diagnosers` one. Claude-Session: https://claude.ai/code/session_01VipiLaG4xy7WctqY9w2475 --- .editorconfig | 17 +++++++++++++++++ pyproject.toml | 15 ++++++++++++--- 2 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..88bf4d0 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,17 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{py,toml,yml,yaml}] +indent_style = space +indent_size = 4 + +[*.md] +trim_trailing_whitespace = false + +[Makefile] +indent_style = tab diff --git a/pyproject.toml b/pyproject.toml index 0b258cf..744cd95 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -8,7 +8,19 @@ version = "0.0.4" description = "Docker / docker-compose backend strategies for enlace (mode=docker, compose, image, docker_attached)" readme = "README.md" requires-python = ">=3.10" +license = "Apache-2.0" keywords = ["enlace", "docker", "docker-compose", "asgi", "multi-app"] +classifiers = [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Software Development :: Libraries :: Python Modules", + "Topic :: System :: Systems Administration", +] authors = [{ name = "Thor Whalen" }] dependencies = [ # 0.1.21 is the first release carrying the `enlace.diagnosers` extension @@ -18,9 +30,6 @@ dependencies = [ "httpx>=0.24.0", ] -[project.license] -text = "Apache-2.0" - [project.urls] Homepage = "https://github.com/i2mint/enlace_docker" "Parent project" = "https://github.com/i2mint/enlace" From ca9586e31c895ecff7a599defeedff3c1a37dc4a Mon Sep 17 00:00:00 2001 From: Thor Whalen <1906276+thorwhalen@users.noreply.github.com> Date: Mon, 3 Aug 2026 23:35:38 +0100 Subject: [PATCH 4/4] fix(ci): declare extras = "dev" so pytest-asyncio is installed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wads' reusable workflow now feeds the install step from `[tool.wads.ci.install].extras`, which defaults to "" — so CI installed the package with core dependencies only. Older runs got the `dev` extra by accident, from the install-deps-uv action's own `default: "dev"`, which the workflow now always overrides with the (empty) resolved config value. pytest-asyncio is declared only in the `dev` extra, and `asyncio_mode = "auto"` needs it, so every `async def` test failed: Failed: async def functions are not natively supported. PytestConfigWarning: Unknown config option: asyncio_mode Reproduced locally in a clean 3.10 venv (package + bare pytest, no extra): 11 failed, 42 passed, 2 skipped. Adding the `dev` extra to that same venv: 53 passed, 2 skipped. `CIConfig.from_file` now reports install_extras='dev'. Same fix already carried by the sibling enlace and enlace_auth repos. Claude-Session: https://claude.ai/code/session_01VipiLaG4xy7WctqY9w2475 --- pyproject.toml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index 744cd95..00e4beb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -83,6 +83,14 @@ packages = ["enlace_docker"] [tool.wads.ci] project_name = "enlace_docker" +[tool.wads.ci.install] +# CI must install the `dev` extra: nearly every lifecycle test is `async def`, +# and pytest-asyncio (which `asyncio_mode = "auto"` above depends on) lives +# only there. wads installs bare `pytest` for the test step but no plugins, and +# `install-extras` defaults to empty — without this line those tests all fail +# with "async def functions are not natively supported". +extras = "dev" + [tool.wads.ci.testing] enabled = true python_versions = ["3.10", "3.12"]