ci: qualify workspace packages that share a name with a dependency (#9065)

The planned package list is passed to cargo as bare -p names. The zstd
compat crate is named zstd so it can patch crates.io, and with zstd
0.14.3 also locked, cargo rejects -p zstd as ambiguous, failing
Workspace Lint and Build on main since #9059.

Qualify such names with the local version from Cargo.lock, and fail
loudly if even that cannot disambiguate.
This commit is contained in:
Chris An
2026-10-30 06:09:42 +08:00
committed by GitHub
parent 4fcbf60f10
commit c67f9fc377
2 changed files with 31 additions and 1 deletions
+21 -1
View File
@@ -8,6 +8,7 @@ from pathlib import Path
import platform
import subprocess
import sys
import tomllib
import xml.etree.ElementTree as ET
from e2e_binary import ROOT, file_hash, source_identity
@@ -71,10 +72,29 @@ def package_args(configuration):
not isinstance(name, str) or not name or name.startswith("-") or name == "e2e_test" for name in packages
):
raise ValueError("CI_PACKAGES must be a nonempty workspace package list")
return [part for name in sorted(set(packages)) for part in ("-p", name)]
return [part for name in sorted(set(packages)) for part in ("-p", package_spec(name))]
return CONFIGURATIONS[configuration]
def locked_packages():
return tomllib.loads((ROOT / "Cargo.lock").read_text()).get("package", [])
def package_spec(name):
"""Qualify a workspace package whose name also resolves to a dependency.
`crates/zstd-compat` is named `zstd` to patch crates.io, so a bare `-p zstd`
is ambiguous whenever another `zstd` version is locked.
"""
entries = [entry for entry in locked_packages() if entry.get("name") == name]
if len(entries) <= 1:
return name
local = [entry for entry in entries if "source" not in entry]
if len(local) != 1 or any(entry["version"] == local[0]["version"] for entry in entries if entry is not local[0]):
raise ValueError(f"workspace package {name} cannot be selected unambiguously")
return f"{name}@{local[0]['version']}"
def build(archive, configuration):
before = identity(configuration)
archive.parent.mkdir(parents=True, exist_ok=True)
+10
View File
@@ -118,6 +118,16 @@ class ArtifactIdentityTests(unittest.TestCase):
with patch.dict(os.environ, {"CI_PACKAGES": '["rustfs-utils", "rustfs", "rustfs"]'}):
self.assertEqual(artifact.package_args("workspace"), ["-p", "rustfs", "-p", "rustfs-utils"])
self.assertEqual(artifact.package_args("e2e"), ["-p", "e2e_test"])
locked = [{"name": "zstd", "version": "0.13.3"},
{"name": "zstd", "version": "0.14.3", "source": "registry+https://github.com/rust-lang/crates.io-index"},
{"name": "rustfs", "version": "0.1.0"}]
with patch.object(artifact, "locked_packages", return_value=locked), \
patch.dict(os.environ, {"CI_PACKAGES": '["zstd", "rustfs"]'}):
self.assertEqual(artifact.package_args("workspace"), ["-p", "rustfs", "-p", "zstd@0.13.3"])
for clash in ([*locked[:2], {"name": "zstd", "version": "0.14.3"}], [locked[1], {**locked[1], "version": "0.15.0"}]):
with self.subTest(clash=clash), patch.object(artifact, "locked_packages", return_value=clash), \
self.assertRaisesRegex(ValueError, "unambiguously"):
artifact.package_args("workspace")
for value in ('[]', '{}', '[null]', '["--all-features"]', '["e2e_test"]', '[""]'):
with self.subTest(value=value), patch.dict(os.environ, {"CI_PACKAGES": value}), self.assertRaises(ValueError):
artifact.package_args("workspace")