bront 0.1.0__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.
- bront-0.1.0/.dockerignore +8 -0
- bront-0.1.0/.env.example +9 -0
- bront-0.1.0/.github/workflows/ci.yml +102 -0
- bront-0.1.0/.gitignore +12 -0
- bront-0.1.0/.python-version +1 -0
- bront-0.1.0/Dockerfile +18 -0
- bront-0.1.0/LICENSE +21 -0
- bront-0.1.0/PKG-INFO +171 -0
- bront-0.1.0/README.md +149 -0
- bront-0.1.0/compose.scenarios.yaml +20 -0
- bront-0.1.0/compose.triton.yaml +37 -0
- bront-0.1.0/compose.yaml +65 -0
- bront-0.1.0/deploy/kubernetes/fallback.yaml +65 -0
- bront-0.1.0/deploy/kubernetes/gateway.yaml +81 -0
- bront-0.1.0/deploy/kubernetes/kind.yaml +5 -0
- bront-0.1.0/deploy/kubernetes/kustomization.yaml +19 -0
- bront-0.1.0/deploy/kubernetes/namespace.yaml +4 -0
- bront-0.1.0/deploy/kubernetes/observability/dashboards.yml +9 -0
- bront-0.1.0/deploy/kubernetes/observability/datasources.yml +11 -0
- bront-0.1.0/deploy/kubernetes/observability/gateway.json +384 -0
- bront-0.1.0/deploy/kubernetes/observability/grafana.yaml +62 -0
- bront-0.1.0/deploy/kubernetes/observability/kustomization.yaml +13 -0
- bront-0.1.0/deploy/kubernetes/observability/prometheus.yaml +71 -0
- bront-0.1.0/deploy/kubernetes/observability/prometheus.yml +23 -0
- bront-0.1.0/deploy/kubernetes/run-job.yaml +37 -0
- bront-0.1.0/deploy/kubernetes/triton.yaml +88 -0
- bront-0.1.0/deploy/prometheus/prometheus.yml +7 -0
- bront-0.1.0/deploy/toxiproxy/proxies.json +8 -0
- bront-0.1.0/deploy/triton/kustomization.yaml +8 -0
- bront-0.1.0/deploy/triton/models/double/1/model.onnx +0 -0
- bront-0.1.0/deploy/triton/models/double/config.pbtxt +11 -0
- bront-0.1.0/docs/architecture.md +68 -0
- bront-0.1.0/docs/comparisons.md +259 -0
- bront-0.1.0/docs/external-endpoints.md +206 -0
- bront-0.1.0/docs/kubernetes.md +229 -0
- bront-0.1.0/docs/observability.md +82 -0
- bront-0.1.0/docs/proposals/inference-reliability.md +44 -0
- bront-0.1.0/docs/reports.md +136 -0
- bront-0.1.0/docs/scenarios.md +222 -0
- bront-0.1.0/docs/triton.md +140 -0
- bront-0.1.0/examples/comparison/baseline.toml +30 -0
- bront-0.1.0/examples/comparison/limits.toml +12 -0
- bront-0.1.0/examples/gateway/cases.jsonl +1 -0
- bront-0.1.0/examples/gateway/suite.toml +16 -0
- bront-0.1.0/examples/http-json/cases.jsonl +3 -0
- bront-0.1.0/examples/http-json/server.py +53 -0
- bront-0.1.0/examples/http-json/suite.toml +16 -0
- bront-0.1.0/examples/kubernetes/cases.jsonl +1 -0
- bront-0.1.0/examples/kubernetes/suite.toml +18 -0
- bront-0.1.0/examples/scenarios/kubernetes-restart.toml +25 -0
- bront-0.1.0/examples/scenarios/kubernetes-scale-zero.toml +29 -0
- bront-0.1.0/examples/scenarios/proxy-delay.toml +27 -0
- bront-0.1.0/examples/scenarios/proxy-outage.toml +26 -0
- bront-0.1.0/pyproject.toml +61 -0
- bront-0.1.0/scripts/build_triton_model.py +31 -0
- bront-0.1.0/scripts/load_kind_images.py +36 -0
- bront-0.1.0/scripts/smoke_compose.py +81 -0
- bront-0.1.0/scripts/smoke_external.py +233 -0
- bront-0.1.0/scripts/smoke_kubernetes.py +89 -0
- bront-0.1.0/scripts/smoke_triton.py +102 -0
- bront-0.1.0/src/bront/__init__.py +1 -0
- bront-0.1.0/src/bront/artifacts.py +30 -0
- bront-0.1.0/src/bront/checks.py +104 -0
- bront-0.1.0/src/bront/cli.py +21 -0
- bront-0.1.0/src/bront/compare_cli.py +81 -0
- bront-0.1.0/src/bront/comparison_models.py +83 -0
- bront-0.1.0/src/bront/comparisons.py +231 -0
- bront-0.1.0/src/bront/evidence.py +297 -0
- bront-0.1.0/src/bront/faults.py +66 -0
- bront-0.1.0/src/bront/html_reports.py +474 -0
- bront-0.1.0/src/bront/kubernetes_scenarios.py +225 -0
- bront-0.1.0/src/bront/measurement.py +69 -0
- bront-0.1.0/src/bront/provenance.py +71 -0
- bront-0.1.0/src/bront/proxy_scenarios.py +81 -0
- bront-0.1.0/src/bront/reference/__init__.py +1 -0
- bront-0.1.0/src/bront/reference/adapters.py +95 -0
- bront-0.1.0/src/bront/reference/backends.py +99 -0
- bront-0.1.0/src/bront/reference/circuit_breaker.py +62 -0
- bront-0.1.0/src/bront/reference/config.py +17 -0
- bront-0.1.0/src/bront/reference/draining.py +30 -0
- bront-0.1.0/src/bront/reference/gateway.py +78 -0
- bront-0.1.0/src/bront/reference/metrics.py +78 -0
- bront-0.1.0/src/bront/reference/mock_backend.py +44 -0
- bront-0.1.0/src/bront/reference/schemas.py +21 -0
- bront-0.1.0/src/bront/report_cli.py +32 -0
- bront-0.1.0/src/bront/report_styles.py +48 -0
- bront-0.1.0/src/bront/results.py +81 -0
- bront-0.1.0/src/bront/run_cli.py +67 -0
- bront-0.1.0/src/bront/runs.py +224 -0
- bront-0.1.0/src/bront/scenario_models.py +92 -0
- bront-0.1.0/src/bront/scenarios.py +181 -0
- bront-0.1.0/src/bront/series.py +79 -0
- bront-0.1.0/src/bront/suites.py +223 -0
- bront-0.1.0/src/bront/targets.py +72 -0
- bront-0.1.0/src/bront/validation.py +124 -0
- bront-0.1.0/tests/test_circuit_breaker.py +48 -0
- bront-0.1.0/tests/test_cli.py +29 -0
- bront-0.1.0/tests/test_comparisons.py +323 -0
- bront-0.1.0/tests/test_external_runs.py +364 -0
- bront-0.1.0/tests/test_gateway.py +374 -0
- bront-0.1.0/tests/test_html_reports.py +238 -0
- bront-0.1.0/tests/test_kubernetes_scenarios.py +297 -0
- bront-0.1.0/tests/test_measurement.py +33 -0
- bront-0.1.0/tests/test_metrics.py +55 -0
- bront-0.1.0/tests/test_mock_backend.py +18 -0
- bront-0.1.0/tests/test_scenarios.py +323 -0
- bront-0.1.0/tests/test_series.py +183 -0
- bront-0.1.0/tests/test_triton_model.py +23 -0
- bront-0.1.0/tests/test_validation.py +58 -0
- bront-0.1.0/uv.lock +727 -0
bront-0.1.0/.env.example
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Copy to .env for gateway runs outside Docker Compose.
|
|
2
|
+
BRONT_PRIMARY_URL=http://127.0.0.1:8001
|
|
3
|
+
BRONT_FALLBACK_URL=http://127.0.0.1:8002
|
|
4
|
+
# Set to triton when running the gateway locally against a Triton primary.
|
|
5
|
+
# compose.triton.yaml sets this automatically for its gateway container.
|
|
6
|
+
BRONT_PRIMARY_PROTOCOL=mock
|
|
7
|
+
BRONT_REQUEST_TIMEOUT_SECONDS=1
|
|
8
|
+
BRONT_FAILURE_THRESHOLD=3
|
|
9
|
+
BRONT_RECOVERY_TIMEOUT_SECONDS=10
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on: [push, pull_request]
|
|
3
|
+
|
|
4
|
+
jobs:
|
|
5
|
+
check:
|
|
6
|
+
runs-on: ubuntu-latest
|
|
7
|
+
steps:
|
|
8
|
+
- uses: actions/checkout@v4
|
|
9
|
+
- uses: astral-sh/setup-uv@v6
|
|
10
|
+
with:
|
|
11
|
+
version: "0.11.21"
|
|
12
|
+
enable-cache: true
|
|
13
|
+
- run: uv sync --frozen
|
|
14
|
+
- run: uv run ruff check .
|
|
15
|
+
- run: uv run ruff format --check .
|
|
16
|
+
- run: uv run ty check --python-version 3.12
|
|
17
|
+
- run: docker compose config --quiet
|
|
18
|
+
- run: docker compose -f compose.triton.yaml config --quiet
|
|
19
|
+
- run: docker compose up --build --wait --wait-timeout 120
|
|
20
|
+
- run: docker compose exec -T gateway /app/.venv/bin/python --version
|
|
21
|
+
- run: uv run python scripts/smoke_compose.py
|
|
22
|
+
- name: Compose logs
|
|
23
|
+
if: failure()
|
|
24
|
+
run: docker compose logs --no-color
|
|
25
|
+
- name: Stop Compose services
|
|
26
|
+
if: always()
|
|
27
|
+
run: docker compose down
|
|
28
|
+
|
|
29
|
+
scenarios:
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
timeout-minutes: 10
|
|
32
|
+
env:
|
|
33
|
+
COMPOSE_FILE: compose.yaml:compose.scenarios.yaml
|
|
34
|
+
COMPOSE_PROJECT_NAME: bront-scenarios-ci
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@v4
|
|
37
|
+
- uses: astral-sh/setup-uv@v6
|
|
38
|
+
with:
|
|
39
|
+
version: "0.11.21"
|
|
40
|
+
enable-cache: true
|
|
41
|
+
- run: uv sync --frozen
|
|
42
|
+
- run: docker compose config --quiet
|
|
43
|
+
- name: Start scenario stack
|
|
44
|
+
run: docker compose up --build --wait --wait-timeout 120
|
|
45
|
+
- name: Run reusable proxy scenarios
|
|
46
|
+
run: |
|
|
47
|
+
uv run --frozen bront run examples/scenarios/proxy-outage.toml --output reports/scenarios/proxy-outage.json
|
|
48
|
+
uv run --frozen bront run examples/scenarios/proxy-delay.toml --output reports/scenarios/proxy-delay.json
|
|
49
|
+
- name: Render scenario HTML
|
|
50
|
+
if: always() && hashFiles('reports/scenarios/*.json') != ''
|
|
51
|
+
run: |
|
|
52
|
+
for source in reports/scenarios/*.json; do
|
|
53
|
+
uv run --frozen bront report "$source" --output "${source%.json}.html"
|
|
54
|
+
done
|
|
55
|
+
- name: Upload scenario reports
|
|
56
|
+
if: always() && hashFiles('reports/scenarios/*.json') != ''
|
|
57
|
+
uses: actions/upload-artifact@v7
|
|
58
|
+
with:
|
|
59
|
+
name: scenario-reports
|
|
60
|
+
path: reports/scenarios/
|
|
61
|
+
if-no-files-found: error
|
|
62
|
+
retention-days: 14
|
|
63
|
+
- name: Scenario Compose logs
|
|
64
|
+
if: failure()
|
|
65
|
+
run: docker compose logs --no-color
|
|
66
|
+
- name: Stop scenario services
|
|
67
|
+
if: always()
|
|
68
|
+
run: docker compose down
|
|
69
|
+
|
|
70
|
+
python-compatibility:
|
|
71
|
+
runs-on: ubuntu-latest
|
|
72
|
+
timeout-minutes: 10
|
|
73
|
+
strategy:
|
|
74
|
+
fail-fast: false
|
|
75
|
+
matrix:
|
|
76
|
+
python: ["3.12", "3.13", "3.14"]
|
|
77
|
+
env:
|
|
78
|
+
UV_PYTHON: ${{ matrix.python }}
|
|
79
|
+
steps:
|
|
80
|
+
- uses: actions/checkout@v4
|
|
81
|
+
- uses: astral-sh/setup-uv@v6
|
|
82
|
+
with:
|
|
83
|
+
version: "0.11.21"
|
|
84
|
+
enable-cache: true
|
|
85
|
+
- run: uv sync --frozen --python "${{ matrix.python }}"
|
|
86
|
+
- run: uv run --frozen pytest
|
|
87
|
+
- name: Build and install the standalone package
|
|
88
|
+
run: |
|
|
89
|
+
uv build
|
|
90
|
+
uv venv --python "${{ matrix.python }}" "$RUNNER_TEMP/bront-core"
|
|
91
|
+
uv pip install --python "$RUNNER_TEMP/bront-core/bin/python" dist/bront-*.whl
|
|
92
|
+
"$RUNNER_TEMP/bront-core/bin/python" -c "import importlib.util; import bront.cli; assert importlib.util.find_spec('fastapi') is None"
|
|
93
|
+
- name: Verify HTTP runs, comparisons, interruption handling, and HTML reports
|
|
94
|
+
run: '"$RUNNER_TEMP/bront-core/bin/python" scripts/smoke_external.py'
|
|
95
|
+
- name: Upload external endpoint reports
|
|
96
|
+
if: always() && hashFiles('reports/external/*.json') != ''
|
|
97
|
+
uses: actions/upload-artifact@v7
|
|
98
|
+
with:
|
|
99
|
+
name: external-endpoint-reports-py${{ matrix.python }}
|
|
100
|
+
path: reports/external/
|
|
101
|
+
if-no-files-found: error
|
|
102
|
+
retention-days: 14
|
bront-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.14
|
bront-0.1.0/Dockerfile
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
FROM python:3.14-slim AS cli
|
|
2
|
+
|
|
3
|
+
ENV PYTHONDONTWRITEBYTECODE=1 PYTHONUNBUFFERED=1 UV_PYTHON_DOWNLOADS=never
|
|
4
|
+
WORKDIR /app
|
|
5
|
+
RUN pip install --no-cache-dir uv==0.11.21
|
|
6
|
+
COPY .python-version pyproject.toml uv.lock README.md ./
|
|
7
|
+
COPY src ./src
|
|
8
|
+
RUN uv sync --frozen --no-dev --no-editable
|
|
9
|
+
RUN useradd --create-home --uid 10001 app
|
|
10
|
+
USER app
|
|
11
|
+
CMD ["/app/.venv/bin/bront", "--help"]
|
|
12
|
+
|
|
13
|
+
FROM cli AS reference
|
|
14
|
+
USER root
|
|
15
|
+
RUN uv sync --frozen --no-dev --no-editable --extra reference
|
|
16
|
+
USER app
|
|
17
|
+
EXPOSE 8000
|
|
18
|
+
CMD ["/app/.venv/bin/uvicorn", "bront.reference.gateway:app", "--host", "0.0.0.0", "--port", "8000"]
|
bront-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Frank Lee
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
bront-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: bront
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Validate and measure inference endpoints, with a reference failover gateway
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
11
|
+
Requires-Python: >=3.12
|
|
12
|
+
Requires-Dist: httpx<1,>=0.28
|
|
13
|
+
Requires-Dist: pydantic<3,>=2.10
|
|
14
|
+
Requires-Dist: rich<16,>=14
|
|
15
|
+
Requires-Dist: typer<1,>=0.20
|
|
16
|
+
Provides-Extra: reference
|
|
17
|
+
Requires-Dist: fastapi<1,>=0.115; extra == 'reference'
|
|
18
|
+
Requires-Dist: prometheus-client<1,>=0.21; extra == 'reference'
|
|
19
|
+
Requires-Dist: pydantic-settings<3,>=2.7; extra == 'reference'
|
|
20
|
+
Requires-Dist: uvicorn<1,>=0.34; extra == 'reference'
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
# Bront
|
|
24
|
+
|
|
25
|
+
Repeatable reliability tests and release evidence for inference deployments.
|
|
26
|
+
Bront checks an existing HTTP JSON endpoint against representative inputs,
|
|
27
|
+
correctness assertions, and latency/error limits. Add fault or rollout scenarios,
|
|
28
|
+
compare repeated baseline and candidate runs, and share an offline HTML report.
|
|
29
|
+
Your service does not need to adopt Bront's reference gateway.
|
|
30
|
+
|
|
31
|
+
## Quickstart
|
|
32
|
+
|
|
33
|
+
Requires Python 3.12 or newer; tested on CPython 3.12, 3.13, and 3.14. From this checkout:
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
uv sync --frozen
|
|
37
|
+
uv run python examples/http-json/server.py
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
In another terminal:
|
|
41
|
+
|
|
42
|
+
```sh
|
|
43
|
+
uv run bront run examples/http-json/suite.toml --output reports/run.json
|
|
44
|
+
uv run bront report reports/run.json --output reports/review.html
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Open `reports/review.html` in a browser. The standalone example requires no Docker,
|
|
48
|
+
Kubernetes, Triton, or backend-specific status API.
|
|
49
|
+
|
|
50
|
+
For your own service, configure the URL, JSONL input cases, expected outputs,
|
|
51
|
+
workload, and assertions in a TOML suite. Read the
|
|
52
|
+
[external endpoint guide](docs/external-endpoints.md) for the supported contract.
|
|
53
|
+
Credentials can reference environment variables; raw payloads and credential values
|
|
54
|
+
are excluded from normal reports.
|
|
55
|
+
|
|
56
|
+
## Release workflow
|
|
57
|
+
|
|
58
|
+
```sh
|
|
59
|
+
uv run bront run baseline.toml --repeat 3 --output reports/baseline.json
|
|
60
|
+
uv run bront run candidate.toml --repeat 3 --output reports/candidate.json
|
|
61
|
+
uv run bront compare reports/baseline.json reports/candidate.json \
|
|
62
|
+
--policy limits.toml --output reports/comparison.json
|
|
63
|
+
uv run bront report reports/comparison.json --output reports/comparison.html
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Record deployment metadata and explicitly allow the intended change in the
|
|
67
|
+
comparison policy. Bront checks experiment compatibility before evaluating
|
|
68
|
+
regressions. Missing context, incomplete execution, or insufficient repeat evidence
|
|
69
|
+
cannot produce a passing comparison. Observed variation is not a statistical
|
|
70
|
+
significance test.
|
|
71
|
+
|
|
72
|
+
| Command | Purpose |
|
|
73
|
+
| --- | --- |
|
|
74
|
+
| `bront run` | Execute a suite, retain samples, and evaluate release assertions. |
|
|
75
|
+
| `bront compare` | Compare compatible repeated experiments against an explicit policy. |
|
|
76
|
+
| `bront report` | Render recorded evidence as self-contained HTML with JSON downloads. |
|
|
77
|
+
|
|
78
|
+
`run` and `compare` return 0 for passing evidence, 1 for failed checks, and 2 for
|
|
79
|
+
execution/configuration problems or inconclusive/incompatible comparisons.
|
|
80
|
+
Interrupted runs use exit 130 and retain partial evidence. `report` returns 0 when
|
|
81
|
+
rendering succeeds; it does not replace a release gate.
|
|
82
|
+
|
|
83
|
+
## Guides
|
|
84
|
+
|
|
85
|
+
- [External endpoints and response validation](docs/external-endpoints.md)
|
|
86
|
+
- [Proxy faults and Kubernetes scenarios](docs/scenarios.md)
|
|
87
|
+
- [Repeated runs and release comparisons](docs/comparisons.md)
|
|
88
|
+
- [Offline HTML reports](docs/reports.md)
|
|
89
|
+
- [Architecture](docs/architecture.md)
|
|
90
|
+
- [Roadmap and remaining validation](docs/proposals/inference-reliability.md)
|
|
91
|
+
|
|
92
|
+
## Optional reference deployment
|
|
93
|
+
|
|
94
|
+
The reference gateway, compatible mock fallback, Triton `double` model, fault
|
|
95
|
+
proxy, and monitoring stack exercise the same suite workflow. They are fixtures,
|
|
96
|
+
not required infrastructure for using Bront. Gateway code lives in
|
|
97
|
+
`bront.reference`; its server dependencies are an optional `reference` extra.
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
# Build and start the mock reference stack.
|
|
101
|
+
docker compose up --build --wait
|
|
102
|
+
uv run bront run examples/gateway/suite.toml --output reports/gateway.json
|
|
103
|
+
uv run python scripts/smoke_compose.py
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
For controlled outage and delay scenarios:
|
|
107
|
+
|
|
108
|
+
```sh
|
|
109
|
+
docker compose -f compose.yaml -f compose.scenarios.yaml up --build --wait
|
|
110
|
+
uv run bront run examples/scenarios/proxy-outage.toml --output reports/outage.json
|
|
111
|
+
uv run bront run examples/scenarios/proxy-delay.toml --output reports/delay.json
|
|
112
|
+
uv run bront report reports/outage.json --output reports/outage.html
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Run one fault experiment at a time against a disposable reference stack. Scenarios
|
|
116
|
+
record control events and restore owned faults on ordinary errors and interruption.
|
|
117
|
+
The [scenario guide](docs/scenarios.md) explains cleanup and recovery boundaries.
|
|
118
|
+
|
|
119
|
+
See the [Triton walkthrough](docs/triton.md) for the ONNX CPU integration,
|
|
120
|
+
[Kubernetes guide](docs/kubernetes.md) for two independent gateway replicas, and
|
|
121
|
+
[observability guide](docs/observability.md) for per-pod metrics. The `double` model
|
|
122
|
+
is an integration fixture; a trained-model example remains on the roadmap.
|
|
123
|
+
|
|
124
|
+
For a locally launched gateway, copy `.env.example` to `.env` and install the
|
|
125
|
+
reference dependencies with `uv sync --extra reference`. Entry points are
|
|
126
|
+
`bront.reference.gateway:app` and `bront.reference.mock_backend:app`.
|
|
127
|
+
Reference environment variables use `BRONT_`; metrics use `bront_`.
|
|
128
|
+
The suite runner uses explicit TOML and process environment variables, not `.env`.
|
|
129
|
+
|
|
130
|
+
## Development and packaging
|
|
131
|
+
|
|
132
|
+
```sh
|
|
133
|
+
uv sync --frozen
|
|
134
|
+
uv run ruff check .
|
|
135
|
+
uv run ruff format --check .
|
|
136
|
+
uv run ty check --python-version 3.12
|
|
137
|
+
uv run pytest
|
|
138
|
+
uv run python scripts/smoke_external.py
|
|
139
|
+
uv build
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
The distribution, import package, and CLI are all named `bront`. A core wheel
|
|
143
|
+
installation needs no FastAPI or Prometheus dependencies. Source-checkout dev
|
|
144
|
+
requirements include the reference dependencies to test both workflows.
|
|
145
|
+
No registry publication is required to install a locally built wheel.
|
|
146
|
+
|
|
147
|
+
The `.python-version` file selects Python 3.14 for default checkout development;
|
|
148
|
+
it is not the package's installation requirement. To work on another supported version:
|
|
149
|
+
|
|
150
|
+
```sh
|
|
151
|
+
uv sync --python 3.12 --frozen
|
|
152
|
+
uv run --python 3.12 pytest
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
CI tests the full suite and an isolated wheel installation on Python 3.12, 3.13,
|
|
156
|
+
and 3.14, including the run/compare/report smoke workflow. Ruff and type checking
|
|
157
|
+
target the 3.12 minimum to catch accidental use of newer syntax or APIs.
|
|
158
|
+
The reference Docker images continue using Python 3.14.
|
|
159
|
+
|
|
160
|
+
The Dockerfile provides a `cli` build target for the tool alone and a default
|
|
161
|
+
`reference` target for the fixture services:
|
|
162
|
+
|
|
163
|
+
```sh
|
|
164
|
+
docker build --target cli -t bront:cli .
|
|
165
|
+
docker run --rm bront:cli
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
CI runs lint, types, tests, the reference Compose smoke check, reusable proxy
|
|
169
|
+
scenarios, and the standalone run/compare/report workflow. It uploads JSON and
|
|
170
|
+
HTML artifacts, including evidence retained after failed experiments. Generated
|
|
171
|
+
reports belong under the ignored `reports/` directory rather than in Git.
|
bront-0.1.0/README.md
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# Bront
|
|
2
|
+
|
|
3
|
+
Repeatable reliability tests and release evidence for inference deployments.
|
|
4
|
+
Bront checks an existing HTTP JSON endpoint against representative inputs,
|
|
5
|
+
correctness assertions, and latency/error limits. Add fault or rollout scenarios,
|
|
6
|
+
compare repeated baseline and candidate runs, and share an offline HTML report.
|
|
7
|
+
Your service does not need to adopt Bront's reference gateway.
|
|
8
|
+
|
|
9
|
+
## Quickstart
|
|
10
|
+
|
|
11
|
+
Requires Python 3.12 or newer; tested on CPython 3.12, 3.13, and 3.14. From this checkout:
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
uv sync --frozen
|
|
15
|
+
uv run python examples/http-json/server.py
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
In another terminal:
|
|
19
|
+
|
|
20
|
+
```sh
|
|
21
|
+
uv run bront run examples/http-json/suite.toml --output reports/run.json
|
|
22
|
+
uv run bront report reports/run.json --output reports/review.html
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Open `reports/review.html` in a browser. The standalone example requires no Docker,
|
|
26
|
+
Kubernetes, Triton, or backend-specific status API.
|
|
27
|
+
|
|
28
|
+
For your own service, configure the URL, JSONL input cases, expected outputs,
|
|
29
|
+
workload, and assertions in a TOML suite. Read the
|
|
30
|
+
[external endpoint guide](docs/external-endpoints.md) for the supported contract.
|
|
31
|
+
Credentials can reference environment variables; raw payloads and credential values
|
|
32
|
+
are excluded from normal reports.
|
|
33
|
+
|
|
34
|
+
## Release workflow
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
uv run bront run baseline.toml --repeat 3 --output reports/baseline.json
|
|
38
|
+
uv run bront run candidate.toml --repeat 3 --output reports/candidate.json
|
|
39
|
+
uv run bront compare reports/baseline.json reports/candidate.json \
|
|
40
|
+
--policy limits.toml --output reports/comparison.json
|
|
41
|
+
uv run bront report reports/comparison.json --output reports/comparison.html
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Record deployment metadata and explicitly allow the intended change in the
|
|
45
|
+
comparison policy. Bront checks experiment compatibility before evaluating
|
|
46
|
+
regressions. Missing context, incomplete execution, or insufficient repeat evidence
|
|
47
|
+
cannot produce a passing comparison. Observed variation is not a statistical
|
|
48
|
+
significance test.
|
|
49
|
+
|
|
50
|
+
| Command | Purpose |
|
|
51
|
+
| --- | --- |
|
|
52
|
+
| `bront run` | Execute a suite, retain samples, and evaluate release assertions. |
|
|
53
|
+
| `bront compare` | Compare compatible repeated experiments against an explicit policy. |
|
|
54
|
+
| `bront report` | Render recorded evidence as self-contained HTML with JSON downloads. |
|
|
55
|
+
|
|
56
|
+
`run` and `compare` return 0 for passing evidence, 1 for failed checks, and 2 for
|
|
57
|
+
execution/configuration problems or inconclusive/incompatible comparisons.
|
|
58
|
+
Interrupted runs use exit 130 and retain partial evidence. `report` returns 0 when
|
|
59
|
+
rendering succeeds; it does not replace a release gate.
|
|
60
|
+
|
|
61
|
+
## Guides
|
|
62
|
+
|
|
63
|
+
- [External endpoints and response validation](docs/external-endpoints.md)
|
|
64
|
+
- [Proxy faults and Kubernetes scenarios](docs/scenarios.md)
|
|
65
|
+
- [Repeated runs and release comparisons](docs/comparisons.md)
|
|
66
|
+
- [Offline HTML reports](docs/reports.md)
|
|
67
|
+
- [Architecture](docs/architecture.md)
|
|
68
|
+
- [Roadmap and remaining validation](docs/proposals/inference-reliability.md)
|
|
69
|
+
|
|
70
|
+
## Optional reference deployment
|
|
71
|
+
|
|
72
|
+
The reference gateway, compatible mock fallback, Triton `double` model, fault
|
|
73
|
+
proxy, and monitoring stack exercise the same suite workflow. They are fixtures,
|
|
74
|
+
not required infrastructure for using Bront. Gateway code lives in
|
|
75
|
+
`bront.reference`; its server dependencies are an optional `reference` extra.
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
# Build and start the mock reference stack.
|
|
79
|
+
docker compose up --build --wait
|
|
80
|
+
uv run bront run examples/gateway/suite.toml --output reports/gateway.json
|
|
81
|
+
uv run python scripts/smoke_compose.py
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
For controlled outage and delay scenarios:
|
|
85
|
+
|
|
86
|
+
```sh
|
|
87
|
+
docker compose -f compose.yaml -f compose.scenarios.yaml up --build --wait
|
|
88
|
+
uv run bront run examples/scenarios/proxy-outage.toml --output reports/outage.json
|
|
89
|
+
uv run bront run examples/scenarios/proxy-delay.toml --output reports/delay.json
|
|
90
|
+
uv run bront report reports/outage.json --output reports/outage.html
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Run one fault experiment at a time against a disposable reference stack. Scenarios
|
|
94
|
+
record control events and restore owned faults on ordinary errors and interruption.
|
|
95
|
+
The [scenario guide](docs/scenarios.md) explains cleanup and recovery boundaries.
|
|
96
|
+
|
|
97
|
+
See the [Triton walkthrough](docs/triton.md) for the ONNX CPU integration,
|
|
98
|
+
[Kubernetes guide](docs/kubernetes.md) for two independent gateway replicas, and
|
|
99
|
+
[observability guide](docs/observability.md) for per-pod metrics. The `double` model
|
|
100
|
+
is an integration fixture; a trained-model example remains on the roadmap.
|
|
101
|
+
|
|
102
|
+
For a locally launched gateway, copy `.env.example` to `.env` and install the
|
|
103
|
+
reference dependencies with `uv sync --extra reference`. Entry points are
|
|
104
|
+
`bront.reference.gateway:app` and `bront.reference.mock_backend:app`.
|
|
105
|
+
Reference environment variables use `BRONT_`; metrics use `bront_`.
|
|
106
|
+
The suite runner uses explicit TOML and process environment variables, not `.env`.
|
|
107
|
+
|
|
108
|
+
## Development and packaging
|
|
109
|
+
|
|
110
|
+
```sh
|
|
111
|
+
uv sync --frozen
|
|
112
|
+
uv run ruff check .
|
|
113
|
+
uv run ruff format --check .
|
|
114
|
+
uv run ty check --python-version 3.12
|
|
115
|
+
uv run pytest
|
|
116
|
+
uv run python scripts/smoke_external.py
|
|
117
|
+
uv build
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The distribution, import package, and CLI are all named `bront`. A core wheel
|
|
121
|
+
installation needs no FastAPI or Prometheus dependencies. Source-checkout dev
|
|
122
|
+
requirements include the reference dependencies to test both workflows.
|
|
123
|
+
No registry publication is required to install a locally built wheel.
|
|
124
|
+
|
|
125
|
+
The `.python-version` file selects Python 3.14 for default checkout development;
|
|
126
|
+
it is not the package's installation requirement. To work on another supported version:
|
|
127
|
+
|
|
128
|
+
```sh
|
|
129
|
+
uv sync --python 3.12 --frozen
|
|
130
|
+
uv run --python 3.12 pytest
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
CI tests the full suite and an isolated wheel installation on Python 3.12, 3.13,
|
|
134
|
+
and 3.14, including the run/compare/report smoke workflow. Ruff and type checking
|
|
135
|
+
target the 3.12 minimum to catch accidental use of newer syntax or APIs.
|
|
136
|
+
The reference Docker images continue using Python 3.14.
|
|
137
|
+
|
|
138
|
+
The Dockerfile provides a `cli` build target for the tool alone and a default
|
|
139
|
+
`reference` target for the fixture services:
|
|
140
|
+
|
|
141
|
+
```sh
|
|
142
|
+
docker build --target cli -t bront:cli .
|
|
143
|
+
docker run --rm bront:cli
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
CI runs lint, types, tests, the reference Compose smoke check, reusable proxy
|
|
147
|
+
scenarios, and the standalone run/compare/report workflow. It uploads JSON and
|
|
148
|
+
HTML artifacts, including evidence retained after failed experiments. Generated
|
|
149
|
+
reports belong under the ignored `reports/` directory rather than in Git.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Overlay either compose.yaml or compose.triton.yaml for controlled fault scenarios.
|
|
2
|
+
services:
|
|
3
|
+
gateway:
|
|
4
|
+
environment:
|
|
5
|
+
BRONT_PRIMARY_URL: http://fault-proxy:8666
|
|
6
|
+
depends_on:
|
|
7
|
+
fault-proxy:
|
|
8
|
+
condition: service_healthy
|
|
9
|
+
|
|
10
|
+
fault-proxy:
|
|
11
|
+
image: ghcr.io/shopify/toxiproxy:2.12.0
|
|
12
|
+
command: ["-host=0.0.0.0", "-config=/config/proxies.json"]
|
|
13
|
+
ports: ["127.0.0.1:${BRONT_TOXIPROXY_PORT:-18474}:8474"]
|
|
14
|
+
volumes:
|
|
15
|
+
- ./deploy/toxiproxy/proxies.json:/config/proxies.json:ro
|
|
16
|
+
healthcheck:
|
|
17
|
+
test: ["CMD", "/toxiproxy-cli", "list"]
|
|
18
|
+
interval: 5s
|
|
19
|
+
timeout: 3s
|
|
20
|
+
retries: 10
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: bront
|
|
2
|
+
# Standalone alternative to compose.yaml: docker compose -f compose.triton.yaml up
|
|
3
|
+
services:
|
|
4
|
+
gateway:
|
|
5
|
+
extends:
|
|
6
|
+
file: compose.yaml
|
|
7
|
+
service: gateway
|
|
8
|
+
environment:
|
|
9
|
+
BRONT_PRIMARY_PROTOCOL: triton
|
|
10
|
+
|
|
11
|
+
primary:
|
|
12
|
+
image: nvcr.io/nvidia/tritonserver:26.08-py3
|
|
13
|
+
init: true
|
|
14
|
+
command:
|
|
15
|
+
- tritonserver
|
|
16
|
+
- --model-repository=/models
|
|
17
|
+
- --disable-auto-complete-config
|
|
18
|
+
- --allow-grpc=false
|
|
19
|
+
- --allow-gpu-metrics=false
|
|
20
|
+
ports: ["127.0.0.1:${BRONT_PRIMARY_PORT:-8001}:8000"]
|
|
21
|
+
volumes:
|
|
22
|
+
- ./deploy/triton/models:/models:ro
|
|
23
|
+
healthcheck:
|
|
24
|
+
test:
|
|
25
|
+
- CMD
|
|
26
|
+
- python3
|
|
27
|
+
- -c
|
|
28
|
+
- "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/v2/models/double/versions/1/ready', timeout=2)"
|
|
29
|
+
interval: 5s
|
|
30
|
+
timeout: 3s
|
|
31
|
+
retries: 12
|
|
32
|
+
start_period: 30s
|
|
33
|
+
|
|
34
|
+
fallback:
|
|
35
|
+
extends:
|
|
36
|
+
file: compose.yaml
|
|
37
|
+
service: fallback
|
bront-0.1.0/compose.yaml
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
name: bront
|
|
2
|
+
x-service: &service
|
|
3
|
+
build: .
|
|
4
|
+
init: true
|
|
5
|
+
healthcheck:
|
|
6
|
+
test:
|
|
7
|
+
[
|
|
8
|
+
"CMD",
|
|
9
|
+
"/app/.venv/bin/python",
|
|
10
|
+
"-c",
|
|
11
|
+
"import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/healthz', timeout=2)",
|
|
12
|
+
]
|
|
13
|
+
interval: 5s
|
|
14
|
+
timeout: 3s
|
|
15
|
+
retries: 5
|
|
16
|
+
start_period: 10s
|
|
17
|
+
|
|
18
|
+
services:
|
|
19
|
+
gateway:
|
|
20
|
+
<<: *service
|
|
21
|
+
ports: ["127.0.0.1:${BRONT_GATEWAY_PORT:-8000}:8000"]
|
|
22
|
+
environment:
|
|
23
|
+
BRONT_PRIMARY_URL: http://primary:8000
|
|
24
|
+
BRONT_FALLBACK_URL: http://fallback:8000
|
|
25
|
+
BRONT_REQUEST_TIMEOUT_SECONDS: "1"
|
|
26
|
+
BRONT_FAILURE_THRESHOLD: "3"
|
|
27
|
+
BRONT_RECOVERY_TIMEOUT_SECONDS: "10"
|
|
28
|
+
depends_on:
|
|
29
|
+
primary:
|
|
30
|
+
condition: service_healthy
|
|
31
|
+
fallback:
|
|
32
|
+
condition: service_healthy
|
|
33
|
+
|
|
34
|
+
primary:
|
|
35
|
+
<<: *service
|
|
36
|
+
command:
|
|
37
|
+
[
|
|
38
|
+
"/app/.venv/bin/uvicorn",
|
|
39
|
+
"bront.reference.mock_backend:app",
|
|
40
|
+
"--host",
|
|
41
|
+
"0.0.0.0",
|
|
42
|
+
"--port",
|
|
43
|
+
"8000",
|
|
44
|
+
]
|
|
45
|
+
ports: ["127.0.0.1:${BRONT_PRIMARY_PORT:-8001}:8000"]
|
|
46
|
+
|
|
47
|
+
fallback:
|
|
48
|
+
<<: *service
|
|
49
|
+
command:
|
|
50
|
+
[
|
|
51
|
+
"/app/.venv/bin/uvicorn",
|
|
52
|
+
"bront.reference.mock_backend:app",
|
|
53
|
+
"--host",
|
|
54
|
+
"0.0.0.0",
|
|
55
|
+
"--port",
|
|
56
|
+
"8000",
|
|
57
|
+
]
|
|
58
|
+
ports: ["127.0.0.1:${BRONT_FALLBACK_PORT:-8002}:8000"]
|
|
59
|
+
|
|
60
|
+
prometheus:
|
|
61
|
+
image: prom/prometheus:v3.2.1
|
|
62
|
+
profiles: ["observability"]
|
|
63
|
+
ports: ["127.0.0.1:9090:9090"]
|
|
64
|
+
volumes:
|
|
65
|
+
- ./deploy/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
|