feat(packaging): check Homebrew formula has a resource per runtime dependency
This commit is contained in:
1 parent
86b22226e2
commit
4c2f498e41
1 file changed
+47
@@ -335,6 +335,50 @@ def bump_srcinfo() -> None:
|
||||
say("regenerated contrib/aur/.SRCINFO")
|
||||
|
||||
|
||||
#: Names that may appear as `resource` blocks in the formula. A Python
|
||||
#: dependency without one is silently skipped at install time because Homebrew
|
||||
#: installs the sdist `--no-deps`, which surfaces as an ImportError on launch
|
||||
#: rather than as a packaging error.
|
||||
RESOURCE_LINE = re.compile(r'(?m)^ resource "([^"]+)" do$')
|
||||
|
||||
|
||||
def pypi_name(name: str) -> str:
|
||||
"""PEP 503 name: lowercase, runs of -_. collapsed to a single hyphen."""
|
||||
return re.sub(r"[-_.]+", "-", name).lower()
|
||||
|
||||
|
||||
def runtime_dependencies() -> list[str]:
|
||||
"""The distribution names in `pyproject.toml`'s `[project] dependencies`."""
|
||||
block = re.search(r"(?ms)^dependencies = \[(.*?)^\]$", PYPROJECT.read_text())
|
||||
if block is None:
|
||||
raise fail("no dependencies array in pyproject.toml")
|
||||
return re.findall(r'^\s*"([A-Za-z0-9._-]+)', block.group(1), re.MULTILINE)
|
||||
|
||||
|
||||
def formula_excluded_resources() -> set[str]:
|
||||
"""Dependencies the formula deliberately leaves to other formulae."""
|
||||
match = re.search(r'pypi_packages .*exclude_packages: "([^"]*)"', FORMULA.read_text())
|
||||
if match is None:
|
||||
return set()
|
||||
return {pypi_name(name.strip()) for name in match.group(1).split(",") if name.strip()}
|
||||
|
||||
|
||||
def check_formula_resources(problems: list[str]) -> None:
|
||||
"""Every runtime dependency needs a `resource`, unless another formula has it."""
|
||||
resources = {pypi_name(name) for name in RESOURCE_LINE.findall(FORMULA.read_text())}
|
||||
if not resources:
|
||||
problems.append("formula vendors no Python resources; it would install --no-deps")
|
||||
excluded = formula_excluded_resources()
|
||||
for dependency in runtime_dependencies():
|
||||
name = pypi_name(dependency)
|
||||
if name in excluded or name in resources:
|
||||
continue
|
||||
problems.append(
|
||||
f"formula has no resource for {name}"
|
||||
" (run `brew update-python-resources Formula/b/beefy-player.rb` in the tap)"
|
||||
)
|
||||
|
||||
|
||||
def bump_formula(version: str, checksum: str) -> None:
|
||||
text = FORMULA.read_text()
|
||||
url = RELEASE_ASSET.format(version=version, name=ASSET_NAME)
|
||||
@@ -344,6 +388,8 @@ def bump_formula(version: str, checksum: str) -> None:
|
||||
)
|
||||
# The default branch is master, and --HEAD is only useful if it resolves.
|
||||
text = text.replace('branch: "main"', 'branch: "master"')
|
||||
# The `resource` blocks pin versions, not the release: they only go stale
|
||||
# when pyproject.toml's dependencies change, which `--check` reports.
|
||||
FORMULA.write_text(text)
|
||||
say("wrote contrib/homebrew/Formula/b/beefy-player.rb")
|
||||
|
||||
@@ -435,6 +481,7 @@ def check(version: str) -> int:
|
||||
problems.append('formula head branch is "main"; this repository uses master')
|
||||
if re.search(r'sha256 "0{64}"', formula):
|
||||
problems.append("formula still has the placeholder sha256")
|
||||
check_formula_resources(problems)
|
||||
|
||||
for problem in problems:
|
||||
say(f"drift: {problem}")
|
||||
|
||||
Reference in new issue
Block a user