|
1 | 1 | import argparse |
2 | 2 |
|
| 3 | +import fenn.cli.auth as auth |
3 | 4 | import fenn.cli.dashboard as dashboard |
4 | 5 | import fenn.cli.list as list |
5 | 6 | import fenn.cli.pull as pull |
| 7 | +import fenn.cli.run as run |
6 | 8 |
|
7 | 9 |
|
8 | 10 | def build_parser() -> argparse.ArgumentParser: |
@@ -61,6 +63,92 @@ def build_parser() -> argparse.ArgumentParser: |
61 | 63 | p_dash.add_argument("--debug", action="store_true", help="Run Flask in debug mode") |
62 | 64 | p_dash.set_defaults(func=dashboard.execute) |
63 | 65 |
|
| 66 | + # ========= RUN ========= |
| 67 | + p_run = subparsers.add_parser( |
| 68 | + "run", |
| 69 | + help="Run a Fenn project locally or on a remote host", |
| 70 | + ) |
| 71 | + p_run.add_argument( |
| 72 | + "script", |
| 73 | + nargs="?", |
| 74 | + default=None, |
| 75 | + help="Path to the entrypoint script (default: main.py)", |
| 76 | + ) |
| 77 | + p_run.add_argument( |
| 78 | + "--host", |
| 79 | + default=None, |
| 80 | + help="Remote host URL (e.g. https://api.fenn.dev). If omitted, runs locally.", |
| 81 | + ) |
| 82 | + p_run.add_argument( |
| 83 | + "--api-key", |
| 84 | + default=None, |
| 85 | + help="API key (overrides env, credentials file, and .env)", |
| 86 | + ) |
| 87 | + p_run.add_argument( |
| 88 | + "--profile", |
| 89 | + default=None, |
| 90 | + help="Credentials profile name (default: 'default' or $FENN_PROFILE)", |
| 91 | + ) |
| 92 | + p_run.add_argument( |
| 93 | + "--max-runtime", |
| 94 | + type=int, |
| 95 | + default=3600, |
| 96 | + help="Maximum allowed wall-time in seconds (server enforces; default: 3600)", |
| 97 | + ) |
| 98 | + p_run.add_argument( |
| 99 | + "--detach", |
| 100 | + action="store_true", |
| 101 | + help="Submit the job and exit without streaming logs", |
| 102 | + ) |
| 103 | + p_run.add_argument( |
| 104 | + "--no-download", |
| 105 | + action="store_true", |
| 106 | + help="Do not download artifacts on completion", |
| 107 | + ) |
| 108 | + p_run.add_argument( |
| 109 | + "--include", |
| 110 | + action="append", |
| 111 | + metavar="PATH", |
| 112 | + help="Extra path (relative to CWD) to include in the upload tarball", |
| 113 | + ) |
| 114 | + p_run.add_argument( |
| 115 | + "--exclude", |
| 116 | + action="append", |
| 117 | + metavar="PATTERN", |
| 118 | + help="Extra shell-glob pattern to exclude from the upload tarball", |
| 119 | + ) |
| 120 | + p_run.set_defaults(func=run.execute) |
| 121 | + |
| 122 | + # ========= AUTH ========= |
| 123 | + p_auth = subparsers.add_parser( |
| 124 | + "auth", help="Manage credentials for the Fenn remote service" |
| 125 | + ) |
| 126 | + auth_subparsers = p_auth.add_subparsers(dest="auth_command", required=True) |
| 127 | + |
| 128 | + p_login = auth_subparsers.add_parser( |
| 129 | + "login", help="Save an API key for a profile" |
| 130 | + ) |
| 131 | + p_login.add_argument("--profile", default=None, help="Profile name (default: 'default')") |
| 132 | + p_login.add_argument("--host", default=None, help="Default host for this profile") |
| 133 | + p_login.add_argument( |
| 134 | + "--api-key", |
| 135 | + default=None, |
| 136 | + help="API key (if omitted, will prompt or read from stdin)", |
| 137 | + ) |
| 138 | + p_login.set_defaults(func=auth.execute) |
| 139 | + |
| 140 | + p_status = auth_subparsers.add_parser( |
| 141 | + "status", help="Show the currently configured profile and credit balance" |
| 142 | + ) |
| 143 | + p_status.add_argument("--profile", default=None, help="Profile name (default: 'default')") |
| 144 | + p_status.set_defaults(func=auth.execute) |
| 145 | + |
| 146 | + p_logout = auth_subparsers.add_parser( |
| 147 | + "logout", help="Remove a profile from the credentials file" |
| 148 | + ) |
| 149 | + p_logout.add_argument("--profile", default=None, help="Profile name (default: 'default')") |
| 150 | + p_logout.set_defaults(func=auth.execute) |
| 151 | + |
64 | 152 | return parser |
65 | 153 |
|
66 | 154 |
|
|
0 commit comments