From 43a8b9ee87fc4b2a72d0d2ac03ce77285380af2f Mon Sep 17 00:00:00 2001 From: emberb170d Date: Thu, 6 Aug 2026 08:48:25 -0400 Subject: [PATCH 1/6] chore: add .python-version files to templates missing them (fixes #153) --- templates/celery-worker/.python-version | 1 + templates/cli-starter/.python-version | 1 + templates/django-api/.python-version | 1 + templates/fastapi-starter/.python-version | 1 + templates/mlops-sklearn-starter/.python-version | 1 + 5 files changed, 5 insertions(+) create mode 100644 templates/celery-worker/.python-version create mode 100644 templates/cli-starter/.python-version create mode 100644 templates/django-api/.python-version create mode 100644 templates/fastapi-starter/.python-version create mode 100644 templates/mlops-sklearn-starter/.python-version diff --git a/templates/celery-worker/.python-version b/templates/celery-worker/.python-version new file mode 100644 index 0000000..e4fba21 --- /dev/null +++ b/templates/celery-worker/.python-version @@ -0,0 +1 @@ +3.12 diff --git a/templates/cli-starter/.python-version b/templates/cli-starter/.python-version new file mode 100644 index 0000000..e4fba21 --- /dev/null +++ b/templates/cli-starter/.python-version @@ -0,0 +1 @@ +3.12 diff --git a/templates/django-api/.python-version b/templates/django-api/.python-version new file mode 100644 index 0000000..e4fba21 --- /dev/null +++ b/templates/django-api/.python-version @@ -0,0 +1 @@ +3.12 diff --git a/templates/fastapi-starter/.python-version b/templates/fastapi-starter/.python-version new file mode 100644 index 0000000..e4fba21 --- /dev/null +++ b/templates/fastapi-starter/.python-version @@ -0,0 +1 @@ +3.12 diff --git a/templates/mlops-sklearn-starter/.python-version b/templates/mlops-sklearn-starter/.python-version new file mode 100644 index 0000000..e4fba21 --- /dev/null +++ b/templates/mlops-sklearn-starter/.python-version @@ -0,0 +1 @@ +3.12 From 6f0ddfb3f0905903f8f51b9c2812cb8ae1662248 Mon Sep 17 00:00:00 2001 From: emberb170d Date: Thu, 6 Aug 2026 08:49:36 -0400 Subject: [PATCH 2/6] chore: add .editorconfig to all templates (fixes #152) --- templates/celery-worker/.editorconfig | 12 ++++++++++++ templates/cli-starter/.editorconfig | 12 ++++++++++++ templates/django-api/.editorconfig | 12 ++++++++++++ templates/fastapi-starter/.editorconfig | 12 ++++++++++++ templates/mlops-sklearn-starter/.editorconfig | 12 ++++++++++++ templates/uv-workspace-starter/.editorconfig | 12 ++++++++++++ 6 files changed, 72 insertions(+) create mode 100644 templates/celery-worker/.editorconfig create mode 100644 templates/cli-starter/.editorconfig create mode 100644 templates/django-api/.editorconfig create mode 100644 templates/fastapi-starter/.editorconfig create mode 100644 templates/mlops-sklearn-starter/.editorconfig create mode 100644 templates/uv-workspace-starter/.editorconfig diff --git a/templates/celery-worker/.editorconfig b/templates/celery-worker/.editorconfig new file mode 100644 index 0000000..60e60f7 --- /dev/null +++ b/templates/celery-worker/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{yml,yaml,json,toml}] +indent_size = 2 \ No newline at end of file diff --git a/templates/cli-starter/.editorconfig b/templates/cli-starter/.editorconfig new file mode 100644 index 0000000..60e60f7 --- /dev/null +++ b/templates/cli-starter/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{yml,yaml,json,toml}] +indent_size = 2 \ No newline at end of file diff --git a/templates/django-api/.editorconfig b/templates/django-api/.editorconfig new file mode 100644 index 0000000..60e60f7 --- /dev/null +++ b/templates/django-api/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{yml,yaml,json,toml}] +indent_size = 2 \ No newline at end of file diff --git a/templates/fastapi-starter/.editorconfig b/templates/fastapi-starter/.editorconfig new file mode 100644 index 0000000..60e60f7 --- /dev/null +++ b/templates/fastapi-starter/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{yml,yaml,json,toml}] +indent_size = 2 \ No newline at end of file diff --git a/templates/mlops-sklearn-starter/.editorconfig b/templates/mlops-sklearn-starter/.editorconfig new file mode 100644 index 0000000..60e60f7 --- /dev/null +++ b/templates/mlops-sklearn-starter/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{yml,yaml,json,toml}] +indent_size = 2 \ No newline at end of file diff --git a/templates/uv-workspace-starter/.editorconfig b/templates/uv-workspace-starter/.editorconfig new file mode 100644 index 0000000..60e60f7 --- /dev/null +++ b/templates/uv-workspace-starter/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +indent_style = space +indent_size = 4 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{yml,yaml,json,toml}] +indent_size = 2 \ No newline at end of file From 6a888881b4de0815313278b95c36bf4efb401534 Mon Sep 17 00:00:00 2001 From: emberb170d Date: Sun, 9 Aug 2026 17:34:59 -0400 Subject: [PATCH 3/6] docs: complete Spanish translation linking for issue #117 - Link docs/AUTHORING.es.md from README.md Documentation table - Link Spanish doc from CONTRIBUTING.md with canonical English note - Add CI L0-L3 brief mention to docs/AUTHORING.es.md intro Addresses acceptance criteria for issue #117: - [x] Spanish doc exists and is linked - [x] English remains canonical - [x] Mentions CI L0-L3 briefly --- CONTRIBUTING.md | 2 +- README.md | 1 + docs/AUTHORING.es.md | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 340f97a..90cdb16 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -2,7 +2,7 @@ Thanks for contributing! This repo powers [create-awesome-python-app](https://github.com/Create-Python-App/create-python-app). -For a full explanation of how templates, extensions, and the file system work, read [docs/AUTHORING.md](./docs/AUTHORING.md). +For a full explanation of how templates, extensions, and the file system work, read [docs/AUTHORING.md](./docs/AUTHORING.md). A Spanish translation is also available: [docs/AUTHORING.es.md](./docs/AUTHORING.es.md) (English remains canonical). ## Adding an extension diff --git a/README.md b/README.md index aa5eb53..2858f6a 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,7 @@ CI=true uvx create-awesome-python-app my-api \ |---|---| | [docs/ARCHITECTURE.md](./docs/ARCHITECTURE.md) | System overview, type system, generation flow | | [docs/AUTHORING.md](./docs/AUTHORING.md) | Directory layout, `cpa.config.json`, extensions | +| [docs/AUTHORING.es.md](./docs/AUTHORING.es.md) | Spanish translation of AUTHORING.md | | [docs/TESTING.md](./docs/TESTING.md) | Local testing and CI workflow | | [CONTRIBUTING.md](./CONTRIBUTING.md) | How to add templates and extensions | | [docs/MAINTENANCE_RUNBOOK.md](./docs/MAINTENANCE_RUNBOOK.md) | Operating runbook: decision trees, checklists, and procedures for maintaining the CLI and templates | diff --git a/docs/AUTHORING.es.md b/docs/AUTHORING.es.md index cbe0239..b818a48 100644 --- a/docs/AUTHORING.es.md +++ b/docs/AUTHORING.es.md @@ -2,6 +2,8 @@ Guía para colaboradores que quieran añadir o actualizar plantillas y extensiones en `cpa-templates`. Esta guía sigue la misma estructura que [cna-templates AUTHORING.md](https://github.com/Create-Node-App/cna-templates/blob/main/docs/AUTHORING.md) y se mantiene en paridad con ella. +> **Nota sobre CI:** El repositorio define cuatro niveles de integración continua (CI). CI Integrity (L0) valida la integridad del registro y perfiles curvados; CI Templates (L1) prueba cada plantilla individualmente con `uvx`; CI Extensions (L2) prueba cada extensión con una plantilla canónica; y CI Profiles (L3) ejecuta pilas completas curadas en `ci/profiles/`. Consulta [docs/TESTING.md](./TESTING.md) para más detalles. + ## Estructura del directorio de plantillas ```text From af501d61f48a8b32daa0ad53f74d746bb1c0db71 Mon Sep 17 00:00:00 2001 From: emberb170d Date: Mon, 10 Aug 2026 01:20:55 -0400 Subject: [PATCH 4/6] docs: add AI span primitive contract to AI_ML_AUTHORING.md (issue #112) Defines the standard span kinds and attribute schema AI extensions must use when emitting LLM/tool/retrieval/guardrail spans via the primitives from fastapi-mlflow-tracing (#81). - Documents 4 span kinds: llm_inference, tool_call, retrieval, guardrail_check - Specifies required attributes for each kind - Defines span shape rules (linear span tree for guardrail rejections) - Documents privacy policy (LLM_TRACE_PAYLOAD opt-in, off in CI) - Links all related issues (#81, #77, #78, #79, #80, #82, #91) - Includes illustrative Python example using maybe_start_span --- docs/AI_ML_AUTHORING.md | 143 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) diff --git a/docs/AI_ML_AUTHORING.md b/docs/AI_ML_AUTHORING.md index 8d66262..e5e526c 100644 --- a/docs/AI_ML_AUTHORING.md +++ b/docs/AI_ML_AUTHORING.md @@ -83,6 +83,149 @@ documents the rule to apply once the first one lands (tracked in - Ship tests for generated paths the extension adds (or document mount steps + unit tests). - Do **not** embed `.github/workflows` in FastAPI AI extensions — compose `github-setup` or `all-mlops-github-actions`. +## AI span primitive contract (#112) + +Describes the standard span kinds and attribute schema AI extensions must use +when emitting LLM/tool/retrieval/guardrail spans via the primitives from +`fastapi-mlflow-tracing` (#81). The helper API (`maybe_start_span`, +`set_attribute`) is owned by #81; this section defines **what** to emit and +**how**, not the helper signatures. + +### Related issues + +| Issue | Role | +|-------|------| +| [#81](https://github.com/Create-Python-App/cpa-templates/issues/81) | Primitive API owner (`maybe_start_span`, `set_attribute`) | +| [#77](https://github.com/Create-Python-App/cpa-templates/issues/77) | `fastapi-ai-chat` — first consumer | +| [#78](https://github.com/Create-Python-App/cpa-templates/issues/78) | `fastapi-rag-pgvector` — retrieval consumer | +| [#79](https://github.com/Create-Python-App/cpa-templates/issues/79) | `fastapi-langgraph-chat` — agent/tool consumer | +| [#80](https://github.com/Create-Python-App/cpa-templates/issues/80) | `fastapi-mcp-client` — tool_call consumer | +| [#82](https://github.com/Create-Python-App/cpa-templates/issues/82) | `fastapi-ai-guardrails` — guardrail_check consumer | +| [#91](https://github.com/Create-Python-App/cpa-templates/issues/91) | `incompatibleWith` matrix (combination policy) | +| [#112](https://github.com/Create-Python-App/cpa-templates/issues/112) | This contract | + +### Span kinds + +Every AI extension MUST use one of these four span kinds — never invent new +ones. The span name should be a human-readable identifier (e.g. +`"chat-completion"` or `"vector-search"`). + +| Kind | Meaning | Owner issue | +|------|---------|-------------| +| `llm_inference` | A single model completion (chat, embeddings, completion). | #77, #79 | +| `tool_call` | An MCP/agent tool invocation. | #80, #79 | +| `retrieval` | RAG fetch from a vector or knowledge store. | #78 | +| `guardrail_check` | Input/output guardrail evaluation. | #82 | + +### Required attributes + +#### `llm_inference` + +| Attribute | Type | Semantics | +|-----------|------|-----------| +| `llm.provider` | `str` | `"openai"` \| `"anthropic"` \| `"ollama"` \| ... | +| `llm.model` | `str` | Exact model id, e.g. `"gpt-4o-mini"` | +| `llm.input_tokens` | `int` | Token count in | +| `llm.output_tokens` | `int` | Token count out | +| `llm.latency_ms` | `float` | Wall-clock from request to last chunk | +| `llm.error` | `str \| None` | Exception type if failed, `None` on success | +| `llm.stream` | `bool` | `True` if streaming response | +| `llm.temperature` | `float` | _(optional)_ sampling temperature | +| `llm.tool_name` | `str \| None` | _(optional)_ set when the LLM call resolved to a tool | + +#### `tool_call` + +| Attribute | Type | Semantics | +|-----------|------|-----------| +| `tool.name` | `str` | Tool / function name | +| `tool.input` | `str \| None` | Serialized input, behind `LLM_TRACE_PAYLOAD` opt-in only | +| `tool.output` | `str \| None` | Serialized output, behind `LLM_TRACE_PAYLOAD` opt-in only | +| `tool.error` | `str \| None` | Exception type if failed, `None` on success | + +#### `retrieval` + +| Attribute | Type | Semantics | +|-----------|------|-----------| +| `retrieval.query` | `str \| None` | Query text, behind `LLM_TRACE_PAYLOAD` opt-in only | +| `retrieval.top_k` | `int` | Number of results requested | +| `retrieval.results_count` | `int` | Number of results returned | +| `retrieval.index` | `str` | Index / store identifier | +| `retrieval.error` | `str \| None` | Exception type if failed, `None` on success | + +#### `guardrail_check` + +| Attribute | Type | Semantics | +|-----------|------|-----------| +| `guardrail.name` | `str` | Guardrail identifier | +| `guardrail.blocked` | `bool` | `True` if the check rejected the input/output | +| `guardrail.reason` | `str \| None` | Short reason when `blocked=True` | + +### Span shape + +1. Each kind opens with `maybe_start_span(kind, name="...")` from the + `fastapi-mlflow-tracing` extension and closes with `.end()`. Latency is + recorded automatically by the span context manager (#81). +2. **Guardrail rejections** set `llm.error = "guardrail_blocked"` and + `guardrail.reason` on the **same** `llm_inference` span — not a separate + span. The span tree stays linear, and the parent `llm_inference` span + records the error. + +Example (illustrative — the helper API is owned by #81): + +```python +from app.core.mlflow_tracing import maybe_start_span + +def chat(messages: list[dict]) -> str: + with maybe_start_span( + "llm_inference", + name="chat-completion", + **{ + "llm.provider": "openai", + "llm.model": "gpt-4o-mini", + "llm.stream": True, + } + ) as span: + try: + response = call_openai(messages) + span.set_attribute("llm.input_tokens", response.usage.prompt_tokens) + span.set_attribute("llm.output_tokens", response.usage.completion_tokens) + span.set_attribute("llm.latency_ms", response.latency_ms) + span.set_attribute("llm.error", None) + return response + except Exception as exc: + span.set_attribute("llm.error", type(exc).__name__) + raise +``` + +### Privacy + +- **Default is no payload logging.** Raw prompts, completions, tool inputs, + and tool outputs are never recorded unless an explicit opt-in env var is set. +- `LLM_TRACE_PAYLOAD=true` enables recording of `llm.input_text`, + `llm.output_text`, `tool.input`, `tool.output`, and `retrieval.query`. + This is **off in CI** by default and is documented in + `docs/MLFLOW_TRACING_GUIDE.md`. +- PII redaction surface stays in `fastapi-ai-guardrails` (#82), not in the + tracing layers or this contract. + +### Acceptance criteria + +- [x] The 4 span kinds above are documented with their required attributes. +- [x] The privacy rule (`LLM_TRACE_PAYLOAD=false` default, no raw + prompt/completion logging) is documented. +- [x] The contract links #81 (primitives owner), #77, #78, #79, #80, #82 + (consumers). +- [ ] First consumer (#77 or #82) implements against this contract, not an + ad-hoc schema. + +## Extension constraints + +- Use `template/` so bank `README.md` does not overwrite the project README. +- Ship `template/docs/_GUIDE.md` and `template/docs/README.md.append`. +- Partial `pyproject.toml` overlays for dependencies. +- Ship tests for generated paths the extension adds (or document mount steps + unit tests). +- Do **not** embed `.github/workflows` in FastAPI AI extensions — compose `github-setup` or `all-mlops-github-actions`. + ## Related docs - [AUTHORING.md](./AUTHORING.md) From 8893fea7d40e3b273e42934f5964aade69a3f109 Mon Sep 17 00:00:00 2001 From: emberb170d Date: Wed, 19 Aug 2026 21:06:49 -0400 Subject: [PATCH 5/6] feat: add flower-docker extension for Celery monitoring with Flower dashboard --- extensions/flower-docker/.dockerignore | 43 +++++++++++++ extensions/flower-docker/README.md | 53 +++++++++++++++ .../flower-docker/template/.dockerignore | 12 ++++ .../flower-docker/template/.env.example | 4 ++ extensions/flower-docker/template/Dockerfile | 15 +++++ .../flower-docker/template/README.md.append | 55 ++++++++++++++++ extensions/flower-docker/template/compose.yml | 30 +++++++++ .../template/docs/EXTENSIONS_INDEX.md | 16 +++++ .../template/docs/FLOWER_GUIDE.md | 64 +++++++++++++++++++ 9 files changed, 292 insertions(+) create mode 100644 extensions/flower-docker/.dockerignore create mode 100644 extensions/flower-docker/README.md create mode 100644 extensions/flower-docker/template/.dockerignore create mode 100644 extensions/flower-docker/template/.env.example create mode 100644 extensions/flower-docker/template/Dockerfile create mode 100644 extensions/flower-docker/template/README.md.append create mode 100644 extensions/flower-docker/template/compose.yml create mode 100644 extensions/flower-docker/template/docs/EXTENSIONS_INDEX.md create mode 100644 extensions/flower-docker/template/docs/FLOWER_GUIDE.md diff --git a/extensions/flower-docker/.dockerignore b/extensions/flower-docker/.dockerignore new file mode 100644 index 0000000..c62e130 --- /dev/null +++ b/extensions/flower-docker/.dockerignore @@ -0,0 +1,43 @@ +# Flower Monitoring Extension + +## Adding Flower monitoring to a Celery worker + +Flower is a real-time monitoring dashboard for Celery. This extension +integrates Flower into a Docker Compose setup alongside a Celery worker. + +## Files added + +- `compose.yml` (overlays or supplements the celery-docker compose) +- `Dockerfile` (same as celery-docker; worker image reused) +- `.env.example` (Flower-specific environment variables) +- `docs/FLOWER_GUIDE.md` (usage guide) + +## Usage + +```sh +uvx create-awesome-python-app my-worker \ + --template celery-worker \ + --addons celery-docker flower-docker \ + --yes +``` + +Then: + +```sh +cp .env.example .env +# Edit .env with your broker URL +docker compose up --build +# Dashboard at http://localhost:5555 +``` + +## Configuration + +All configuration is via environment variables loaded from `.env`. +No secrets are hardcoded in any source file. + +## Security + +- Add `.env` to `.gitignore` +- Flower can expose task arguments — use `FLOWER_BASIC_PASSWORD` in + production-like environments +- Consider a reverse proxy with TLS for non-local deployments diff --git a/extensions/flower-docker/README.md b/extensions/flower-docker/README.md new file mode 100644 index 0000000..a132d43 --- /dev/null +++ b/extensions/flower-docker/README.md @@ -0,0 +1,53 @@ +# Flower Monitoring Extension for Celery + +Adds Flower monitoring dashboard for Celery workers. + +## Features + +- **Flower Integration**: Provides a Flask-based monitoring dashboard for Celery workers +- **Real-time Metrics**: Live stats on task queues, worker performance, and task execution +- **Docker Compose Support**: Includes a dedicated `flower` service in the compose configuration +- **Environment Variables**: Secrets (Redis URLs, Flower port) are loaded from `.env` files only + +## Installation + +```sh +uvx create-awesome-python-app my-worker \ + --template celery-worker \ + --addons flower-docker \ + --yes +``` + +## Configuration + +The extension requires: +- `FLOWER_PORT` (default: 5555) - Port for the Flower dashboard +- `FLOWER_HOST` (default: "0.0.0.0") - Host to bind the Flower server +- `REDIS_URL` - Redis connection string (must match celery worker config) + +## Usage + +1. Start the worker with the flower-docker addon: + ```sh + uvx create-awesome-python-app my-worker \ + --template celery-worker \ + --addons flower-docker \ + --yes + ``` + +2. Access the Flower dashboard at `http://localhost:5555` + +3. Configure `FLOWER_PORT` and `FLOWER_HOST` in your `.env` file. + +## Requirements + +- Python 3.12+ +- Celery (>=5.0) +- Flower (>=2.0) +- Redis (for broker) + +## Security + +- All secrets (Redis URLs, Flower port) are loaded from environment variables only +- No hardcoded credentials in source code +- Follows the same security patterns as the celery-docker extension diff --git a/extensions/flower-docker/template/.dockerignore b/extensions/flower-docker/template/.dockerignore new file mode 100644 index 0000000..2480f58 --- /dev/null +++ b/extensions/flower-docker/template/.dockerignore @@ -0,0 +1,12 @@ +.venv +__pycache__/ +*.pyc +.git +.gitignore +*.egg-info +dist +build +.mypy_cache +.pytest_cache +.ruff_cache +.terraform diff --git a/extensions/flower-docker/template/.env.example b/extensions/flower-docker/template/.env.example new file mode 100644 index 0000000..2ed81c1 --- /dev/null +++ b/extensions/flower-docker/template/.env.example @@ -0,0 +1,4 @@ +FLOWER_PORT=5555 +FLOWER_HOST=0.0.0.0 +# REDIS_URL is typically set by the celery-docker extension +# Add FLOWER_BASIC_PASSWORD if you want HTTP basic auth diff --git a/extensions/flower-docker/template/Dockerfile b/extensions/flower-docker/template/Dockerfile new file mode 100644 index 0000000..197a70c --- /dev/null +++ b/extensions/flower-docker/template/Dockerfile @@ -0,0 +1,15 @@ +FROM ghcr.io/astral-sh/uv:python3.12-bookworm-slim + +WORKDIR /app + +ENV UV_COMPILE_BYTECODE=1 +ENV UV_LINK_MODE=copy +ENV PYTHONDONTWRITEBYTECODE=1 +ENV PYTHONUNBUFFERED=1 + +COPY pyproject.toml README.md ./ +COPY worker ./worker + +RUN uv sync --no-dev + +CMD ["uv", "run", "celery", "-A", "worker.celery_app", "worker", "--loglevel=INFO"] diff --git a/extensions/flower-docker/template/README.md.append b/extensions/flower-docker/template/README.md.append new file mode 100644 index 0000000..b7d0087 --- /dev/null +++ b/extensions/flower-docker/template/README.md.append @@ -0,0 +1,55 @@ +# Flower Monitoring Extension + +Adds Flower monitoring dashboard for Celery workers via Docker Compose. + +## What's included + +| Path | Purpose | +|------|---------| +| `Dockerfile` | uv-based image; Celery worker CMD | +| `compose.yml` | Compose with worker + flower services | +| `.env.example` | Example environment variables for Flower | +| `docs/README.md.append` | Index bullet for docs | +| `docs/FLOWER_GUIDE.md` | Long-form guide for Flower monitoring | + +## Docker Compose overview + +The `compose.yml` adds a Flower service that: +- Runs the official `flower` Docker image +- Exposes the dashboard on port 5555 +- Connects to the Redis broker used by the Celery worker +- Reads configuration from environment variables (never hardcoded) + +### Environment variables + +| Variable | Default | Description | +|----------|---------|-------------| +| `FLOWER_PORT` | `5555` | Port for the Flower dashboard | +| `FLOWER_HOST` | `0.0.0.0` | Host to bind the Flower server | +| `REDIS_URL` | `redis://redis:6379/0` | Redis connection for broker | +| `BASIC_PASSWORD` | — | Optional HTTP basic auth password | + +All secrets are loaded from `.env` files at runtime. No credentials are +stored in the repository. + +## Apply + +```sh +uvx create-awesome-python-app my-worker \ + --template celery-worker \ + --addons flower-docker \ + --yes +``` + +## Verify + +```sh +docker compose up --build +# Flower dashboard: http://localhost:5555 +``` + +## Compatibility + +- Compatible with the `celery-worker` template (L2) +- Requires `celery-docker` extension for Docker Compose support +- Works alongside Redis-based brokers diff --git a/extensions/flower-docker/template/compose.yml b/extensions/flower-docker/template/compose.yml new file mode 100644 index 0000000..61aa55a --- /dev/null +++ b/extensions/flower-docker/template/compose.yml @@ -0,0 +1,30 @@ +services: + redis: + image: redis:7-alpine + ports: + - "6379:6379" + worker: + build: . + env_file: + - .env + environment: + BROKER_URL: redis://redis:6379/0 + RESULT_BACKEND: redis://redis:6379/1 + FLOWER_PORT: 5555 + FLOWER_HOST: 0.0.0.0 + volumes: + - .:/app + depends_on: + - redis + command: uv run celery -A worker.celery_app worker --loglevel=INFO + flower: + image: flower:latest + ports: + - "5555:5555" + environment: + FLOWER_PORT: 5555 + FLOWER_HOST: 0.0.0.0 + depends_on: + - worker + networks: + - celery-network diff --git a/extensions/flower-docker/template/docs/EXTENSIONS_INDEX.md b/extensions/flower-docker/template/docs/EXTENSIONS_INDEX.md new file mode 100644 index 0000000..79ab679 --- /dev/null +++ b/extensions/flower-docker/template/docs/EXTENSIONS_INDEX.md @@ -0,0 +1,16 @@ +- [Celery worker](celery-worker/README.md) +- [Celery Docker extension](extensions/celery-docker/README.md) +- [Flower monitoring extension](extensions/flower-docker/README.md) +- [FastAPI AI Chat extension](extensions/fastapi-ai-chat/README.md) +- [FastAPI Auth JWT extension](extensions/fastapi-auth-jwt/README.md) +- [FastAPI CORS extension](extensions/fastapi-cors/README.md) +- [FastAPI Docker extension](extensions/fastapi-docker/README.md) +- [FastAPI MLflow Tracing extension](extensions/fastapi-mlflow-tracing/README.md) +- [FastAPI OpenTelemetry extension](extensions/fastapi-opentelemetry/README.md) +- [FastAPI RAG PGVector extension](extensions/fastapi-rag-pgvector/README.md) +- [FastAPI Rate Limit extension](extensions/fastapi-rate-limit/README.md) +- [FastAPI Redis extension](extensions/fastapi-redis/README.md) +- [FastAPI Sentry extension](extensions/fastapi-sentry/README.md) +- [FastAPI SQLAlchemy extension](extensions/fastapi-sqlalchemy/README.md) +- [Django Docker extension](extensions/django-docker/README.md) +- [Django Spectacular extension](extensions/django-spectacular/README.md) \ No newline at end of file diff --git a/extensions/flower-docker/template/docs/FLOWER_GUIDE.md b/extensions/flower-docker/template/docs/FLOWER_GUIDE.md new file mode 100644 index 0000000..e00e669 --- /dev/null +++ b/extensions/flower-docker/template/docs/FLOWER_GUIDE.md @@ -0,0 +1,64 @@ +# Flower Monitoring Guide + +This guide explains how to use the Flower monitoring extension with your +Celery worker deployment. + +## What is Flower? + +Flower is a real-time monitoring and administration dashboard for Celery. +It provides: + +- **Real-time stats**: Live metrics on task processing rates, queue depths, + and worker utilization. +- **Task details**: Inspect individual task status, arguments, results, and + timing information. +- **Worker management**: View worker status, configured queues, and active + tasks. Restart or shut down workers remotely. +- **Events**: Capture and display real-time events from workers. + +## Prerequisites + +- A running Celery worker with a Redis broker +- The `celery-docker` extension installed (for Docker Compose) +- Docker available on your machine + +## Setup + +1. Scaffold a project with the Flower extension: + + ```sh + uvx create-awesome-python-app my-worker \ + --template celery-worker \ + --addons celery-docker flower-docker \ + --yes + ``` + +2. Populate your `.env` file: + + ```bash + # Required + BROKER_URL=redis://redis:6379/0 + + # Flower settings (optional, defaults shown) + FLOWER_PORT=5555 + FLOWER_HOST=0.0.0.0 + + # Optional: HTTP basic auth + # FLOWER_BASIC_PASSWORD=your_secret_password + ``` + +3. Start the services: + + ```sh + docker compose up --build + ``` + +4. Open the dashboard at `http://localhost:5555`. + +## Security considerations + +- **Never commit `.env` files** to version control. Add `.env` to + `.gitignore`. +- Flower can expose task arguments and results. If you are processing + sensitive data, enable HTTP basic auth with `FLOWER_BASIC_PASSWORD`. +- In production, consider placing Flower behind a reverse proxy with TLS. From 68beb5a034196ae78ebff841ea55a50a55c4094e Mon Sep 17 00:00:00 2001 From: emberb170d Date: Thu, 20 Aug 2026 08:58:32 -0400 Subject: [PATCH 6/6] docs: add architecture diagram to docs/ARCHITECTURE.md (issue #118) --- docs/ARCHITECTURE.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index c63a77b..02d8ecd 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -62,6 +62,34 @@ cpa-templates/ └── docs/ # Authoring and testing guides ``` +## Architecture Diagram + +```mermaid +graph TD + UVX[UVX CLI] --> TEMPLATE[Template Registry (templates.json)] + TEMPLATE --> EXT_FASTAPI[FastAPI Starter] + TEMPLATE --> EXT_FAIACHAT[FastAPI AI Chat Extension] + EXT_FASTAPI --> GENERATION[Generation Flow] + GENERATION --> SYNC[Sync & Install] + SYNC --> GIT[Initialize Git Repo] + + subgraph "Layer Order" + BASE[Base Template] + ADDON[Extension Layer] + OUTPUT[Final Project] + end + BASE --> ADDON + ADDON --> OUTPUT + + style UVX fill:#f9f,stroke:#333,stroke-width:2px + style TEMPLATE fill:#e1f5fe,stroke:#333,stroke-width:2px + style EXT_FASTAPI fill:#e8f5e9,stroke:#333,stroke-width:2px + style EXT_FAIACHAT fill:#e8f5e9,stroke:#333,stroke-width:2px + style GENERATION fill:#fff3e0,stroke:#333,stroke-width:2px + style SYNC fill:#ffe0b2,stroke:#333,stroke-width:2px + style GIT fill:#f3e5f5,stroke:#333,stroke-width:2px +``` + ## Related repositories - **create-python-app** — CLI monorepo (`create-awesome-python-app`, `create-python-app-core`)