golf-mcp 0.2.16__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- golf/__init__.py +1 -0
- golf/auth/__init__.py +277 -0
- golf/auth/api_key.py +73 -0
- golf/auth/factory.py +360 -0
- golf/auth/helpers.py +175 -0
- golf/auth/providers.py +586 -0
- golf/auth/registry.py +256 -0
- golf/cli/__init__.py +1 -0
- golf/cli/branding.py +191 -0
- golf/cli/main.py +377 -0
- golf/commands/__init__.py +5 -0
- golf/commands/build.py +81 -0
- golf/commands/init.py +290 -0
- golf/commands/run.py +137 -0
- golf/core/__init__.py +1 -0
- golf/core/builder.py +1884 -0
- golf/core/builder_auth.py +209 -0
- golf/core/builder_metrics.py +221 -0
- golf/core/builder_telemetry.py +99 -0
- golf/core/config.py +199 -0
- golf/core/parser.py +1085 -0
- golf/core/telemetry.py +492 -0
- golf/core/transformer.py +231 -0
- golf/examples/__init__.py +0 -0
- golf/examples/basic/.env.example +4 -0
- golf/examples/basic/README.md +133 -0
- golf/examples/basic/auth.py +76 -0
- golf/examples/basic/golf.json +5 -0
- golf/examples/basic/prompts/welcome.py +27 -0
- golf/examples/basic/resources/current_time.py +34 -0
- golf/examples/basic/resources/info.py +28 -0
- golf/examples/basic/resources/weather/city.py +46 -0
- golf/examples/basic/resources/weather/client.py +48 -0
- golf/examples/basic/resources/weather/current.py +36 -0
- golf/examples/basic/resources/weather/forecast.py +36 -0
- golf/examples/basic/tools/calculator.py +94 -0
- golf/examples/basic/tools/say/hello.py +65 -0
- golf/metrics/__init__.py +10 -0
- golf/metrics/collector.py +320 -0
- golf/metrics/registry.py +12 -0
- golf/telemetry/__init__.py +23 -0
- golf/telemetry/instrumentation.py +1402 -0
- golf/utilities/__init__.py +12 -0
- golf/utilities/context.py +53 -0
- golf/utilities/elicitation.py +170 -0
- golf/utilities/sampling.py +221 -0
- golf_mcp-0.2.16.dist-info/METADATA +262 -0
- golf_mcp-0.2.16.dist-info/RECORD +52 -0
- golf_mcp-0.2.16.dist-info/WHEEL +5 -0
- golf_mcp-0.2.16.dist-info/entry_points.txt +2 -0
- golf_mcp-0.2.16.dist-info/licenses/LICENSE +201 -0
- golf_mcp-0.2.16.dist-info/top_level.txt +1 -0
golf/cli/main.py
ADDED
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
"""CLI entry points for GolfMCP."""
|
|
2
|
+
|
|
3
|
+
import atexit
|
|
4
|
+
import os
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
|
|
7
|
+
import typer
|
|
8
|
+
from rich.console import Console
|
|
9
|
+
|
|
10
|
+
from golf import __version__
|
|
11
|
+
from golf.cli.branding import create_welcome_banner, create_command_header
|
|
12
|
+
from golf.core.config import find_project_root, load_settings
|
|
13
|
+
from golf.core.telemetry import (
|
|
14
|
+
is_telemetry_enabled,
|
|
15
|
+
set_telemetry_enabled,
|
|
16
|
+
shutdown,
|
|
17
|
+
track_event,
|
|
18
|
+
track_detailed_error,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
# Create console for rich output
|
|
22
|
+
console = Console()
|
|
23
|
+
|
|
24
|
+
# Create the typer app instance
|
|
25
|
+
app = typer.Typer(
|
|
26
|
+
name="golf",
|
|
27
|
+
help="GolfMCP: A Pythonic framework for building MCP servers with zero boilerplate",
|
|
28
|
+
add_completion=False,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# Register telemetry shutdown on exit
|
|
32
|
+
atexit.register(shutdown)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _version_callback(value: bool) -> None:
|
|
36
|
+
"""Print version and exit if --version flag is used."""
|
|
37
|
+
if value:
|
|
38
|
+
create_welcome_banner(__version__, console)
|
|
39
|
+
raise typer.Exit()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@app.callback()
|
|
43
|
+
def callback(
|
|
44
|
+
version: bool = typer.Option(
|
|
45
|
+
None,
|
|
46
|
+
"--version",
|
|
47
|
+
"-V",
|
|
48
|
+
help="Show the version and exit.",
|
|
49
|
+
callback=_version_callback,
|
|
50
|
+
is_eager=True,
|
|
51
|
+
),
|
|
52
|
+
verbose: bool = typer.Option(False, "--verbose", "-v", help="Increase verbosity of output."),
|
|
53
|
+
no_telemetry: bool = typer.Option(
|
|
54
|
+
False,
|
|
55
|
+
"--no-telemetry",
|
|
56
|
+
help="Disable telemetry collection (persists for future commands).",
|
|
57
|
+
),
|
|
58
|
+
test: bool = typer.Option(
|
|
59
|
+
False,
|
|
60
|
+
"--test",
|
|
61
|
+
hidden=True,
|
|
62
|
+
help="Run in test mode (disables telemetry for this execution only).",
|
|
63
|
+
),
|
|
64
|
+
) -> None:
|
|
65
|
+
"""GolfMCP: A Pythonic framework for building MCP servers with zero boilerplate."""
|
|
66
|
+
# Set verbosity in environment for other components to access
|
|
67
|
+
if verbose:
|
|
68
|
+
os.environ["GOLF_VERBOSE"] = "1"
|
|
69
|
+
|
|
70
|
+
# Set test mode if flag is used (temporary, just for this execution)
|
|
71
|
+
if test:
|
|
72
|
+
set_telemetry_enabled(False, persist=False)
|
|
73
|
+
os.environ["GOLF_TEST_MODE"] = "1"
|
|
74
|
+
|
|
75
|
+
# Set telemetry preference if flag is used (permanent)
|
|
76
|
+
if no_telemetry:
|
|
77
|
+
set_telemetry_enabled(False, persist=True)
|
|
78
|
+
console.print("[dim]Telemetry has been disabled. You can re-enable it with: golf telemetry enable[/dim]")
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@app.command()
|
|
82
|
+
def init(
|
|
83
|
+
project_name: str = typer.Argument(..., help="Name of the project to create"),
|
|
84
|
+
output_dir: Path | None = typer.Option(None, "--output-dir", "-o", help="Directory to create the project in"),
|
|
85
|
+
) -> None:
|
|
86
|
+
"""Initialize a new GolfMCP project.
|
|
87
|
+
|
|
88
|
+
Creates a new directory with the project scaffold, including
|
|
89
|
+
examples for tools, resources, and prompts.
|
|
90
|
+
"""
|
|
91
|
+
# Show the Golf logo for project initialization
|
|
92
|
+
create_welcome_banner(__version__, console)
|
|
93
|
+
console.print()
|
|
94
|
+
create_command_header("Initialize Project", f"Creating {project_name}", console)
|
|
95
|
+
|
|
96
|
+
# Import here to avoid circular imports
|
|
97
|
+
from golf.commands.init import initialize_project
|
|
98
|
+
|
|
99
|
+
# Use the current directory if no output directory is specified
|
|
100
|
+
if output_dir is None:
|
|
101
|
+
output_dir = Path.cwd() / project_name
|
|
102
|
+
|
|
103
|
+
# Execute the initialization command (it handles its own tracking)
|
|
104
|
+
initialize_project(project_name=project_name, output_dir=output_dir)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
# Create a build group with subcommands
|
|
108
|
+
build_app = typer.Typer(help="Build a standalone FastMCP application")
|
|
109
|
+
app.add_typer(build_app, name="build")
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@build_app.command("dev")
|
|
113
|
+
def build_dev(
|
|
114
|
+
output_dir: str | None = typer.Option(None, "--output-dir", "-o", help="Directory to output the built project"),
|
|
115
|
+
) -> None:
|
|
116
|
+
"""Build a development version with app environment variables copied.
|
|
117
|
+
|
|
118
|
+
Golf credentials (GOLF_*) are always loaded from .env for build operations.
|
|
119
|
+
All environment variables are copied to the built project for development.
|
|
120
|
+
"""
|
|
121
|
+
# Find project root directory
|
|
122
|
+
project_root, config_path = find_project_root()
|
|
123
|
+
|
|
124
|
+
if not project_root:
|
|
125
|
+
console.print(
|
|
126
|
+
"[bold red]Error: No GolfMCP project found in the current directory or any parent directory.[/bold red]"
|
|
127
|
+
)
|
|
128
|
+
console.print("Run 'golf init <project_name>' to create a new project.")
|
|
129
|
+
track_event(
|
|
130
|
+
"cli_build_failed",
|
|
131
|
+
{
|
|
132
|
+
"success": False,
|
|
133
|
+
"environment": "dev",
|
|
134
|
+
"error_type": "NoProjectFound",
|
|
135
|
+
"error_message": "No GolfMCP project found",
|
|
136
|
+
},
|
|
137
|
+
)
|
|
138
|
+
raise typer.Exit(code=1)
|
|
139
|
+
|
|
140
|
+
# Load settings from the found project
|
|
141
|
+
settings = load_settings(project_root)
|
|
142
|
+
|
|
143
|
+
# Set default output directory if not specified
|
|
144
|
+
output_dir = project_root / "dist" if output_dir is None else Path(output_dir)
|
|
145
|
+
|
|
146
|
+
try:
|
|
147
|
+
# Build the project with environment variables copied
|
|
148
|
+
from golf.commands.build import build_project
|
|
149
|
+
|
|
150
|
+
build_project(project_root, settings, output_dir, build_env="dev", copy_env=True)
|
|
151
|
+
# Track successful build with environment
|
|
152
|
+
track_event("cli_build_success", {"success": True, "environment": "dev"})
|
|
153
|
+
except Exception as e:
|
|
154
|
+
track_detailed_error(
|
|
155
|
+
"cli_build_failed",
|
|
156
|
+
e,
|
|
157
|
+
context="Development build with environment variables",
|
|
158
|
+
operation="build_dev",
|
|
159
|
+
additional_props={"environment": "dev", "copy_env": True},
|
|
160
|
+
)
|
|
161
|
+
raise
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
@build_app.command("prod")
|
|
165
|
+
def build_prod(
|
|
166
|
+
output_dir: str | None = typer.Option(None, "--output-dir", "-o", help="Directory to output the built project"),
|
|
167
|
+
) -> None:
|
|
168
|
+
"""Build a production version for deployment.
|
|
169
|
+
|
|
170
|
+
Environment variables from .env are loaded for build operations.
|
|
171
|
+
App environment variables are NOT copied for security - provide them
|
|
172
|
+
in your deployment environment.
|
|
173
|
+
"""
|
|
174
|
+
# Find project root directory
|
|
175
|
+
project_root, config_path = find_project_root()
|
|
176
|
+
|
|
177
|
+
if not project_root:
|
|
178
|
+
console.print(
|
|
179
|
+
"[bold red]Error: No GolfMCP project found in the current directory or any parent directory.[/bold red]"
|
|
180
|
+
)
|
|
181
|
+
console.print("Run 'golf init <project_name>' to create a new project.")
|
|
182
|
+
track_event(
|
|
183
|
+
"cli_build_failed",
|
|
184
|
+
{
|
|
185
|
+
"success": False,
|
|
186
|
+
"environment": "prod",
|
|
187
|
+
"error_type": "NoProjectFound",
|
|
188
|
+
"error_message": "No GolfMCP project found",
|
|
189
|
+
},
|
|
190
|
+
)
|
|
191
|
+
raise typer.Exit(code=1)
|
|
192
|
+
|
|
193
|
+
# Load settings from the found project
|
|
194
|
+
settings = load_settings(project_root)
|
|
195
|
+
|
|
196
|
+
# Set default output directory if not specified
|
|
197
|
+
output_dir = project_root / "dist" if output_dir is None else Path(output_dir)
|
|
198
|
+
|
|
199
|
+
try:
|
|
200
|
+
# Build the project without copying environment variables
|
|
201
|
+
from golf.commands.build import build_project
|
|
202
|
+
|
|
203
|
+
build_project(project_root, settings, output_dir, build_env="prod", copy_env=False)
|
|
204
|
+
# Track successful build with environment
|
|
205
|
+
track_event("cli_build_success", {"success": True, "environment": "prod"})
|
|
206
|
+
except Exception as e:
|
|
207
|
+
track_detailed_error(
|
|
208
|
+
"cli_build_failed",
|
|
209
|
+
e,
|
|
210
|
+
context="Production build without environment variables",
|
|
211
|
+
operation="build_prod",
|
|
212
|
+
additional_props={"environment": "prod", "copy_env": False},
|
|
213
|
+
)
|
|
214
|
+
raise
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
@app.command()
|
|
218
|
+
def run(
|
|
219
|
+
dist_dir: str | None = typer.Option(None, "--dist-dir", "-d", help="Directory containing the built server"),
|
|
220
|
+
host: str | None = typer.Option(None, "--host", "-h", help="Host to bind to (overrides settings)"),
|
|
221
|
+
port: int | None = typer.Option(None, "--port", "-p", help="Port to bind to (overrides settings)"),
|
|
222
|
+
build_first: bool = typer.Option(True, "--build/--no-build", help="Build the project before running"),
|
|
223
|
+
) -> None:
|
|
224
|
+
"""Run the built FastMCP server.
|
|
225
|
+
|
|
226
|
+
This command runs the built server from the dist directory.
|
|
227
|
+
By default, it will build the project first if needed.
|
|
228
|
+
"""
|
|
229
|
+
# Find project root directory
|
|
230
|
+
project_root, config_path = find_project_root()
|
|
231
|
+
|
|
232
|
+
if not project_root:
|
|
233
|
+
console.print(
|
|
234
|
+
"[bold red]Error: No GolfMCP project found in the current directory or any parent directory.[/bold red]"
|
|
235
|
+
)
|
|
236
|
+
console.print("Run 'golf init <project_name>' to create a new project.")
|
|
237
|
+
track_event(
|
|
238
|
+
"cli_run_failed",
|
|
239
|
+
{
|
|
240
|
+
"success": False,
|
|
241
|
+
"error_type": "NoProjectFound",
|
|
242
|
+
"error_message": "No GolfMCP project found",
|
|
243
|
+
},
|
|
244
|
+
)
|
|
245
|
+
raise typer.Exit(code=1)
|
|
246
|
+
|
|
247
|
+
# Load settings from the found project
|
|
248
|
+
settings = load_settings(project_root)
|
|
249
|
+
|
|
250
|
+
# Set default dist directory if not specified
|
|
251
|
+
dist_dir = project_root / "dist" if dist_dir is None else Path(dist_dir)
|
|
252
|
+
|
|
253
|
+
# Check if dist directory exists
|
|
254
|
+
if not dist_dir.exists():
|
|
255
|
+
if build_first:
|
|
256
|
+
console.print(f"[yellow]Dist directory {dist_dir} not found. Building first...[/yellow]")
|
|
257
|
+
try:
|
|
258
|
+
# Build the project
|
|
259
|
+
from golf.commands.build import build_project
|
|
260
|
+
|
|
261
|
+
build_project(project_root, settings, dist_dir)
|
|
262
|
+
except Exception as e:
|
|
263
|
+
console.print(f"[bold red]Error building project:[/bold red] {str(e)}")
|
|
264
|
+
track_detailed_error(
|
|
265
|
+
"cli_run_failed",
|
|
266
|
+
e,
|
|
267
|
+
context="Auto-build before running server",
|
|
268
|
+
operation="auto_build_before_run",
|
|
269
|
+
additional_props={"auto_build": True},
|
|
270
|
+
)
|
|
271
|
+
raise
|
|
272
|
+
else:
|
|
273
|
+
console.print(f"[bold red]Error: Dist directory {dist_dir} not found.[/bold red]")
|
|
274
|
+
console.print("Run 'golf build' first or use --build to build automatically.")
|
|
275
|
+
track_event(
|
|
276
|
+
"cli_run_failed",
|
|
277
|
+
{
|
|
278
|
+
"success": False,
|
|
279
|
+
"error_type": "DistNotFound",
|
|
280
|
+
"error_message": "Dist directory not found",
|
|
281
|
+
},
|
|
282
|
+
)
|
|
283
|
+
raise typer.Exit(code=1)
|
|
284
|
+
|
|
285
|
+
try:
|
|
286
|
+
# Import and run the server
|
|
287
|
+
from golf.commands.run import run_server
|
|
288
|
+
|
|
289
|
+
return_code = run_server(
|
|
290
|
+
project_path=project_root,
|
|
291
|
+
settings=settings,
|
|
292
|
+
dist_dir=dist_dir,
|
|
293
|
+
host=host,
|
|
294
|
+
port=port,
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
# Track based on return code with better categorization
|
|
298
|
+
if return_code == 0:
|
|
299
|
+
track_event("cli_run_success", {"success": True})
|
|
300
|
+
elif return_code in [130, 143, 137, 2]:
|
|
301
|
+
# Intentional shutdowns (not errors):
|
|
302
|
+
# 130: Ctrl+C (SIGINT)
|
|
303
|
+
# 143: SIGTERM (graceful shutdown, e.g., Kubernetes, Docker)
|
|
304
|
+
# 137: SIGKILL (forced shutdown)
|
|
305
|
+
# 2: General interrupt/graceful shutdown
|
|
306
|
+
shutdown_type = {
|
|
307
|
+
130: "UserInterrupt",
|
|
308
|
+
143: "GracefulShutdown",
|
|
309
|
+
137: "ForcedShutdown",
|
|
310
|
+
2: "Interrupt",
|
|
311
|
+
}.get(return_code, "GracefulShutdown")
|
|
312
|
+
|
|
313
|
+
track_event(
|
|
314
|
+
"cli_run_shutdown",
|
|
315
|
+
{
|
|
316
|
+
"success": True, # Not an error
|
|
317
|
+
"shutdown_type": shutdown_type,
|
|
318
|
+
"exit_code": return_code,
|
|
319
|
+
},
|
|
320
|
+
)
|
|
321
|
+
else:
|
|
322
|
+
# Actual errors (unexpected exit codes)
|
|
323
|
+
track_event(
|
|
324
|
+
"cli_run_failed",
|
|
325
|
+
{
|
|
326
|
+
"success": False,
|
|
327
|
+
"error_type": "UnexpectedExit",
|
|
328
|
+
"error_message": (f"Server process exited unexpectedly with code {return_code}"),
|
|
329
|
+
"exit_code": return_code,
|
|
330
|
+
"operation": "server_process_execution",
|
|
331
|
+
"context": "Server process terminated with unexpected exit code",
|
|
332
|
+
},
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
# Exit with the same code as the server
|
|
336
|
+
if return_code != 0:
|
|
337
|
+
raise typer.Exit(code=return_code)
|
|
338
|
+
except Exception as e:
|
|
339
|
+
track_detailed_error(
|
|
340
|
+
"cli_run_failed",
|
|
341
|
+
e,
|
|
342
|
+
context="Server execution or startup failure",
|
|
343
|
+
operation="run_server_execution",
|
|
344
|
+
additional_props={"has_dist_dir": dist_dir.exists() if dist_dir else False},
|
|
345
|
+
)
|
|
346
|
+
raise
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
# Add telemetry command group
|
|
350
|
+
@app.command()
|
|
351
|
+
def telemetry(
|
|
352
|
+
action: str = typer.Argument(..., help="Action to perform: 'enable' or 'disable'"),
|
|
353
|
+
) -> None:
|
|
354
|
+
"""Manage telemetry settings."""
|
|
355
|
+
if action.lower() == "enable":
|
|
356
|
+
set_telemetry_enabled(True, persist=True)
|
|
357
|
+
console.print("[green]✓[/green] Telemetry enabled. Thank you for helping improve Golf!")
|
|
358
|
+
elif action.lower() == "disable":
|
|
359
|
+
set_telemetry_enabled(False, persist=True)
|
|
360
|
+
console.print("[yellow]Telemetry disabled.[/yellow] You can re-enable it anytime with: golf telemetry enable")
|
|
361
|
+
else:
|
|
362
|
+
console.print(f"[red]Unknown action '{action}'. Use 'enable' or 'disable'.[/red]")
|
|
363
|
+
raise typer.Exit(code=1)
|
|
364
|
+
|
|
365
|
+
|
|
366
|
+
if __name__ == "__main__":
|
|
367
|
+
# Show welcome banner when run directly
|
|
368
|
+
create_welcome_banner(__version__, console)
|
|
369
|
+
|
|
370
|
+
# Add telemetry notice if enabled
|
|
371
|
+
if is_telemetry_enabled():
|
|
372
|
+
console.print(
|
|
373
|
+
"[dim]📊 Anonymous usage data is collected to improve Golf. Disable with: golf telemetry disable[/dim]\n"
|
|
374
|
+
)
|
|
375
|
+
|
|
376
|
+
# Run the CLI app
|
|
377
|
+
app()
|
golf/commands/build.py
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""Build command for GolfMCP.
|
|
2
|
+
|
|
3
|
+
This module implements the `golf build` command which generates a standalone
|
|
4
|
+
FastMCP application from a GolfMCP project.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import argparse
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
from rich.console import Console
|
|
11
|
+
|
|
12
|
+
from golf.core.builder import build_project as core_build_project
|
|
13
|
+
from golf.core.config import Settings, load_settings
|
|
14
|
+
|
|
15
|
+
console = Console()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def build_project(
|
|
19
|
+
project_path: Path,
|
|
20
|
+
settings: Settings,
|
|
21
|
+
output_dir: Path,
|
|
22
|
+
build_env: str = "prod",
|
|
23
|
+
copy_env: bool = False,
|
|
24
|
+
) -> None:
|
|
25
|
+
"""Build a standalone FastMCP application from a GolfMCP project.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
project_path: Path to the project root
|
|
29
|
+
settings: Project settings
|
|
30
|
+
output_dir: Directory to output the built project
|
|
31
|
+
build_env: Build environment ('dev' or 'prod')
|
|
32
|
+
copy_env: Whether to copy environment variables to the built app
|
|
33
|
+
"""
|
|
34
|
+
# Call the centralized build function from core.builder
|
|
35
|
+
core_build_project(project_path, settings, output_dir, build_env=build_env, copy_env=copy_env)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
# Add a main section to run the build_project function when this module is
|
|
39
|
+
# executed directly
|
|
40
|
+
if __name__ == "__main__":
|
|
41
|
+
parser = argparse.ArgumentParser(description="Build a standalone FastMCP application")
|
|
42
|
+
parser.add_argument(
|
|
43
|
+
"--project-path",
|
|
44
|
+
"-p",
|
|
45
|
+
type=Path,
|
|
46
|
+
default=Path.cwd(),
|
|
47
|
+
help="Path to the project root (default: current directory)",
|
|
48
|
+
)
|
|
49
|
+
parser.add_argument(
|
|
50
|
+
"--output-dir",
|
|
51
|
+
"-o",
|
|
52
|
+
type=Path,
|
|
53
|
+
default=Path.cwd() / "dist",
|
|
54
|
+
help="Directory to output the built project (default: ./dist)",
|
|
55
|
+
)
|
|
56
|
+
parser.add_argument(
|
|
57
|
+
"--build-env",
|
|
58
|
+
type=str,
|
|
59
|
+
default="prod",
|
|
60
|
+
choices=["dev", "prod"],
|
|
61
|
+
help="Build environment to use (default: prod)",
|
|
62
|
+
)
|
|
63
|
+
parser.add_argument(
|
|
64
|
+
"--copy-env",
|
|
65
|
+
action="store_true",
|
|
66
|
+
help="Copy environment variables to the built application",
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
args = parser.parse_args()
|
|
70
|
+
|
|
71
|
+
# Load settings from the project path
|
|
72
|
+
settings = load_settings(args.project_path)
|
|
73
|
+
|
|
74
|
+
# Execute the build
|
|
75
|
+
build_project(
|
|
76
|
+
args.project_path,
|
|
77
|
+
settings,
|
|
78
|
+
args.output_dir,
|
|
79
|
+
build_env=args.build_env,
|
|
80
|
+
copy_env=args.copy_env,
|
|
81
|
+
)
|