GRM-9: feat: add runner registry for simplified CLI UX

This commit is contained in:
Emil Simeonov
2026-06-19 00:57:26 +02:00
parent a575a89026
commit 4c08606d0c
10 changed files with 869 additions and 244 deletions
+92 -90
View File
@@ -129,36 +129,33 @@ def update(
raise click.ClickException(_("Update failed: {error}", error=e)) from e
@cli.command(help=_("Start and configure a Gitea Runner on a remote host."))
@click.argument("host")
@click.option(
"--user",
"-u",
default=lambda: os.getenv("GITEA_RUNNER_USER", os.getlogin()),
help=_("SSH user"),
)
@click.option("--name", "-n", help=_("Gitea Runner name (default: host)"))
@cli.command(help=_("Start a registered Gitea Runner."))
@click.argument("runner_name")
@click.option("--host", help=_("Override host from registry"))
@click.option("--user", "-u", help=_("Override user from registry"))
@click.option("--key", "-k", help=_("Override SSH key from registry"))
@click.option(
"--mode",
"-m",
type=click.Choice(["docker", "binary"]),
default="docker",
help=_("Gitea Runner deployment mode (default: docker)"),
help=_("Override deployment mode from registry"),
)
@click.option("--ask-become-pass", is_flag=True, help=_("Prompt for sudo password"))
def start(
host: str,
user: str,
name: str | None,
mode: str,
runner_name: str,
host: str | None,
user: str | None,
key: str | None,
mode: str | None,
ask_become_pass: bool,
) -> None:
manager = RunnerManager()
try:
manager.start(
name=runner_name,
host=host,
user=user,
name=name,
key=key,
mode=mode,
ask_become_pass=ask_become_pass,
)
@@ -166,71 +163,63 @@ def start(
raise click.ClickException(_("Start failed: {error}", error=e)) from e
@cli.command(help=_("Stop a Gitea Runner on a remote host."))
@click.argument("host")
@click.option(
"--user",
"-u",
default=lambda: os.getenv("GITEA_RUNNER_USER", os.getlogin()),
help=_("SSH user"),
)
@click.option("--name", "-n", help=_("Gitea Runner name (default: host)"))
@cli.command(help=_("Stop a registered Gitea Runner."))
@click.argument("runner_name")
@click.option("--host", help=_("Override host from registry"))
@click.option("--user", "-u", help=_("Override user from registry"))
@click.option("--key", "-k", help=_("Override SSH key from registry"))
@click.option("--ask-become-pass", is_flag=True, help=_("Prompt for sudo password"))
def stop(
host: str,
user: str,
name: str | None,
runner_name: str,
host: str | None,
user: str | None,
key: str | None,
ask_become_pass: bool,
) -> None:
manager = RunnerManager()
try:
manager.stop(
name=runner_name,
host=host,
user=user,
name=name,
key=key,
ask_become_pass=ask_become_pass,
)
except GRMError as e:
raise click.ClickException(_("Stop failed: {error}", error=e)) from e
@cli.command(help=_("Enable a Gitea Runner to start on boot."))
@click.argument("host")
@click.option(
"--user",
"-u",
default=lambda: os.getenv("GITEA_RUNNER_USER", os.getlogin()),
help=_("SSH user"),
)
@click.option("--name", "-n", help=_("Gitea Runner name (default: host)"))
@cli.command(help=_("Enable a registered Gitea Runner to start on boot."))
@click.argument("runner_name")
@click.option("--host", help=_("Override host from registry"))
@click.option("--user", "-u", help=_("Override user from registry"))
@click.option("--key", "-k", help=_("Override SSH key from registry"))
@click.option("--ask-become-pass", is_flag=True, help=_("Prompt for sudo password"))
def enable(
host: str,
user: str,
name: str | None,
runner_name: str,
host: str | None,
user: str | None,
key: str | None,
ask_become_pass: bool,
) -> None:
manager = RunnerManager()
try:
manager.enable(
name=runner_name,
host=host,
user=user,
name=name,
key=key,
ask_become_pass=ask_become_pass,
)
except GRMError as e:
raise click.ClickException(_("Enable failed: {error}", error=e)) from e
@cli.command(help=_("Disable a Gitea Runner and deregister it."))
@click.argument("host")
@click.option(
"--user",
"-u",
default=lambda: os.getenv("GITEA_RUNNER_USER", os.getlogin()),
help=_("SSH user"),
)
@click.option("--name", "-n", help=_("Gitea Runner name (default: host)"))
@cli.command(help=_("Disable a registered Gitea Runner and deregister it."))
@click.argument("runner_name")
@click.option("--host", help=_("Override host from registry"))
@click.option("--user", "-u", help=_("Override user from registry"))
@click.option("--key", "-k", help=_("Override SSH key from registry"))
@click.option(
"--token",
"-t",
@@ -241,16 +230,16 @@ def enable(
"--mode",
"-m",
type=click.Choice(["docker", "binary"]),
default="docker",
help=_("Gitea Runner deployment mode (default: docker)"),
help=_("Override deployment mode from registry"),
)
@click.option("--ask-become-pass", is_flag=True, help=_("Prompt for sudo password"))
def disable(
host: str,
user: str,
name: str | None,
runner_name: str,
host: str | None,
user: str | None,
key: str | None,
token: str | None,
mode: str,
mode: str | None,
ask_become_pass: bool,
) -> None:
gitea_url = os.getenv("GITEA_URL", "")
@@ -259,9 +248,10 @@ def disable(
manager = RunnerManager()
try:
manager.disable(
name=runner_name,
host=host,
user=user,
name=name,
key=key,
token=token,
gitea_url=gitea_url,
mode=mode,
@@ -271,36 +261,33 @@ def disable(
raise click.ClickException(_("Disable failed: {error}", error=e)) from e
@cli.command(help=_("Check the status of a Gitea Runner."))
@click.argument("host")
@click.option(
"--user",
"-u",
default=lambda: os.getenv("GITEA_RUNNER_USER", os.getlogin()),
help=_("SSH user"),
)
@click.option("--name", "-n", help=_("Gitea Runner name (default: host)"))
@cli.command(help=_("Check the status of a registered Gitea Runner."))
@click.argument("runner_name")
@click.option("--host", help=_("Override host from registry"))
@click.option("--user", "-u", help=_("Override user from registry"))
@click.option("--key", "-k", help=_("Override SSH key from registry"))
@click.option(
"--mode",
"-m",
type=click.Choice(["docker", "binary"]),
default="docker",
help=_("Gitea Runner deployment mode (default: docker)"),
help=_("Override deployment mode from registry"),
)
@click.option("--ask-become-pass", is_flag=True, help=_("Prompt for sudo password"))
def status(
host: str,
user: str,
name: str | None,
mode: str,
runner_name: str,
host: str | None,
user: str | None,
key: str | None,
mode: str | None,
ask_become_pass: bool,
) -> None:
manager = RunnerManager()
try:
manager.status(
name=runner_name,
host=host,
user=user,
name=name,
key=key,
mode=mode,
ask_become_pass=ask_become_pass,
)
@@ -308,15 +295,11 @@ def status(
raise click.ClickException(_("Status check failed: {error}", error=e)) from e
@cli.command(help=_("Remove a Gitea Runner completely."))
@click.argument("host")
@click.option(
"--user",
"-u",
default=lambda: os.getenv("GITEA_RUNNER_USER", os.getlogin()),
help=_("SSH user"),
)
@click.option("--name", "-n", help=_("Gitea Runner name (default: host)"))
@cli.command(help=_("Remove a registered Gitea Runner completely."))
@click.argument("runner_name")
@click.option("--host", help=_("Override host from registry"))
@click.option("--user", "-u", help=_("Override user from registry"))
@click.option("--key", "-k", help=_("Override SSH key from registry"))
@click.option(
"--token",
"-t",
@@ -327,16 +310,16 @@ def status(
"--mode",
"-m",
type=click.Choice(["docker", "binary"]),
default="docker",
help=_("Gitea Runner deployment mode (default: docker)"),
help=_("Override deployment mode from registry"),
)
@click.option("--ask-become-pass", is_flag=True, help=_("Prompt for sudo password"))
def remove(
host: str,
user: str,
name: str | None,
runner_name: str,
host: str | None,
user: str | None,
key: str | None,
token: str | None,
mode: str,
mode: str | None,
ask_become_pass: bool,
) -> None:
gitea_url = os.getenv("GITEA_URL", "")
@@ -345,9 +328,10 @@ def remove(
manager = RunnerManager()
try:
manager.remove(
name=runner_name,
host=host,
user=user,
name=name,
key=key,
token=token,
gitea_url=gitea_url,
mode=mode,
@@ -355,3 +339,21 @@ def remove(
)
except GRMError as e:
raise click.ClickException(_("Remove failed: {error}", error=e)) from e
@cli.command(name="list", help=_("List all registered runners with live status."))
def list_runners() -> None:
manager = RunnerManager()
try:
runners = manager.list_runners()
except GRMError as e:
raise click.ClickException(_("List failed: {error}", error=e)) from e
if not runners:
click.echo(_("No runners registered. Use 'grm install' to add one."))
return
click.echo(f"{'NAME':<20} {'HOST':<18} {'USER':<12} {'MODE':<8} {'STATUS'}")
click.echo("-" * 70)
for r in runners:
click.echo(f"{r['name']:<20} {r['host']:<18} {r['user']:<12} {r['mode']:<8} {r['status']}")