diff --git a/tools/dev/README.md b/tools/dev/README.md index 1bb85f2a9..46f412a5c 100644 --- a/tools/dev/README.md +++ b/tools/dev/README.md @@ -27,6 +27,10 @@ declares ruff, mypy, and pytest as its dependencies, and every other workspace member names `magpie-dev` in its own `[dependency-groups] dev` instead of repeating the pins. Bump a version here and the whole workspace moves together. +One deliberate exception: `tools/vetted-ops` declares no `dev` group. It ships +as a plugin and runs from outside the workspace, where `magpie-dev` cannot +resolve; its tests get the toolchain from the root `dev` group instead. + Each member's environment stays self-contained — the checks still run `uv run --directory --project . python -m `, so no member depends on tools leaking in from the root environment. Only the *declaration* is shared. diff --git a/tools/vetted-ops/pyproject.toml b/tools/vetted-ops/pyproject.toml index e40c9cbc8..692ac2173 100644 --- a/tools/vetted-ops/pyproject.toml +++ b/tools/vetted-ops/pyproject.toml @@ -80,7 +80,11 @@ minversion = "8.0" addopts = "-ra -q" testpaths = ["tests"] -[dependency-groups] -# The shared toolchain (mypy, pytest, ruff) comes from `magpie-dev` -# (tools/dev), declared once for the whole workspace. -dev = ["magpie-dev"] +# No `[dependency-groups] dev` here, unlike the other workspace members. This +# project ships as the `magpie-vetted-ops` plugin, and the documented runner is +# `uv run --project /tools/vetted-ops vetted-op-read …`. uv resolves +# every dependency group before it runs anything, and `magpie-dev` only +# resolves through the workspace root's `[tool.uv.sources]`, which the plugin +# does not ship, so a `dev` group makes every plugin invocation fail. The +# shared toolchain still reaches this project's tests: CI and the workspace +# checks sync the root `dev` group, which names `magpie-dev`. diff --git a/tools/vetted-ops/tests/test_vetted_ops.py b/tools/vetted-ops/tests/test_vetted_ops.py index 7a90f33d2..e2aec0167 100644 --- a/tools/vetted-ops/tests/test_vetted_ops.py +++ b/tools/vetted-ops/tests/test_vetted_ops.py @@ -18,6 +18,7 @@ from __future__ import annotations import json +import tomllib import urllib.error import urllib.request from email.message import Message @@ -1455,3 +1456,13 @@ def test_run_http_execution_non_https_rejected(capsys: pytest.CaptureFixture[str rc = cli._run_http({"url": "http://insecure.example.com"}, body=None) assert rc == cli.EXIT_COMMAND assert "missing valid https://" in capsys.readouterr().err + + +def test_project_resolves_outside_the_workspace() -> None: + # The plugin ships this directory alone, without the workspace root, and + # runs it with `uv run --project`. uv resolves every dependency group first, + # so a group naming a workspace-only package (`magpie-dev`) or a + # workspace-relative source breaks every plugin invocation. + pyproject = tomllib.loads((Path(__file__).parents[1] / "pyproject.toml").read_text()) + assert "dependency-groups" not in pyproject + assert "sources" not in pyproject.get("tool", {}).get("uv", {}) diff --git a/uv.lock b/uv.lock index 91127517c..d9eb488af 100644 --- a/uv.lock +++ b/uv.lock @@ -2155,16 +2155,6 @@ name = "vetted-ops" version = "0.1.0" source = { editable = "tools/vetted-ops" } -[package.dev-dependencies] -dev = [ - { name = "magpie-dev" }, -] - -[package.metadata] - -[package.metadata.requires-dev] -dev = [{ name = "magpie-dev", editable = "tools/dev" }] - [[package]] name = "vulnogram-api" version = "0.1.0"