Skip to content

Commit

Permalink
Add script to identify backends not part of the pants distribution. (#…
Browse files Browse the repository at this point in the history
…20548)

These mistakes are done over and over again, and goes undetected for too
long.

As a follow up, we could add a check mode and run during CI to catch
early. For now, it's merely a conveniency that can be run manually.

Example output (pre #20529):
```
❯ ./build-support/bin/check_orphaned_plugins.py
These are discovered backends, which are not included in the pantsbuild.pants distribution:
  *   (internal_plugins.releases - intentionally excluded)
  *   (internal_plugins.test_lockfile_fixtures - intentionally excluded)
  * pants.backend.build_files.fmt.ruff
  * pants.backend.experimental.typescript
  *   (pants_explorer.server - intentionally excluded)
```

---------

Co-authored-by: cburroughs <[email protected]>
  • Loading branch information
kaos and cburroughs authored Jan 9, 2025
1 parent 8cdc235 commit 2391e81
Showing 1 changed file with 65 additions and 0 deletions.
65 changes: 65 additions & 0 deletions build-support/bin/check_orphaned_plugins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/usr/bin/env python
# Copyright 2024 Pants project contributors (see CONTRIBUTORS.md).
# Licensed under the Apache License, Version 2.0 (see LICENSE).

from __future__ import annotations

import json
import subprocess
from typing import cast

NOT_DISTRIBUTED_BACKENDS = {
"internal_plugins.releases",
"internal_plugins.test_lockfile_fixtures",
"pants_explorer.server",
}


def main() -> None:
discovered_backends = get_backends()
distributed_backends = get_pants_binary_plugins()
orphaned_backends = discovered_backends - distributed_backends
if orphaned_backends:
print(
"These are discovered backends, which are not included in the pantsbuild.pants distribution:\n * "
+ "\n * ".join(
f" ({be} - intentionally excluded)" if be in NOT_DISTRIBUTED_BACKENDS else be
for be in sorted(orphaned_backends)
)
)


def get_pants_binary_plugins() -> set[str]:
return {
plugin_path_to_backend(plugin)
for plugin in run_pants("peek", "src/python/pants/bin:plugins")[0]["dependencies_raw"]
}


def plugin_path_to_backend(plugin: str) -> str:
return plugin.replace("src/python/", "").replace("/", ".")


def get_backends() -> set[str]:
return set(get_help_info()["name_to_backend_help_info"])


def get_help_info() -> dict:
return run_pants("help-all")


def run_pants(*args: str) -> dict:
return cast(
"dict",
json.loads(
subprocess.run(
["pants", *args],
stdout=subprocess.PIPE,
check=True,
).stdout.decode()
),
)


if __name__ == "__main__":
main()

0 comments on commit 2391e81

Please sign in to comment.