blob: d43e105960a43462dcf07e2f6ef282e44b6cdb7d [file] [edit]
# /// script
# requires-python = ">=3.12"
# dependencies = []
#
# [tool.ty.rules]
# truthiness-test-of-none-union = "warn"
# blanket-ignore-comment = "warn"
# missing-type-argument = "warn"
# possibly-unresolved-reference = "warn"
# unsound-return-statement = "warn"
# unsound-yield = "warn"
# unsupported-dynamic-base = "warn"
# division-by-zero = "warn"
# dynamic-function-decorator-return = "warn"
# unsound-assignment = "warn"
# redundant-condition-strict = "warn"
# disjoint-cast = "warn"
# missing-direct-dependency = "warn"
#
# [tool.uv]
# no-build = true
# exclude-newer = "P7D"
# ///
"""Supplement cargo-deny bans with workspace dependency policy checks."""
from __future__ import annotations
import json
import subprocess
import sys
import tomllib
from pathlib import Path
from typing import Any
ROOT = Path(__file__).resolve().parent.parent
def inspect(
metadata: dict[str, Any], workspace_dependencies: dict[str, Any]
) -> list[str]:
"""Return errors for workspace requests for external default features."""
root = Path(metadata["workspace_root"]).resolve()
member_ids = set(metadata["workspace_members"])
members = [
package for package in metadata["packages"] if package["id"] in member_ids
]
member_paths = {
Path(package["manifest_path"]).resolve().parent for package in members
}
errors: set[str] = set()
def is_external(path: str | None) -> bool:
return path is None or (root / path).resolve() not in member_paths
# Metadata omits unused workspace dependency definitions.
for name, specification in workspace_dependencies.items():
dependency = {} if isinstance(specification, str) else specification
if is_external(dependency.get("path")) and (
dependency.get("default-features", True)
or "default" in dependency.get("features", [])
):
errors.add(
f"Cargo.toml: workspace.dependencies.{name} requests default features"
)
for package in members:
manifest = Path(package["manifest_path"]).resolve()
location = (
manifest.relative_to(root) if manifest.is_relative_to(root) else manifest
)
external_aliases = set()
# Cargo has already applied workspace inheritance and target-specific rules.
for dependency in package["dependencies"]:
if not is_external(dependency.get("path")):
continue
alias = dependency.get("rename") or dependency["name"]
external_aliases.add(alias)
if (
dependency["uses_default_features"]
or "default" in dependency["features"]
):
errors.add(
f"{location}: dependency {alias!r} requests default features"
)
for feature, activations in package["features"].items():
for activation in activations:
alias, separator, target = activation.partition("/")
if (
separator
and target == "default"
and alias.removesuffix("?") in external_aliases
):
errors.add(
f"{location}: features.{feature} requests {activation!r}"
)
return sorted(errors)
def inspect_build_scripts(
metadata: dict[str, Any], allow_build_scripts: list[str]
) -> list[str]:
"""Return errors for stale entries in the external build-script allowlist."""
member_ids = set(metadata["workspace_members"])
build_script_crates = {
package["name"]
for package in metadata["packages"]
if package["id"] not in member_ids
and any("custom-build" in target["kind"] for target in package["targets"])
}
return [
f".cargo/deny.toml: bans.build.allow-build-scripts entry {name!r} "
"does not match any dependency with a build script"
for name in sorted(set(allow_build_scripts) - build_script_crates)
]
def main() -> int:
command = [
"cargo",
"metadata",
"--locked",
"--offline",
"--all-features",
"--format-version",
"1",
]
try:
raw_metadata = subprocess.check_output(command, cwd=ROOT, text=True)
except subprocess.CalledProcessError as error:
return error.returncode
metadata = json.loads(raw_metadata)
root = Path(metadata["workspace_root"])
with (root / "Cargo.toml").open("rb") as manifest:
workspace_dependencies = (
tomllib.load(manifest).get("workspace", {}).get("dependencies", {})
)
with (root / ".cargo" / "deny.toml").open("rb") as config:
allow_build_scripts = tomllib.load(config)["bans"]["build"][
"allow-build-scripts"
]
feature_errors = inspect(metadata, workspace_dependencies)
for error in feature_errors:
print(f"error: {error}", file=sys.stderr)
if feature_errors:
print(
"Set default-features = false and request named features explicitly.",
file=sys.stderr,
)
build_script_errors = inspect_build_scripts(metadata, allow_build_scripts)
for error in build_script_errors:
print(f"error: {error}", file=sys.stderr)
if build_script_errors:
print(
"Remove stale entries from bans.build.allow-build-scripts.", file=sys.stderr
)
if feature_errors or build_script_errors:
return 1
print("Workspace external dependencies request no default features.")
print("The cargo-deny build-script allowlist has no stale entries.")
return 0
if __name__ == "__main__":
sys.exit(main())