Coverage for frappe_manager / commands / ngrok.py: 29%
45 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-07-02 18:13 +0530
« prev ^ index » next coverage.py v7.13.5, created at 2026-07-02 18:13 +0530
1from typing import Annotated
3import typer
4from typer_examples import example
6from frappe_manager.metadata_manager import FMConfigManager
7from frappe_manager.ngrok import create_tunnel
8from frappe_manager.output_manager import get_global_output_handler
9from frappe_manager.output_manager.context_managers import spinner, temporary_stop
10from frappe_manager.site_manager.exceptions import BenchNotRunning
11from frappe_manager.site_manager.site import Bench
12from frappe_manager.utils.callbacks import sitename_callback, sites_autocompletion_callback
15@example(
16 "Create ngrok tunnel for bench",
17 "{benchname} --auth-token YOUR_TOKEN",
18 detail="Creates a public ngrok tunnel for the bench using a specified auth token.",
19 benchname="mybench",
20)
21@example(
22 "Use saved auth token from config",
23 "{benchname}",
24 detail="Uses an auth token stored in FM configuration to create the tunnel without passing it on the command line.",
25 benchname="mybench",
26)
27def ngrok(
28 ctx: typer.Context,
29 benchname: Annotated[
30 str | None,
31 typer.Argument(
32 help="Name of the bench.",
33 autocompletion=sites_autocompletion_callback,
34 callback=sitename_callback,
35 ),
36 ] = None,
37 auth_token: Annotated[
38 str | None,
39 typer.Option("--auth-token", "-t", help="Ngrok authentication token", envvar="NGROK_AUTHTOKEN"),
40 ] = None,
41 save_token: Annotated[
42 bool | None,
43 typer.Option(
44 "--save-token/--no-save-token",
45 help="Save or don't save the ngrok auth token to config for future use",
46 ),
47 ] = None,
48):
49 """
50 Create ngrok tunnel for bench.
52 Provisions a public URL for local benches using ngrok; requires an auth token either via flag or config.
53 """
54 services_manager = ctx.obj["services"]
55 verbose = ctx.obj["verbose"]
57 output = get_global_output_handler()
58 logger = ctx.obj.get("logger")
59 bench = Bench.get_object(benchname, services_manager, logger=logger, output_handler=output)
61 if not bench.running:
62 raise BenchNotRunning(bench_name=bench.name)
64 fm_config_manager: FMConfigManager = ctx.obj["fm_config_manager"]
66 with spinner(output, "Setting up ngrok tunnel"):
67 if not auth_token and fm_config_manager.ngrok_auth_token:
68 auth_token = fm_config_manager.ngrok_auth_token
69 output.print("Using ngrok auth token from config file", emoji_code=":key:")
70 elif not auth_token:
71 output.display_error(
72 "Ngrok auth token is required. Please provide it with --auth-token or set NGROK_AUTHTOKEN environment variable.",
73 )
74 raise typer.Exit(1)
76 if auth_token and not fm_config_manager.ngrok_auth_token:
77 output.print("New auth token provided", emoji_code=":new:")
79 if save_token is None:
80 with temporary_stop(output):
81 should_save = output.prompt_ask(
82 prompt="Do you want to save the ngrok auth token in config for future use?",
83 choices=["yes", "no"],
84 required_flag="--save-token or --no-save-token",
85 )
86 else:
87 should_save = "yes" if save_token else "no"
89 if should_save == "yes":
90 output.print("Saving auth token to config...", emoji_code=":floppy_disk:")
91 fm_config_manager.ngrok_auth_token = auth_token
92 fm_config_manager.export_to_toml()
93 output.print("Saved ngrok auth token to config", emoji_code=":white_check_mark:")
95 output.print(f"Creating ngrok tunnel for {bench.name}", emoji_code=":link:")
97 try:
98 create_tunnel(bench.name, auth_token)
99 except Exception as e:
100 output.display_error(f"Failed to create tunnel: {e!s}")
101 raise