Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions docs/Flash_Apps_and_Environments.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,14 @@ Flash apps are the top-level packaging unit for Flash projects. Each app tracks
- `FlashApp` instances call `_hydrate()` to fetch or create the remote app ID before doing any work.
- CLI helpers (`flash app ...`, `flash deploy ...`) call `discover_flash_project()` when `--app-name` is omitted, then hydrate via `FlashApp.from_name` or eager constructors.
2. **Environment Creation**
- `flash deploy new <env>` calls `FlashApp.create_environment_and_app` to ensure the parent app exists and to create the environment in a single async transaction.
- `flash env create <env>` calls `FlashApp.create_environment_and_app` to ensure the parent app exists and to create the environment in a single async transaction.
- Once created, the CLI prints both a confirmation panel and a table summarizing the environment metadata so operators can confirm IDs/states.
3. **Build Upload & Resource Provisioning**
- `flash build` generates `.flash/artifact.tar.gz` artifacts containing source code and flash_manifest.json. `flash deploy send <env>` uploads the archive and provisions all resources upfront before environment activation, extracting the manifest on each resource during boot.
4. **Inspection & Operations**
- `flash app list/get` surface app-level metadata: environment counts, build history, IDs.
- `flash deploy list/info` zoom into environment state, showing associated endpoints and volumes, while `flash deploy delete` undeploys associated resources before deleting the environment (aborting on failures) with confirmation prompts.
- `flash env list/get` zoom into environment state, showing associated endpoints and volumes, while `flash env delete` undeploys associated resources before deleting the environment (aborting on failures) with confirmation prompts.

## Operational Notes
- Flash app CLI entrypoint wraps async helpers with `asyncio.run`, so tests patch that boundary and the shared Rich `console` to keep assertions deterministic.
- Environment deletion requires confirmation because the API call is irreversible. The CLI renders a warning `Panel` with the app/env IDs before prompting.

28 changes: 14 additions & 14 deletions docs/Flash_Deploy_Guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ graph TB

### Key Concepts

**Mothership**: The orchestration endpoint responsible for deployment, resource provisioning, and manifest distribution. Created via `flash deploy new <env_name>`.
**Mothership**: The orchestration endpoint responsible for deployment, resource provisioning, and manifest distribution. Created via `flash env create <env_name>`.

**Child Endpoints**: Worker endpoints that execute `@remote` functions. One per resource config (e.g., `gpu_config`, `cpu_config`).

Expand All @@ -69,19 +69,19 @@ graph TB

## CLI Commands Reference

### flash deploy new
### flash env create

Create a new deployment environment (mothership).

```bash
flash deploy new <env_name> [--app-name <app_name>]
flash env create <env_name> [--app <app_name>]
```

**Arguments:**
- `env_name`: Name for the deployment environment

**Options:**
- `--app-name <app_name>`: Flash app name (auto-detected if not provided)
- `--app <app_name>`: Flash app name (auto-detected if not provided)

**What it does:**
1. Creates a FlashApp in RunPod (if first environment for the app)
Expand All @@ -90,7 +90,7 @@ flash deploy new <env_name> [--app-name <app_name>]

**Example:**
```bash
flash deploy new production
flash env create production
# Output: Environment 'production' created successfully
# Environment ID: flash-prod-abc123
# Next: flash deploy send production
Expand Down Expand Up @@ -133,16 +133,16 @@ flash deploy send production

---

### flash deploy list
### flash env list

List all deployment environments for an app.

```bash
flash deploy list [--app-name <app_name>]
flash env list [--app <app_name>]
```

**Options:**
- `--app-name <app_name>`: Flash app name (auto-detected if not provided)
- `--app <app_name>`: Flash app name (auto-detected if not provided)

**Output:** Table showing:
- Environment name
Expand All @@ -154,19 +154,19 @@ flash deploy list [--app-name <app_name>]

---

### flash deploy info
### flash env get

Show detailed information about a deployment environment.

```bash
flash deploy info <env_name> [--app-name <app_name>]
flash env get <env_name> [--app <app_name>]
```

**Arguments:**
- `env_name`: Name of the deployment environment

**Options:**
- `--app-name <app_name>`: Flash app name (auto-detected if not provided)
- `--app <app_name>`: Flash app name (auto-detected if not provided)

**Output:** Displays:
- Environment status and ID
Expand All @@ -178,19 +178,19 @@ flash deploy info <env_name> [--app-name <app_name>]

---

### flash deploy delete
### flash env delete

Delete a deployment environment.

```bash
flash deploy delete <env_name> [--app-name <app_name>]
flash env delete <env_name> [--app <app_name>]
```

**Arguments:**
- `env_name`: Name of the deployment environment

**Options:**
- `--app-name <app_name>`: Flash app name (auto-detected if not provided)
- `--app <app_name>`: Flash app name (auto-detected if not provided)

**Safety:**
- Requires confirmation (twice for safety)
Expand Down
6 changes: 3 additions & 3 deletions src/runpod_flash/cli/commands/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,17 +157,17 @@ async def _create_environment(app_name: str, env_name: str):
console.print(table)


def info_command(
def get_command(
env_name: str = typer.Argument(..., help="Name of the deployment environment"),
app_name: str = typer.Option(None, "--app", "-a", help="Flash app name"),
):
"""Show detailed information about a deployment environment."""
if not app_name:
_, app_name = discover_flash_project()
asyncio.run(_info_environment(app_name, env_name))
asyncio.run(_get_environment(app_name, env_name))


async def _info_environment(app_name: str, env_name: str):
async def _get_environment(app_name: str, env_name: str):
app = await FlashApp.from_name(app_name)
env = await app.get_environment_by_name(env_name)

Expand Down
2 changes: 1 addition & 1 deletion src/runpod_flash/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def get_version() -> str:

env_app.command("list")(env.list_command)
env_app.command("create")(env.create_command)
env_app.command("info")(env.info_command)
env_app.command("get")(env.get_command)
env_app.command("delete")(env.delete_command)

app.add_typer(env_app, name="env")
Expand Down
10 changes: 5 additions & 5 deletions tests/unit/cli/test_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,9 @@ def test_create_environment_success(
assert isinstance(table, Table)


class TestEnvInfo:
class TestEnvGet:
@patch("runpod_flash.cli.commands.env.FlashApp.from_name", new_callable=AsyncMock)
def test_info_includes_children(
def test_get_includes_children(
self, mock_from_name, runner, mock_asyncio_run_coro, patched_console
):
flash_app = MagicMock()
Expand All @@ -155,7 +155,7 @@ def test_info_includes_children(
"runpod_flash.cli.commands.env.asyncio.run",
side_effect=mock_asyncio_run_coro,
):
result = runner.invoke(app, ["env", "info", "dev", "--app", "demo"])
result = runner.invoke(app, ["env", "get", "dev", "--app", "demo"])

assert result.exit_code == 0
panel = patched_console.print.call_args_list[0].args[0]
Expand All @@ -166,7 +166,7 @@ def test_info_includes_children(
assert isinstance(network_table, Table)

@patch("runpod_flash.cli.commands.env.FlashApp.from_name", new_callable=AsyncMock)
def test_info_without_children(
def test_get_without_children(
self, mock_from_name, runner, mock_asyncio_run_coro, patched_console
):
flash_app = MagicMock()
Expand All @@ -187,7 +187,7 @@ def test_info_without_children(
"runpod_flash.cli.commands.env.asyncio.run",
side_effect=mock_asyncio_run_coro,
):
result = runner.invoke(app, ["env", "info", "dev", "--app", "demo"])
result = runner.invoke(app, ["env", "get", "dev", "--app", "demo"])

assert result.exit_code == 0
# Only the panel should be printed when there are no child resources
Expand Down
Loading