first commit

This commit is contained in:
2026-06-24 14:31:42 +00:00
parent 77f946a553
commit 22b05a7a1b
10 changed files with 456 additions and 0 deletions
+5
View File
@@ -0,0 +1,5 @@
TZ=Europe/Berlin
REPORT_RENDERER_PORT=8080
GOTENBERG_URL=http://gotenberg:3000
RENDER_TIMEOUT_SECONDS=60
MAX_PAYLOAD_BYTES=2097152
+7
View File
@@ -0,0 +1,7 @@
.env
__pycache__/
*.pyc
.pytest_cache/
output/*.pdf
output/*.html
!output/.gitkeep
+17
View File
@@ -0,0 +1,17 @@
MIT License
Copyright (c) 2026
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+92
View File
@@ -0,0 +1,92 @@
.env.example
.gitignore
LICENSE
Makefile
QUICKSTART.md
README.md
docker-compose.yml
docs/CUSTOMIZATION.md
docs/DATA_MODEL.md
docs/PRODUCTION_CHECKLIST.md
examples/curl-render.sh
examples/render-all-themes.sh
examples/sample-claude-input.json
examples/sample-claude-output.json
examples/sample-report.json
n8n/README.md
n8n/code-build-claude-request.js
n8n/code-build-render-payload.js
n8n/code-extract-claude-output.js
n8n/code-normalize-month.js
n8n/postgres-example-queries.sql
n8n/postgres-schema.sql
n8n/workflow-template.json
output/.gitkeep
output/sample-report-classic.html
output/sample-report-classic.pdf
output/sample-report-modern.html
output/sample-report-modern.pdf
output/theme-catalog/alpine-sage.html
output/theme-catalog/classic.html
output/theme-catalog/editorial-ink.html
output/theme-catalog/editorial-ivory.html
output/theme-catalog/editorial-rose.html
output/theme-catalog/executive-blue.html
output/theme-catalog/executive-burgundy.html
output/theme-catalog/executive-charcoal.html
output/theme-catalog/forest-lodge.html
output/theme-catalog/ledger-blue.html
output/theme-catalog/ledger-green.html
output/theme-catalog/ledger-sepia.html
output/theme-catalog/magazine-citrus.html
output/theme-catalog/magazine-cobalt.html
output/theme-catalog/magazine-plum.html
output/theme-catalog/midnight-gold.html
output/theme-catalog/modern.html
output/theme-catalog/nordic-light.html
output/theme-catalog/nordic-night.html
output/theme-catalog/ocean-breeze.html
output/theme-catalog/poster-mono.html
output/theme-catalog/poster-red.html
output/theme-catalog/poster-yellow.html
output/theme-catalog/soft-lavender.html
output/theme-catalog/split-teal.html
output/theme-catalog/split-terracotta.html
output/theme-catalog/split-violet.html
output/theme-catalog/sunset-coral.html
output/theme-catalog/theme-gallery.html
output/theme-catalog/theme-gallery.pdf
prompts/anthropic-request-template.json
prompts/system-prompt.txt
prompts/user-prompt-template.txt
pytest.ini
renderer/Dockerfile
renderer/app/__init__.py
renderer/app/formatting.py
renderer/app/main.py
renderer/app/renderer.py
renderer/app/schemas/claude-output-anthropic.schema.json
renderer/app/schemas/claude-output.schema.json
renderer/app/schemas/report-payload.schema.json
renderer/app/templates/_shared/footer.html.j2
renderer/app/templates/_shared/macros.html.j2
renderer/app/templates/classic/footer.html.j2
renderer/app/templates/classic/report.html.j2
renderer/app/templates/dashboard/report.html.j2
renderer/app/templates/editorial/report.html.j2
renderer/app/templates/ledger/report.html.j2
renderer/app/templates/magazine/report.html.j2
renderer/app/templates/minimal/report.html.j2
renderer/app/templates/modern/footer.html.j2
renderer/app/templates/modern/report.html.j2
renderer/app/templates/poster/report.html.j2
renderer/app/templates/sidebar/report.html.j2
renderer/app/templates/split/report.html.j2
renderer/app/theme_catalog.py
renderer/app/validation.py
renderer/requirements.txt
scripts/render-local.py
scripts/render-theme-gallery.py
tests/conftest.py
tests/test_render.py
tests/test_validation.py
+27
View File
@@ -0,0 +1,27 @@
.PHONY: up down logs test sample preview zip
up:
docker compose up -d --build
down:
docker compose down
logs:
docker compose logs -f report-renderer gotenberg
test:
python -m pytest -q
sample:
mkdir -p output
curl -sS -X POST http://localhost:8080/render \
-H 'Content-Type: application/json' \
--data-binary @examples/sample-report.json \
-o output/sample-report.pdf
preview:
mkdir -p output
curl -sS -X POST http://localhost:8080/preview/html \
-H 'Content-Type: application/json' \
--data-binary @examples/sample-report.json \
-o output/sample-report.html
+52
View File
@@ -0,0 +1,52 @@
# Schnellstart in 10 Schritten
1. Ordner auf deinen Docker-Host kopieren.
2. `.env.example` nach `.env` kopieren.
3. `docker compose up -d --build` starten.
4. `http://HOST:8080/health` pruefen.
5. `examples/sample-report.json` anpassen.
6. Mit `/preview/html` zuerst das HTML kontrollieren.
7. Mit `/render` das PDF erzeugen.
8. `n8n/workflow-template.json` in n8n importieren.
9. Anthropic-API-Key in n8n als Credential oder Secret hinterlegen.
10. Beispiel-Set-Node durch deine PostgreSQL-Abfragen ersetzen.
## Minimaler Render-Aufruf
```bash
curl -sS \
-X POST http://localhost:8080/render \
-H 'Content-Type: application/json' \
--data-binary @examples/sample-report.json \
-o output/report.pdf
```
## Dienste
- Report Renderer: `http://localhost:8080`
- Gotenberg: standardmaessig nur im internen Docker-Netz erreichbar
## API-Routen
- `GET /health`
- `GET /themes`
- `POST /validate`
- `POST /preview/html`
- `POST /render`
## Designs ansehen
Alle IDs abfragen:
```bash
curl -s http://localhost:8080/themes | python3 -m json.tool
```
Im Beispiel-Payload `design.theme` ändern oder alle Designs rendern:
```bash
bash examples/render-all-themes.sh
```
Der mitgelieferte visuelle Katalog liegt unter `output/theme-catalog/theme-gallery.pdf`.
+124
View File
@@ -0,0 +1,124 @@
# Monthly Report Kit
Ein reproduzierbares Starterpaket fuer monatliche Kundenreports mit:
- Claude Structured Outputs fuer valide, schemakonforme Inhalte
- fester HTML/CSS-Vorlage statt KI-generiertem Layout
- 28 austauschbaren Designs in 10 Layoutfamilien
- Python/FastAPI-Render-Service
- Gotenberg fuer die PDF-Erzeugung mit Chromium
- JSON-Schema-Validierung vor jedem Rendern
- n8n-Bausteinen und einem importierbaren Beispielworkflow
- Beispielreport, Prompt-Vorlagen und PostgreSQL-Grundstruktur
## Architektur
```text
PostgreSQL / andere Datenquelle
|
v
n8n normalisiert Monatsdaten
|
v
Claude Messages API + output_config.format
|
v
validiertes Claude-JSON
|
v
Report-Payload aus Kunde + Kennzahlen + Claude-Inhalt
|
v
report-renderer -> HTML/Jinja2 -> Gotenberg -> PDF
```
Claude entscheidet nur, **was** im Report steht. Das Template entscheidet, **wie** es aussieht.
## Schnellstart
```bash
cp .env.example .env
docker compose up -d --build
curl http://localhost:8080/health
```
Beispielreport erzeugen:
```bash
curl \
--request POST http://localhost:8080/render \
--header 'Content-Type: application/json' \
--data @examples/sample-report.json \
--output output/monatsreport-beispiel.pdf
```
HTML-Vorschau im Browser:
```bash
curl \
--request POST http://localhost:8080/preview/html \
--header 'Content-Type: application/json' \
--data @examples/sample-report.json \
--output output/preview.html
```
## Wichtigste Dateien
| Datei | Zweck |
|---|---|
| `renderer/app/theme_catalog.py` | Katalog aller 28 Designs und Farbpaletten |
| `renderer/app/templates/` | 10 wiederverwendbare Layoutfamilien |
| `scripts/render-theme-gallery.py` | erzeugt Vorschauen und einen PDF-Designkatalog |
| `renderer/app/schemas/claude-output-anthropic.schema.json` | API-kompatibles Structured-Output-Schema |
| `renderer/app/schemas/claude-output.schema.json` | strenge Nachvalidierung mit Textlaengen und Grenzen |
| `renderer/app/schemas/report-payload.schema.json` | kompletter Render-Payload |
| `prompts/system-prompt.txt` | feste Claude-Rolle und Regeln |
| `prompts/user-prompt-template.txt` | dynamischer Auftrag je Kunde/Monat |
| `n8n/workflow-template.json` | importierbarer Workflow-Startpunkt |
| `n8n/postgres-schema.sql` | Tabellen fuer Konfiguration und Reportlaeufe |
## Design auswählen
Alle verfügbaren Designs liefert der Renderer über `GET /themes`. Im Payload genügt die Theme-ID:
```json
{
"design": {
"theme": "executive-blue",
"palette_mode": "theme"
}
}
```
`palette_mode: "theme"` verwendet die fest definierte Farbwelt des Designs. Mit `palette_mode: "custom"` bleiben Layout und Typografie erhalten, während die im Payload gelieferten Kundenfarben verwendet werden. Die flexiblen Varianten `modern` und `classic` verwenden standardmäßig Kundenfarben.
### Enthaltene Layoutfamilien
| Familie | Charakter | Designs |
|---|---|---|
| Modern | Karten, Verlaufskopf, weich | `modern`, `soft-lavender`, `midnight-gold` |
| Classic | Serifenschrift, feine Linien | `classic` |
| Minimal | viel Weißraum, ruhige Flächen | `nordic-light`, `nordic-night`, `alpine-sage` |
| Dashboard | Management-orientierte KPI-Flächen | `executive-blue`, `executive-charcoal`, `executive-burgundy` |
| Sidebar | markante Seitenleiste | `ocean-breeze`, `forest-lodge`, `sunset-coral` |
| Editorial | magazinartige Serifengestaltung | `editorial-ivory`, `editorial-ink`, `editorial-rose` |
| Magazine | große Typografie, asymmetrische Module | `magazine-cobalt`, `magazine-citrus`, `magazine-plum` |
| Ledger | dicht, tabellarisch, zahlenorientiert | `ledger-green`, `ledger-blue`, `ledger-sepia` |
| Split | geteilte Titel- und Inhaltsflächen | `split-teal`, `split-violet`, `split-terracotta` |
| Poster | plakativ, sehr große Kennzahlen | `poster-red`, `poster-yellow`, `poster-mono` |
Den vollständigen visuellen Katalog findest du nach dem Entpacken unter `output/theme-catalog/theme-gallery.pdf`. Neu erzeugen kannst du ihn mit:
```bash
python scripts/render-theme-gallery.py
```
## Produktionshinweise
- API-Key niemals in Workflows exportieren oder im Repository speichern.
- `report_version`, `prompt_version` und `template_version` je Report sichern.
- Vor dem Versand immer Payload- und PDF-Pruefungen ausfuehren.
- Wiederholungen ueber einen eindeutigen Schluessel aus `customer_id + period` verhindern.
- Externe Bild-URLs vermeiden. Logos als Base64 Data URI uebergeben.
Weitere Hinweise stehen unter `docs/`.
+92
View File
@@ -0,0 +1,92 @@
3772de64cc98a7a239dd0ac1b671f5727c436eb97fdb6c04e4a026ac7c927d5e .env.example
cddeca481da53748d012f440fb4cc6346d79a4a435b088790df22a8fbeb5d14e .gitignore
ec4ab498897ee0d12aa7f8e354f3a7d4fd1baaf9db18dbf99927ffb78bed08ed LICENSE
734d0a6525a8303825860336d7199dd3a1f0c64ca6eef6f5216028b9c1de410d Makefile
f89b8af8904b9c2db9d798faa666e3dd680c1b1bb07dedde707a2db802780c15 QUICKSTART.md
8a173a2995256f0a31633d5bb7a389701b7ce7c0ed8f4b6bc75bb8ea77f33cec README.md
0234c23e00d70cd029f88c3d720326ec3fe0d14d4b857e36bb191836cece95d5 docker-compose.yml
339d856cdafc72a681fc14f5b21c525852ed7f9157e70464a21978328a8754a0 docs/CUSTOMIZATION.md
86bb53e3a4c40bf29feb11af0d4e160365b323010bdb846f473838afb66c5a4d docs/DATA_MODEL.md
9de8e978680517af375577c166af6fee0698a9e86ce0e37cd877dc2b91971b59 docs/PRODUCTION_CHECKLIST.md
901e0b2ffe44168bcdca34b2f37d257eafd183b50b66ab0fec38698a87014142 examples/curl-render.sh
ca7b0ddae3f0456def13ae40183ecf97e1d718e6fb80382ae2d8995e8260e00e examples/render-all-themes.sh
a188ee2512e5acc5015495e10701b412fb673dfb37885b580a4b2ece983f915f examples/sample-claude-input.json
c5db2c90552fc7499225c96a19f415cadeb40501c7834842c6e24ac8448467bd examples/sample-claude-output.json
9d83b926c4eab21bd7a9468bbde907a4a7075aa0a9f088fec3b587e4b76037c1 examples/sample-report.json
114c245d8200036e65e6e40530b747c643a09ce328e719b6713a0405ea75083f n8n/README.md
d95757c0b89bbb9257833f552f6fa28e5a69998421ce2ddfbf5eea1bdcf4b70a n8n/code-build-claude-request.js
19a764449c5040ac6cd1beee28a6a79073ea33063134b846a59a5bae23c44643 n8n/code-build-render-payload.js
2181b163b2a38bc280099a45fce6ade4729376f299e7b5b29ffbe62697471a7f n8n/code-extract-claude-output.js
e5a3dbef59ddb1b926a1fd282c3cf0f763d54429ed7f5f3265cb560544d663a4 n8n/code-normalize-month.js
c5f095a90926e7909d28623c8e2ae1e4dd2a755597b8f258de46e6040669168e n8n/postgres-example-queries.sql
1a69a0f745ea8b6b0f4aeaf841bfe30efd215dfab4d428dbf94451402a5ff54d n8n/postgres-schema.sql
80a655e305f2a9e6f33b73f7e1b6c468498727237260a49612b51ab137f1a2dc n8n/workflow-template.json
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 output/.gitkeep
67e0aa47dbab19484bd9668105f0c4452ec28295a23ca320b25f1e7067bb92b1 output/sample-report-classic.html
eda43c23832bd4ad9f0b8b6657235a13dd7fe3ccff6d25b8b62efd486ada1cdb output/sample-report-classic.pdf
3b51d683b8b13ba657d71067cb6b3ab5ba007aca4baa4d200bc654dc2e5da9af output/sample-report-modern.html
a4515612d9c153d77b423d6247501be2ecab64777b76ebb28ca9744b9ddfea06 output/sample-report-modern.pdf
182b07aa4da2759c1be79e82e72acefc068c89b1cdd4a79acec319ee76695a23 output/theme-catalog/alpine-sage.html
67e0aa47dbab19484bd9668105f0c4452ec28295a23ca320b25f1e7067bb92b1 output/theme-catalog/classic.html
cd65005a85bbe343a94773f8d97c6f12c75a313d7ea418858e3d4c892ecc744e output/theme-catalog/editorial-ink.html
e9e5e90889cf6b8075b3653d5cfc8632f17004ade3e4a3ec6dda2c0223ebb940 output/theme-catalog/editorial-ivory.html
9f6657791c563288c6a3e2bb0a154cbd356db0a9a33512343738956ae931272e output/theme-catalog/editorial-rose.html
9085f9d73c9afac53e336c424cde1f0fe8b1d7b062864db56eb9e45b5cdbdc46 output/theme-catalog/executive-blue.html
97227d9ed5d70ab9a24fe274e6718db808029cc12c5ffc09b451d8211a3c3031 output/theme-catalog/executive-burgundy.html
64607b1569dc17840cf8fc10a4eccd6409eb084193e46beb8556fbb8bc77fddc output/theme-catalog/executive-charcoal.html
2106baf980e86f5bdd0a520a073df40d35428a215e4efcc7f3f472adcdfa8594 output/theme-catalog/forest-lodge.html
3732f81d77b1cc80dba468f2cbda94779a613630ae74d84c65efcba7ec742c7c output/theme-catalog/ledger-blue.html
78783ddbc17c0e9866b25b6b93fa9010c488610115f4fa1a794108a7fb56e040 output/theme-catalog/ledger-green.html
514e8cf3e981ae304262866edae11cb69628ca870ba6ec7736969c9ca6f2ebe9 output/theme-catalog/ledger-sepia.html
f2b4413e8743a8e36fc5721df8fd3bad8cd4f500ecf60714d346086e34e2cde2 output/theme-catalog/magazine-citrus.html
889db73c6c649bb114fdd29055abc5e0a8fb30fe66e98fefb9608e4d25bdd823 output/theme-catalog/magazine-cobalt.html
2b7911ed20750b1939f96cc030243d95dd8ade9841c4cca3e059524f6e3b7d20 output/theme-catalog/magazine-plum.html
786f9f8ad6e27a27ab7ad0579d4ff5bd37900a653c53519f1aa5c7d9e7de83e6 output/theme-catalog/midnight-gold.html
3b51d683b8b13ba657d71067cb6b3ab5ba007aca4baa4d200bc654dc2e5da9af output/theme-catalog/modern.html
c12b3922f8f96afd221c1e9049fd5eaa7fcca6fdf608221630fe0deed6cfa07f output/theme-catalog/nordic-light.html
7ae6c3eae738abb26f7272e4171ef23dc3ded84e12938a2d35e1b9a5437a70b1 output/theme-catalog/nordic-night.html
52e63e72d056acbbb93f9c9954ffdf9406e18966955f9b3c76c54ef257e14995 output/theme-catalog/ocean-breeze.html
b0ccf9b7e7d492ce27a002b3da5b0aa7f6b056102997375e4492b54af4ba1f73 output/theme-catalog/poster-mono.html
11a3b7ebfc570371b0d2d59e065b0083630bfd5b180a679f045d22fc427fe47b output/theme-catalog/poster-red.html
d456da8ab54fc6b6e4c10d3fb5d10d964db40c819d2f3bb53816a1198315e0dc output/theme-catalog/poster-yellow.html
fe926c94c73f51b1aabf03bafef7a04acda08c6291ac19a70cfe5897ffb2fac8 output/theme-catalog/soft-lavender.html
b96d8a0c74e8f41e19085620366448bd4492ae49bd950268585a76f2a4a8846c output/theme-catalog/split-teal.html
c6dc77a1de12a41cf9540d8906debaf4512cc431c2797eacf524b1df15400924 output/theme-catalog/split-terracotta.html
2472963115164b2ae2c7fb38278e691065db845a95db8ad94be183aef66ae612 output/theme-catalog/split-violet.html
7aba082062da87bd78d08d8d984ee7ca755fe32917654e72d937ad4e9678a960 output/theme-catalog/sunset-coral.html
08d242bed264e0f31e1ab31ed79a37fb8a6bd18b91b63e79e05af175e97d4608 output/theme-catalog/theme-gallery.html
f39bb252bd52865c4551691a929d0cdf10d00eddd6a7f3ae0378f8bf2a8c5b55 output/theme-catalog/theme-gallery.pdf
23134c1e9992b5eb7c877b1c157d53ab0e36ac9c8ddcb2821b083f992b3dda39 prompts/anthropic-request-template.json
cd385809063a0badc73a37d7f87dc436886999785f8707c41bd57bd886fddc91 prompts/system-prompt.txt
0c6faf43172f0fa137d9c361dacceae4c5b972aef8623dcc14ea849bb1ccfb9b prompts/user-prompt-template.txt
c809c969ec7e11b9ff37784e9c6fcc0b7c5148d168e18b05aed797e03fbd6ead pytest.ini
6622f5ec0bc98804a17760ae13be6c9a9d1532eb36b69f72de01c749b565d454 renderer/Dockerfile
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 renderer/app/__init__.py
f46c52197e900e03b4a0b86d3b421534aa0387421c571ba743e3f0e041c2a0aa renderer/app/formatting.py
d515a0b7f4ea1976ba09903100409a3596f5f39e90aa496b4b7f2250a919d53f renderer/app/main.py
f18636cfa6ee4c5e509608cf047194eafb289b6798913595e4b43f3db7506178 renderer/app/renderer.py
8b7af092bdc0088832bd8f0e2fca15c10cb7c058ad4ad9d736ab7cbd677f97d6 renderer/app/schemas/claude-output-anthropic.schema.json
75b1bc32ae1e6d334279b385cf99712bf33cc78366e59c8f7013a39d11e334fc renderer/app/schemas/claude-output.schema.json
b1d9da86c2b0723f8c3bc3f03ffe89da15a099b1411b4e0a6c49a1e4be52b40a renderer/app/schemas/report-payload.schema.json
632d0dc09ca2bd9b98ac98aaf4540c14cd7c41c7cbad63358a56139303fce6e0 renderer/app/templates/_shared/footer.html.j2
cff8e11e83cca48fe3a6fc59cf0d72be2349c3d7c1ad5b168cb1826d8975594c renderer/app/templates/_shared/macros.html.j2
4c085ecc7a6418eb6d7fd673242dce76a65076b65c428baf6b1fff191354dd5a renderer/app/templates/classic/footer.html.j2
140c3d2810b67d62729a57cc03aa45d651236f93d6e124c9caaca7267157a62b renderer/app/templates/classic/report.html.j2
1690c913f1b92e45d40093338478ecff2b63e4a3efb92cf2e9e8da2af74c687e renderer/app/templates/dashboard/report.html.j2
e43f73535b336a52da00f2e6c11699c4f304a819f0f738629cef65b23b6af8b0 renderer/app/templates/editorial/report.html.j2
9f2827abc07b4888d2ffe9d5bb20062a242fcfcc0e50b183cb88bdd8532cbeb5 renderer/app/templates/ledger/report.html.j2
b3acd510ba16424bb32baa2e08b1ac9de95d84ac912e39913e19348d02d81e13 renderer/app/templates/magazine/report.html.j2
a89095e83da21a3c3f5db08d2abce769fcb6dbdb4f0bc89ae55e5aff0c740b86 renderer/app/templates/minimal/report.html.j2
a63847d53e571ddb28fd5cf3593e0913e6273ad6c9a6d50c550f045e1fb38942 renderer/app/templates/modern/footer.html.j2
cbb71a402abbd4ad4bcd95bfdfde6688a68d88c05168d6da51abbe72335e8446 renderer/app/templates/modern/report.html.j2
dd1d096c8c34ac741d3d645ec2bc23c698c208376c61036bcaa2c9235dda7173 renderer/app/templates/poster/report.html.j2
75a16ed98c86ba108e64d528c5292432c96101d4d466e27706c0ee4be216108e renderer/app/templates/sidebar/report.html.j2
63c48859557e147be9ed8b929370d49de8d7c192d0d2ad0361075353e819b68a renderer/app/templates/split/report.html.j2
30fbfcaf3973531384b8d0ed8df1b8868987a1be1d42d297953bf172db3d6e6d renderer/app/theme_catalog.py
1c8d516e13a21c16a306b35dedbc26929012f7afe03a8cb28899da09960b2d26 renderer/app/validation.py
35137cd8aeecd002116d489d98d0dc505909ec5d999d237387a094bd3e7f72f9 renderer/requirements.txt
e9ba2837656241375edd0f1027efe34c874d401efe87f3840a0a95e42a326ad0 scripts/render-local.py
0991e6bfdd450d1ce376b1cbf17170ba8c35342ac9bf320b30e858f0e45be49c scripts/render-theme-gallery.py
23b58558bad1c0c26a9095cb788f1b17bc8ba048c6db5fc9b24fa80b7097aa9b tests/conftest.py
811ecd465756c60292e65450434c6003ded577572315eee7f7809525ec253a49 tests/test_render.py
391a85063ce5ccafc11b23c24262292d05115c540d046a2dc177592233026852 tests/test_validation.py
+38
View File
@@ -0,0 +1,38 @@
services:
report-renderer:
build:
context: ./renderer
container_name: monthly-report-renderer
restart: unless-stopped
environment:
TZ: ${TZ:-Europe/Berlin}
GOTENBERG_URL: ${GOTENBERG_URL:-http://gotenberg:3000}
RENDER_TIMEOUT_SECONDS: ${RENDER_TIMEOUT_SECONDS:-60}
MAX_PAYLOAD_BYTES: ${MAX_PAYLOAD_BYTES:-2097152}
ports:
- "${REPORT_RENDERER_PORT:-8080}:8080"
depends_on:
gotenberg:
condition: service_healthy
networks:
- report-net
gotenberg:
image: gotenberg/gotenberg:8
container_name: monthly-report-gotenberg
restart: unless-stopped
command:
- gotenberg
- --chromium-disable-javascript=true
- --api-timeout=90s
healthcheck:
test: ["CMD", "curl", "--fail", "http://localhost:3000/health"]
interval: 10s
timeout: 5s
retries: 10
networks:
- report-net
networks:
report-net:
name: monthly-report-net
+2
View File
@@ -0,0 +1,2 @@
[pytest]
testpaths = tests