This is an automated email from the ASF dual-hosted git repository.

sbp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tooling-releases-client.git


The following commit(s) were added to refs/heads/main by this push:
     new 6f0afa8  Use a common prefix for all subcommand apps
6f0afa8 is described below

commit 6f0afa849d4d3dd24456cf3205142de6aed77625
Author: Sean B. Palmer <[email protected]>
AuthorDate: Thu Jul 10 19:06:45 2025 +0100

    Use a common prefix for all subcommand apps
---
 pyproject.toml          |  4 +--
 src/atrclient/client.py | 84 ++++++++++++++++++++++++++-----------------------
 tests/cli_version.t     |  2 +-
 uv.lock                 |  4 +--
 4 files changed, 49 insertions(+), 45 deletions(-)

diff --git a/pyproject.toml b/pyproject.toml
index 5728a35..597ead7 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -11,7 +11,7 @@ build-backend = "hatchling.build"
 
 [project]
 name            = "apache-trusted-releases"
-version         = "0.20250710.1756"
+version         = "0.20250710.1806"
 description     = "ATR CLI and Python API"
 readme          = "README.md"
 requires-python = ">=3.13"
@@ -48,4 +48,4 @@ atr = "atrclient.client:main"
 packages = ["src/atrclient"]
 
 [tool.uv]
-exclude-newer = "2025-07-10T17:56:00Z"
+exclude-newer = "2025-07-10T18:06:00Z"
diff --git a/src/atrclient/client.py b/src/atrclient/client.py
index 182acf7..9f13868 100755
--- a/src/atrclient/client.py
+++ b/src/atrclient/client.py
@@ -46,14 +46,14 @@ if TYPE_CHECKING:
     from collections.abc import Generator
 
 APP: cyclopts.App = cyclopts.App()
-CHECKS: cyclopts.App = cyclopts.App(name="checks", help="Check result 
operations.")
-CONFIG: cyclopts.App = cyclopts.App(name="config", help="Configuration 
operations.")
-DEV: cyclopts.App = cyclopts.App(name="dev", help="Developer operations.")
-DRAFT: cyclopts.App = cyclopts.App(name="draft", help="Draft operations.")
-JWT: cyclopts.App = cyclopts.App(name="jwt", help="JWT operations.")
-RELEASE: cyclopts.App = cyclopts.App(name="release", help="Release 
operations.")
+APP_CHECKS: cyclopts.App = cyclopts.App(name="checks", help="Check result 
operations.")
+APP_CONFIG: cyclopts.App = cyclopts.App(name="config", help="Configuration 
operations.")
+APP_DEV: cyclopts.App = cyclopts.App(name="dev", help="Developer operations.")
+APP_DRAFT: cyclopts.App = cyclopts.App(name="draft", help="Draft operations.")
+APP_JWT: cyclopts.App = cyclopts.App(name="jwt", help="JWT operations.")
+APP_RELEASE: cyclopts.App = cyclopts.App(name="release", help="Release 
operations.")
+APP_VOTE: cyclopts.App = cyclopts.App(name="vote", help="Vote operations.")
 VERSION: str = metadata.version("apache-trusted-releases")
-VOTE: cyclopts.App = cyclopts.App(name="vote", help="Vote operations.")
 YAML_DEFAULTS: dict[str, Any] = {"asf": {}, "atr": {}, "tokens": {}}
 YAML_SCHEMA: strictyaml.Map = strictyaml.Map(
     {
@@ -73,7 +73,9 @@ YAML_SCHEMA: strictyaml.Map = strictyaml.Map(
 )
 
 
[email protected](name="exceptions", help="Get check exceptions for a release 
revision.")
+@APP_CHECKS.command(
+    name="exceptions", help="Get check exceptions for a release revision."
+)
 def app_checks_exceptions(
     project: str,
     version: str,
@@ -88,7 +90,7 @@ def app_checks_exceptions(
     checks_display_status("exception", results, members=members)
 
 
[email protected](name="failures", help="Get check failures for a release 
revision.")
+@APP_CHECKS.command(name="failures", help="Get check failures for a release 
revision.")
 def app_checks_failures(
     project: str,
     version: str,
@@ -103,7 +105,7 @@ def app_checks_failures(
     checks_display_status("failure", results, members=members)
 
 
[email protected](name="status", help="Get check status for a release revision.")
+@APP_CHECKS.command(name="status", help="Get check status for a release 
revision.")
 def app_checks_status(
     project: str,
     version: str,
@@ -138,7 +140,7 @@ def app_checks_status(
     checks_display(results, verbose)
 
 
[email protected](name="warnings", help="Get check warnings for a release 
revision.")
+@APP_CHECKS.command(name="warnings", help="Get check warnings for a release 
revision.")
 def app_checks_warnings(
     project: str,
     version: str,
@@ -153,7 +155,7 @@ def app_checks_warnings(
     checks_display_status("warning", results, members=members)
 
 
[email protected](name="file", help="Display the configuration file contents.")
+@APP_CONFIG.command(name="file", help="Display the configuration file 
contents.")
 def app_config_file() -> None:
     path = config_path()
     if not path.exists():
@@ -164,12 +166,12 @@ def app_config_file() -> None:
             print(chunk, end="")
 
 
[email protected](name="path", help="Show the configuration file path.")
+@APP_CONFIG.command(name="path", help="Show the configuration file path.")
 def app_config_path() -> None:
     print(config_path())
 
 
[email protected](name="env", help="Show the environment variables.")
+@APP_DEV.command(name="env", help="Show the environment variables.")
 def app_dev_env() -> None:
     total = 0
     for key, value in sorted(os.environ.items()):
@@ -180,7 +182,9 @@ def app_dev_env() -> None:
     print(f"There are {total} ATR_* environment variables.")
 
 
[email protected](name="stamp", help="Update version and exclude-newer in 
pyproject.toml.")
+@APP_DEV.command(
+    name="stamp", help="Update version and exclude-newer in pyproject.toml."
+)
 def app_dev_stamp() -> None:
     path = pathlib.Path("pyproject.toml")
     if not path.exists():
@@ -217,6 +221,16 @@ def app_dev_stamp() -> None:
         print("Updated tests/cli_version.t.")
 
 
+@APP_DRAFT.command(name="delete", help="Delete a draft release.")
+def app_draft_delete(project: str, version: str, /) -> None:
+    jwt_value = config_jwt_usable()
+    host, verify_ssl = config_host_get()
+    payload: dict[str, str] = {"project_name": project, "version": version}
+    url = f"https://{host}/api/draft/delete";
+    result = asyncio.run(web_post(url, payload, jwt_value, verify_ssl))
+    print(result)
+
+
 @APP.command(name="docs", help="Show comprehensive CLI documentation in 
Markdown.")
 def app_docs() -> None:
     old_help_format = APP.help_format
@@ -240,7 +254,7 @@ def app_drop(path: str, /) -> None:
     print(f"Removed {path}.")
 
 
[email protected](name="dump", help="Show decoded JWT payload from stored config.")
+@APP_JWT.command(name="dump", help="Show decoded JWT payload from stored 
config.")
 def app_jwt_dump() -> None:
     jwt_value = config_jwt_get()
 
@@ -256,7 +270,7 @@ def app_jwt_dump() -> None:
     print(json.dumps(payload, indent=None))
 
 
[email protected](name="info", help="Show JWT payload in human-readable form.")
+@APP_JWT.command(name="info", help="Show JWT payload in human-readable form.")
 def app_jwt_info() -> None:
     _jwt_value, payload = config_jwt_payload()
 
@@ -269,7 +283,7 @@ def app_jwt_info() -> None:
     print("\n".join(lines))
 
 
[email protected](
+@APP_JWT.command(
     name="refresh", help="Fetch a JWT using the stored PAT and store it in 
config."
 )
 def app_jwt_refresh(asf_uid: str | None = None) -> None:
@@ -277,7 +291,7 @@ def app_jwt_refresh(asf_uid: str | None = None) -> None:
     print(jwt_value)
 
 
[email protected](name="show", help="Show stored JWT token.")
+@APP_JWT.command(name="show", help="Show stored JWT token.")
 def app_jwt_show() -> None:
     return app_show("tokens.jwt")
 
@@ -293,7 +307,7 @@ def app_list(project: str, version: str, revision: str | 
None = None, /) -> None
     print(result)
 
 
[email protected](name="info", help="Show information about a release.")
+@APP_RELEASE.command(name="info", help="Show information about a release.")
 def app_release_info(project: str, version: str, /) -> None:
     host, verify_ssl = config_host_get()
     url = f"https://{host}/api/releases/{project}/{version}";
@@ -301,7 +315,7 @@ def app_release_info(project: str, version: str, /) -> None:
     print(result)
 
 
[email protected](name="list", help="List releases for a project.")
+@APP_RELEASE.command(name="list", help="List releases for a project.")
 def app_release_list(project: str, /) -> None:
     # TODO: Support showing all of a user's releases if no project is provided
     host, verify_ssl = config_host_get()
@@ -310,7 +324,7 @@ def app_release_list(project: str, /) -> None:
     releases_display(result)
 
 
[email protected](name="start", help="Start a release.")
+@APP_RELEASE.command(name="start", help="Start a release.")
 def app_release_start(project: str, version: str, /) -> None:
     jwt_value = config_jwt_usable()
     host, verify_ssl = config_host_get()
@@ -378,7 +392,7 @@ def app_upload(project: str, version: str, path: str, 
filepath: str, /) -> None:
     print(result)
 
 
[email protected](name="start", help="Start a vote.")
+@APP_VOTE.command(name="start", help="Start a vote.")
 def app_vote_start(
     project: str,
     version: str,
@@ -411,16 +425,6 @@ def app_vote_start(
     print(result)
 
 
[email protected](name="delete", help="Delete a draft release.")
-def app_draft_delete(project: str, version: str, /) -> None:
-    jwt_value = config_jwt_usable()
-    host, verify_ssl = config_host_get()
-    payload: dict[str, str] = {"project_name": project, "version": version}
-    url = f"https://{host}/api/draft/delete";
-    result = asyncio.run(web_post(url, payload, jwt_value, verify_ssl))
-    print(result)
-
-
 def checks_display(results: list[dict[str, Any]], verbose: bool = False) -> 
None:
     if not results:
         print("No check results found for this revision.")
@@ -768,13 +772,13 @@ def show_warning(message: str) -> None:
 
 
 def subcommands_register(app: cyclopts.App) -> None:
-    app.command(CHECKS)
-    app.command(CONFIG)
-    app.command(DEV)
-    app.command(DRAFT)
-    app.command(JWT)
-    app.command(RELEASE)
-    app.command(VOTE)
+    app.command(APP_CHECKS)
+    app.command(APP_CONFIG)
+    app.command(APP_DEV)
+    app.command(APP_DRAFT)
+    app.command(APP_JWT)
+    app.command(APP_RELEASE)
+    app.command(APP_VOTE)
 
 
 def timestamp_format(ts: int | str | None) -> str | None:
diff --git a/tests/cli_version.t b/tests/cli_version.t
index efde72d..de10014 100644
--- a/tests/cli_version.t
+++ b/tests/cli_version.t
@@ -1,2 +1,2 @@
 $ atr --version
-0.20250710.1756
+0.20250710.1806
diff --git a/uv.lock b/uv.lock
index 8f76a75..20dd570 100644
--- a/uv.lock
+++ b/uv.lock
@@ -2,7 +2,7 @@ version = 1
 requires-python = ">=3.13"
 
 [options]
-exclude-newer = "2025-07-10T17:56:00Z"
+exclude-newer = "2025-07-10T18:06:00Z"
 
 [[package]]
 name = "aiohappyeyeballs"
@@ -74,7 +74,7 @@ wheels = [
 
 [[package]]
 name = "apache-trusted-releases"
-version = "0.20250710.1756"
+version = "0.20250710.1806"
 source = { editable = "." }
 dependencies = [
     { name = "aiohttp" },


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to