flowstash-cli 0.4.2__tar.gz → 0.5.1__tar.gz
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.
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/PKG-INFO +2 -2
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/pyproject.toml +2 -2
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/commands/deploy.py +4 -5
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/commands/project.py +4 -3
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/core/api_client.py +2 -2
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/main.py +7 -7
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/AGENTS.md +9 -7
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_config/shared/clients/demoClient.yaml +2 -1
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/__init__.py +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/commands/__init__.py +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/commands/apikey.py +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/commands/auth.py +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/commands/build.py +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/commands/client.py +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/commands/run.py +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/commands/webhook.py +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/core/__init__.py +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/core/auth_server.py +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/core/builder.py +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/core/config.py +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/core/docker_utils.py +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/core/patcher.py +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/README.md +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_.dockerignore +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_.flowstash +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_api_main.py +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_config/[env]/(backend-asyncio)/backend.yaml +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_config/[env]/(backend-dramatiq)/backend.yaml +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_config/[env]/(backend-managed)/backend.yaml +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_config/[env]/(observability-logfile)/observability.yaml +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_config/[env]/(observability-managed)/observability.yaml +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_config/shared/backend.yaml +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_config/shared/clients.yaml +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_deployment/[env]/(backend-asyncio)/docker-compose.yaml +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_deployment/[env]/(backend-dramatiq)/docker-compose.yaml +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_deployment/shared/api.Dockerfile +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_deployment/shared/worker.Dockerfile +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_pyproject.toml +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_src/_api/__init__.py +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_src/_api/_routes/webhooks.py +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_src/_shared/__init__.py +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_src/_shared/clients/client.py +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_src/_shared/models/models.py +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_src/_shared/tasks/sharedTasks.py +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_src/_worker/__init__.py +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_src/_worker/tasks/tasks.py +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_worker_main.py +0 -0
- {flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/ui/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: flowstash-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.1
|
|
4
4
|
Summary: CLI for the flowstash Managed Platform
|
|
5
5
|
Author: juraj.bezdek@gmail.com
|
|
6
6
|
Author-email: juraj.bezdek@gmail.com
|
|
@@ -9,7 +9,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
9
9
|
Classifier: Programming Language :: Python :: 3.11
|
|
10
10
|
Classifier: Programming Language :: Python :: 3.12
|
|
11
11
|
Classifier: Programming Language :: Python :: 3.13
|
|
12
|
-
Requires-Dist: flowstash-runtime (>=0.
|
|
12
|
+
Requires-Dist: flowstash-runtime (>=0.5.1,<0.6.0)
|
|
13
13
|
Requires-Dist: httpx (>=0.27.0)
|
|
14
14
|
Requires-Dist: keyring (>=25.0.0)
|
|
15
15
|
Requires-Dist: libcst (>=1.1.0)
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "flowstash-cli"
|
|
3
|
-
version = "0.
|
|
3
|
+
version = "0.5.1"
|
|
4
4
|
description = "CLI for the flowstash Managed Platform"
|
|
5
5
|
authors = [{name = "juraj.bezdek@gmail.com", email = "juraj.bezdek@gmail.com"}]
|
|
6
6
|
requires-python = ">=3.11"
|
|
7
7
|
dependencies = [
|
|
8
|
-
"flowstash-runtime>=0.
|
|
8
|
+
"flowstash-runtime>=0.5.1,<0.6.0",
|
|
9
9
|
"typer[all]>=0.12.0",
|
|
10
10
|
"httpx>=0.27.0",
|
|
11
11
|
"pyyaml>=6.0.1",
|
|
@@ -14,6 +14,7 @@ console = Console()
|
|
|
14
14
|
# Status labels shown to the user while polling
|
|
15
15
|
_STATUS_LABELS = {
|
|
16
16
|
"QUEUED": "Queued, waiting for deployment to start...",
|
|
17
|
+
"VALIDATING": "Validating container images...",
|
|
17
18
|
"DEPLOYING": "Deploying services...",
|
|
18
19
|
"HEALTH_CHECK": "Health-checking API and Worker...",
|
|
19
20
|
"SYNCING_SCHEDULES": "Fetching and syncing scheduled tasks...",
|
|
@@ -93,9 +94,7 @@ def deploy(
|
|
|
93
94
|
artifact: Optional[str] = typer.Option(
|
|
94
95
|
None, "--artifact", "-a", help="Artifact ID to deploy"
|
|
95
96
|
),
|
|
96
|
-
|
|
97
|
-
False, "--non-interactive", help="Do not ask for confirmation"
|
|
98
|
-
),
|
|
97
|
+
yes: bool = typer.Option(False, "--yes", "-y", help="Do not ask for confirmation"),
|
|
99
98
|
):
|
|
100
99
|
"""Deploy an artifact to the managed platform for a specified environment."""
|
|
101
100
|
project_config = load_project_config()
|
|
@@ -106,7 +105,7 @@ def deploy(
|
|
|
106
105
|
raise typer.Exit(code=1)
|
|
107
106
|
|
|
108
107
|
# Ask for confirmation unless non-interactive is provided
|
|
109
|
-
if not
|
|
108
|
+
if not yes:
|
|
110
109
|
from rich.prompt import Confirm
|
|
111
110
|
|
|
112
111
|
if not Confirm.ask(f"Are you sure you want to deploy to '{env}'?"):
|
|
@@ -131,7 +130,7 @@ def deploy(
|
|
|
131
130
|
|
|
132
131
|
project_id = project_config.project_id
|
|
133
132
|
if not project_id:
|
|
134
|
-
if not
|
|
133
|
+
if not yes:
|
|
135
134
|
from rich.prompt import Confirm
|
|
136
135
|
|
|
137
136
|
if Confirm.ask(
|
|
@@ -556,7 +556,8 @@ def env_add(
|
|
|
556
556
|
|
|
557
557
|
@app.command("delete")
|
|
558
558
|
def env_delete(
|
|
559
|
-
env_name: str = typer.Argument(..., help="Name of the environment to delete")
|
|
559
|
+
env_name: str = typer.Argument(..., help="Name of the environment to delete"),
|
|
560
|
+
yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation prompt"),
|
|
560
561
|
):
|
|
561
562
|
"""
|
|
562
563
|
[bold red]Delete an environment[/bold red] from your project.
|
|
@@ -588,7 +589,7 @@ def env_delete(
|
|
|
588
589
|
|
|
589
590
|
from rich.prompt import Confirm
|
|
590
591
|
|
|
591
|
-
if not Confirm.ask(
|
|
592
|
+
if not yes and not Confirm.ask(
|
|
592
593
|
f"Are you sure you want to delete environment [bold red]{env_name}[/bold red]?"
|
|
593
594
|
):
|
|
594
595
|
console.print("Cancelled.")
|
|
@@ -603,7 +604,7 @@ def env_delete(
|
|
|
603
604
|
# Optionally delete the folder
|
|
604
605
|
env_folder = root / env_name
|
|
605
606
|
if env_folder.exists() and env_folder.is_dir():
|
|
606
|
-
if Confirm.ask(
|
|
607
|
+
if yes or Confirm.ask(
|
|
607
608
|
f"Do you also want to delete the configuration folder [bold]{env_name}/[/bold]?"
|
|
608
609
|
):
|
|
609
610
|
import shutil
|
|
@@ -23,8 +23,8 @@ class APIClient:
|
|
|
23
23
|
response.raise_for_status()
|
|
24
24
|
return response.json()
|
|
25
25
|
|
|
26
|
-
async def post(self, path: str, json: Optional[Dict[str, Any]] = None):
|
|
27
|
-
async with httpx.AsyncClient(timeout=
|
|
26
|
+
async def post(self, path: str, json: Optional[Dict[str, Any]] = None, timeout: float = 30.0):
|
|
27
|
+
async with httpx.AsyncClient(timeout=timeout) as client:
|
|
28
28
|
response = await client.post(
|
|
29
29
|
f"{self.base_url}{path}", json=json, headers=self._get_headers()
|
|
30
30
|
)
|
|
@@ -198,6 +198,7 @@ def run(
|
|
|
198
198
|
logs: bool = typer.Option(
|
|
199
199
|
False, "--logs", help="Follow logs (useful with --detach)"
|
|
200
200
|
),
|
|
201
|
+
yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation prompts"),
|
|
201
202
|
):
|
|
202
203
|
"""
|
|
203
204
|
[bold magenta]Run[/bold magenta] the project locally using Docker Compose.
|
|
@@ -219,7 +220,7 @@ def run(
|
|
|
219
220
|
env_mode = next((e for e in project_config.environments if e.name == env), None)
|
|
220
221
|
if not env_mode:
|
|
221
222
|
if env == "dev":
|
|
222
|
-
if Confirm.ask(
|
|
223
|
+
if yes or Confirm.ask(
|
|
223
224
|
f"Environment '{env}' not found. Would you like to set it up now?"
|
|
224
225
|
):
|
|
225
226
|
project_cmds.add_environment(project_config, env_name=env)
|
|
@@ -240,6 +241,7 @@ def build(
|
|
|
240
241
|
ctx: typer.Context,
|
|
241
242
|
env: str = typer.Argument("dev", help="Environment to build (default: local)"),
|
|
242
243
|
tag: str = typer.Option("latest", "--tag", "-t", help="Tag for the image"),
|
|
244
|
+
yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation prompts"),
|
|
243
245
|
):
|
|
244
246
|
"""
|
|
245
247
|
[bold yellow]Build[/bold yellow] project artifacts/images.
|
|
@@ -261,7 +263,7 @@ def build(
|
|
|
261
263
|
env_mode = next((e for e in project_config.environments if e.name == env), None)
|
|
262
264
|
if not env_mode:
|
|
263
265
|
if env == "dev":
|
|
264
|
-
if Confirm.ask(
|
|
266
|
+
if yes or Confirm.ask(
|
|
265
267
|
f"Environment '{env}' not found. Would you like to set it up now?"
|
|
266
268
|
):
|
|
267
269
|
project_cmds.add_environment(project_config, env_name=env)
|
|
@@ -284,9 +286,7 @@ def deploy(
|
|
|
284
286
|
artifact: Optional[str] = typer.Option(
|
|
285
287
|
None, "--artifact", "-a", help="Artifact ID to deploy"
|
|
286
288
|
),
|
|
287
|
-
|
|
288
|
-
False, "--non-interactive", help="Do not ask for confirmation"
|
|
289
|
-
),
|
|
289
|
+
yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation prompts"),
|
|
290
290
|
):
|
|
291
291
|
"""
|
|
292
292
|
[bold cyan]Deploy[/bold cyan] your project to the flowstash Managed Platform.
|
|
@@ -316,7 +316,7 @@ def deploy(
|
|
|
316
316
|
|
|
317
317
|
if not env_mode:
|
|
318
318
|
if env == "prod":
|
|
319
|
-
if
|
|
319
|
+
if yes or Confirm.ask(
|
|
320
320
|
f"Environment '{env}' not found. Would you like to set it up now?"
|
|
321
321
|
):
|
|
322
322
|
# We need to pass the actual project_config object to add_environment
|
|
@@ -347,7 +347,7 @@ def deploy(
|
|
|
347
347
|
)
|
|
348
348
|
raise typer.Exit(code=1)
|
|
349
349
|
|
|
350
|
-
deploy_cmds.deploy(env=env, artifact=artifact,
|
|
350
|
+
deploy_cmds.deploy(env=env, artifact=artifact, yes=yes)
|
|
351
351
|
|
|
352
352
|
|
|
353
353
|
@app.command()
|
|
@@ -233,15 +233,13 @@ class DemoClient(HttpClient):
|
|
|
233
233
|
async def get_user(self, user_id: int) -> dict:
|
|
234
234
|
response = await self.request("GET", f"/users/{user_id}")
|
|
235
235
|
return response.json()
|
|
236
|
+
```
|
|
236
237
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
238
|
+
You can then resolve this custom client by name:
|
|
239
|
+
`demo = get_client("DemoClient")`
|
|
240
|
+
or
|
|
241
|
+
`DemoClient.get_client()`
|
|
241
242
|
|
|
242
|
-
# You can then resolve this custom client by name:
|
|
243
|
-
# demo = get_client("DemoClient")
|
|
244
|
-
```
|
|
245
243
|
|
|
246
244
|
## Logging
|
|
247
245
|
|
|
@@ -367,3 +365,7 @@ flowstash uses a tiered configuration system that allows for seamless transition
|
|
|
367
365
|
- **`api_main.py`**: The entry point for the web server. It sets up the FastAPI application and automatically imports modules from `src/api` to register routes.
|
|
368
366
|
- **`worker_main.py`**: The entry point for the background process. It connects to the task backend (like Redis) and automatically imports modules from `src/worker` to register task signatures.
|
|
369
367
|
|
|
368
|
+
### Imports
|
|
369
|
+
Always import directly from the module level (e.g., api, worker, shared), assuming src is the root of your $PYTHONPATH.
|
|
370
|
+
This mirrors the Docker environment structure, ensuring cleaner code and consistency across environments. When writing tests or standalone scripts, you must either manually add src to your PYTHONPATH or configure poetry to install src as the package source.
|
|
371
|
+
Avoid relative imports
|
|
@@ -10,7 +10,8 @@ auth:
|
|
|
10
10
|
token_url: "https://auth.example.com/token"
|
|
11
11
|
refresh_token: null
|
|
12
12
|
scopes: []
|
|
13
|
-
|
|
13
|
+
# clientAuthMethod: client_secret_basic (default) # Supported values: client_secret_basic, client_secret_post
|
|
14
|
+
# extra_params: {}
|
|
14
15
|
|
|
15
16
|
# Authentication Alternatives
|
|
16
17
|
# ------------------------------------------s
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_config/shared/backend.yaml
RENAMED
|
File without changes
|
{flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_config/shared/clients.yaml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_src/_api/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_src/_shared/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_src/_worker/__init__.py
RENAMED
|
File without changes
|
{flowstash_cli-0.4.2 → flowstash_cli-0.5.1}/src/flowstash/cli/templates/_src/_worker/tasks/tasks.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|