proofrun 0.1.1__tar.gz → 0.2.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.
Files changed (73) hide show
  1. proofrun-0.2.0/.dockerignore +13 -0
  2. {proofrun-0.1.1 → proofrun-0.2.0}/.github/workflows/ci.yaml +32 -14
  3. proofrun-0.2.0/.github/workflows/release.yaml +175 -0
  4. {proofrun-0.1.1 → proofrun-0.2.0}/.gitignore +4 -0
  5. proofrun-0.2.0/CHANGELOG.md +116 -0
  6. proofrun-0.2.0/Dockerfile +31 -0
  7. proofrun-0.2.0/Makefile +89 -0
  8. proofrun-0.2.0/PKG-INFO +702 -0
  9. proofrun-0.2.0/README.md +670 -0
  10. proofrun-0.2.0/deploy/docker-compose.yaml +31 -0
  11. proofrun-0.2.0/deploy/systemd/proofrun.env.example +13 -0
  12. proofrun-0.2.0/deploy/systemd/proofrun.service +57 -0
  13. {proofrun-0.1.1 → proofrun-0.2.0}/pyproject.toml +22 -4
  14. {proofrun-0.1.1 → proofrun-0.2.0}/scenarios/chain.yaml +2 -2
  15. {proofrun-0.1.1 → proofrun-0.2.0}/scenarios/crud.yaml +3 -4
  16. {proofrun-0.1.1 → proofrun-0.2.0}/scenarios/profile.yaml +2 -2
  17. proofrun-0.2.0/scenarios/resilient.yaml +51 -0
  18. proofrun-0.2.0/scenarios/server.py +186 -0
  19. {proofrun-0.1.1 → proofrun-0.2.0}/src/proofrun/__init__.py +1 -1
  20. {proofrun-0.1.1 → proofrun-0.2.0}/src/proofrun/__main__.py +1 -1
  21. proofrun-0.2.0/src/proofrun/cli/__init__.py +5 -0
  22. proofrun-0.2.0/src/proofrun/cli/commands.py +392 -0
  23. proofrun-0.2.0/src/proofrun/cli/render.py +97 -0
  24. proofrun-0.2.0/src/proofrun/config/__init__.py +1 -0
  25. {proofrun-0.1.1/src/proofrun/core → proofrun-0.2.0/src/proofrun/config}/compiler.py +62 -4
  26. proofrun-0.2.0/src/proofrun/config/envvars.py +75 -0
  27. proofrun-0.1.1/src/proofrun/core/config.py → proofrun-0.2.0/src/proofrun/config/models.py +96 -8
  28. {proofrun-0.1.1/src/proofrun/core → proofrun-0.2.0/src/proofrun/config}/provider.py +14 -3
  29. proofrun-0.1.1/src/proofrun/core/state.py → proofrun-0.2.0/src/proofrun/health.py +23 -3
  30. proofrun-0.2.0/src/proofrun/metrics/__init__.py +1 -0
  31. proofrun-0.2.0/src/proofrun/metrics/registry.py +136 -0
  32. proofrun-0.2.0/src/proofrun/metrics/server.py +117 -0
  33. proofrun-0.2.0/src/proofrun/monitor/__init__.py +1 -0
  34. proofrun-0.2.0/src/proofrun/monitor/daemon.py +202 -0
  35. proofrun-0.2.0/src/proofrun/monitor/scheduler.py +75 -0
  36. proofrun-0.2.0/src/proofrun/notify/__init__.py +1 -0
  37. proofrun-0.2.0/src/proofrun/notify/base.py +26 -0
  38. proofrun-0.1.1/src/proofrun/core/notifier.py → proofrun-0.2.0/src/proofrun/notify/webhook.py +25 -19
  39. proofrun-0.2.0/src/proofrun/runner/__init__.py +1 -0
  40. {proofrun-0.1.1/src/proofrun/core → proofrun-0.2.0/src/proofrun/runner}/context.py +16 -6
  41. {proofrun-0.1.1/src/proofrun/core → proofrun-0.2.0/src/proofrun/runner}/engine.py +48 -4
  42. proofrun-0.2.0/src/proofrun/runner/execution.py +56 -0
  43. proofrun-0.2.0/tests/conftest.py +45 -0
  44. proofrun-0.2.0/tests/test_cli.py +687 -0
  45. {proofrun-0.1.1 → proofrun-0.2.0}/tests/test_compiler.py +319 -2
  46. {proofrun-0.1.1 → proofrun-0.2.0}/tests/test_config.py +162 -3
  47. {proofrun-0.1.1 → proofrun-0.2.0}/tests/test_context.py +34 -1
  48. proofrun-0.2.0/tests/test_daemon.py +571 -0
  49. {proofrun-0.1.1 → proofrun-0.2.0}/tests/test_engine.py +89 -3
  50. proofrun-0.2.0/tests/test_envvars.py +69 -0
  51. proofrun-0.2.0/tests/test_execution.py +128 -0
  52. proofrun-0.1.1/tests/test_state.py → proofrun-0.2.0/tests/test_health.py +75 -1
  53. {proofrun-0.1.1 → proofrun-0.2.0}/tests/test_main.py +2 -2
  54. proofrun-0.2.0/tests/test_metrics.py +246 -0
  55. {proofrun-0.1.1 → proofrun-0.2.0}/tests/test_notifier.py +82 -13
  56. {proofrun-0.1.1 → proofrun-0.2.0}/tests/test_provider.py +49 -2
  57. proofrun-0.2.0/tests/test_readme.py +38 -0
  58. proofrun-0.2.0/tests/test_scheduler.py +95 -0
  59. {proofrun-0.1.1 → proofrun-0.2.0}/uv.lock +5 -70
  60. proofrun-0.1.1/.github/workflows/release.yaml +0 -113
  61. proofrun-0.1.1/Makefile +0 -67
  62. proofrun-0.1.1/PKG-INFO +0 -268
  63. proofrun-0.1.1/README.md +0 -250
  64. proofrun-0.1.1/scenarios/server.py +0 -83
  65. proofrun-0.1.1/src/proofrun/cli.py +0 -325
  66. proofrun-0.1.1/src/proofrun/core/__init__.py +0 -40
  67. proofrun-0.1.1/tests/test_cli.py +0 -912
  68. {proofrun-0.1.1 → proofrun-0.2.0}/.pre-commit-config.yaml +0 -0
  69. {proofrun-0.1.1 → proofrun-0.2.0}/LICENSE +0 -0
  70. {proofrun-0.1.1 → proofrun-0.2.0}/docs/demo-fail.svg +0 -0
  71. {proofrun-0.1.1 → proofrun-0.2.0}/docs/demo-pass.svg +0 -0
  72. {proofrun-0.1.1 → proofrun-0.2.0}/scenarios/auth.yaml +0 -0
  73. {proofrun-0.1.1 → proofrun-0.2.0}/tests/__init__.py +0 -0
@@ -0,0 +1,13 @@
1
+ .git
2
+ .github
3
+ .venv
4
+ .pytest_cache
5
+ .ruff_cache
6
+ .coverage
7
+ htmlcov
8
+ dist
9
+ **/__pycache__
10
+ tests
11
+ docs
12
+ deploy
13
+ FUTURE.md
@@ -16,7 +16,7 @@ permissions:
16
16
  jobs:
17
17
  quality:
18
18
  name: Quality & Tests
19
- runs-on: ubuntu-latest
19
+ runs-on: ubuntu-24.04
20
20
 
21
21
  strategy:
22
22
  fail-fast: false
@@ -27,15 +27,15 @@ jobs:
27
27
 
28
28
  steps:
29
29
  - name: Checkout repository
30
- uses: actions/checkout@v4
30
+ uses: actions/checkout@v7
31
31
 
32
32
  - name: Set up Python
33
- uses: actions/setup-python@v5
33
+ uses: actions/setup-python@v7
34
34
  with:
35
35
  python-version: ${{ matrix.python-version }}
36
36
 
37
37
  - name: Set up uv
38
- uses: astral-sh/setup-uv@v5
38
+ uses: astral-sh/setup-uv@v7
39
39
  with:
40
40
  enable-cache: true
41
41
  github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -46,29 +46,25 @@ jobs:
46
46
  - name: Run code quality & coverage checks
47
47
  run: make check
48
48
 
49
- - name: Run integration scenarios
50
- run: |
51
- make run-profile
52
- make run-auth
53
- make run-chain
54
- make run-crud
49
+ - name: Run integration scenarios (local demo API, no network)
50
+ run: make integration
55
51
 
56
52
  build:
57
53
  name: Build Package
58
- runs-on: ubuntu-latest
54
+ runs-on: ubuntu-24.04
59
55
  needs: quality
60
56
 
61
57
  steps:
62
58
  - name: Checkout repository
63
- uses: actions/checkout@v4
59
+ uses: actions/checkout@v7
64
60
 
65
61
  - name: Set up Python
66
- uses: actions/setup-python@v5
62
+ uses: actions/setup-python@v7
67
63
  with:
68
64
  python-version: "3.11"
69
65
 
70
66
  - name: Set up uv
71
- uses: astral-sh/setup-uv@v5
67
+ uses: astral-sh/setup-uv@v7
72
68
  with:
73
69
  enable-cache: true
74
70
  github-token: ${{ secrets.GITHUB_TOKEN }}
@@ -84,3 +80,25 @@ jobs:
84
80
  ls -lh dist/
85
81
  test -f dist/*.whl
86
82
  test -f dist/*.tar.gz
83
+
84
+ - name: Install the built packages in a clean environment
85
+ run: make dist-smoke
86
+
87
+ docker:
88
+ name: Docker Image
89
+ runs-on: ubuntu-24.04
90
+ needs: quality
91
+
92
+ steps:
93
+ - name: Checkout repository
94
+ uses: actions/checkout@v7
95
+
96
+ - name: Build image
97
+ run: docker build --tag proofrun:ci .
98
+
99
+ - name: Smoke test image
100
+ run: |
101
+ docker run --rm proofrun:ci --version
102
+ docker run --rm -v "$PWD/scenarios:/monitors:ro" \
103
+ -e DEMO_PASSWORD=demo-password \
104
+ proofrun:ci /monitors/resilient.yaml --validate
@@ -0,0 +1,175 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ quality:
13
+ name: Quality & Tests
14
+ runs-on: ubuntu-24.04
15
+ steps:
16
+ - name: Checkout repository
17
+ uses: actions/checkout@v7
18
+
19
+ - name: Set up Python
20
+ uses: actions/setup-python@v7
21
+ with:
22
+ python-version: "3.11"
23
+
24
+ - name: Set up uv
25
+ uses: astral-sh/setup-uv@v7
26
+ with:
27
+ enable-cache: true
28
+ github-token: ${{ secrets.GITHUB_TOKEN }}
29
+
30
+ - name: Install dependencies
31
+ run: make install
32
+
33
+ - name: Run code quality checks
34
+ run: make check
35
+
36
+ - name: Run integration scenarios (local demo API, no network)
37
+ run: make integration
38
+
39
+ build:
40
+ name: Build Package
41
+ runs-on: ubuntu-24.04
42
+ needs: quality
43
+ steps:
44
+ - name: Checkout repository
45
+ uses: actions/checkout@v7
46
+
47
+ - name: Set up Python
48
+ uses: actions/setup-python@v7
49
+ with:
50
+ python-version: "3.11"
51
+
52
+ - name: Set up uv
53
+ uses: astral-sh/setup-uv@v7
54
+ with:
55
+ enable-cache: true
56
+ github-token: ${{ secrets.GITHUB_TOKEN }}
57
+
58
+ - name: Verify tag matches package version
59
+ run: |
60
+ TAG_VERSION="${GITHUB_REF_NAME#v}"
61
+ PKG_VERSION="$(grep -m1 '^version = ' pyproject.toml | cut -d'"' -f2)"
62
+ echo "tag: ${TAG_VERSION} pyproject: ${PKG_VERSION}"
63
+ if [ "${TAG_VERSION}" != "${PKG_VERSION}" ]; then
64
+ echo "::error::Tag v${TAG_VERSION} does not match pyproject version ${PKG_VERSION}"
65
+ exit 1
66
+ fi
67
+
68
+ - name: Build distributions
69
+ run: make build
70
+
71
+ - name: Install the built packages in a clean environment
72
+ run: make dist-smoke
73
+
74
+ - name: Store distributions
75
+ uses: actions/upload-artifact@v7
76
+ with:
77
+ name: package-distributions
78
+ path: dist/
79
+
80
+ publish-to-pypi:
81
+ name: Publish to PyPI
82
+ runs-on: ubuntu-24.04
83
+ needs: build
84
+ environment: release
85
+ permissions:
86
+ id-token: write
87
+ steps:
88
+ - name: Download distributions
89
+ uses: actions/download-artifact@v8
90
+ with:
91
+ name: package-distributions
92
+ path: dist/
93
+
94
+ - name: Publish to PyPI
95
+ uses: pypa/gh-action-pypi-publish@release/v1
96
+
97
+ publish-docker:
98
+ name: Publish Docker Image
99
+ runs-on: ubuntu-24.04
100
+ needs: build
101
+ permissions:
102
+ contents: read
103
+ packages: write
104
+ steps:
105
+ - name: Checkout repository
106
+ uses: actions/checkout@v7
107
+
108
+ - name: Set up QEMU
109
+ uses: docker/setup-qemu-action@v4
110
+
111
+ - name: Set up Docker Buildx
112
+ uses: docker/setup-buildx-action@v4
113
+
114
+ - name: Build image for smoke test
115
+ uses: docker/build-push-action@v7
116
+ with:
117
+ context: .
118
+ load: true
119
+ tags: proofrun:smoke
120
+ cache-from: type=gha
121
+ cache-to: type=gha,mode=max
122
+
123
+ - name: Smoke test image
124
+ run: |
125
+ TAG_VERSION="${GITHUB_REF_NAME#v}"
126
+ OUTPUT="$(docker run --rm proofrun:smoke --version)"
127
+ echo "${OUTPUT}"
128
+ echo "${OUTPUT}" | grep -qxF "Proofrun version ${TAG_VERSION}"
129
+
130
+ - name: Log in to GitHub Container Registry
131
+ uses: docker/login-action@v4
132
+ with:
133
+ registry: ghcr.io
134
+ username: ${{ github.actor }}
135
+ password: ${{ secrets.GITHUB_TOKEN }}
136
+
137
+ - name: Generate image tags and labels
138
+ id: meta
139
+ uses: docker/metadata-action@v6
140
+ with:
141
+ images: ghcr.io/kishan-thanki/proofrun
142
+ tags: |
143
+ type=semver,pattern={{version}}
144
+ type=semver,pattern={{major}}.{{minor}}
145
+ type=raw,value=latest,enable=${{ !contains(github.ref_name, '-') }}
146
+
147
+ - name: Build and push (linux/amd64, linux/arm64)
148
+ uses: docker/build-push-action@v7
149
+ with:
150
+ context: .
151
+ platforms: linux/amd64,linux/arm64
152
+ push: true
153
+ tags: ${{ steps.meta.outputs.tags }}
154
+ labels: ${{ steps.meta.outputs.labels }}
155
+ cache-from: type=gha
156
+ cache-to: type=gha,mode=max
157
+
158
+ github-release:
159
+ name: Create GitHub Release
160
+ runs-on: ubuntu-24.04
161
+ needs: [publish-to-pypi, publish-docker]
162
+ permissions:
163
+ contents: write
164
+ steps:
165
+ - name: Download distributions
166
+ uses: actions/download-artifact@v8
167
+ with:
168
+ name: package-distributions
169
+ path: dist/
170
+
171
+ - name: Create GitHub Release
172
+ uses: softprops/action-gh-release@v3
173
+ with:
174
+ files: dist/*
175
+ generate_release_notes: true
@@ -82,3 +82,7 @@ __pypackages__/
82
82
 
83
83
 
84
84
  FUTURE.md
85
+
86
+ # downloaded archives and patches
87
+ *.zip
88
+ *.patch
@@ -0,0 +1,116 @@
1
+ # Changelog
2
+
3
+ All notable changes to Proofrun are documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Proofrun is below 1.0,
5
+ so a minor release can contain breaking changes; each one is listed under
6
+ **Breaking changes**.
7
+
8
+ ## [0.2.0]
9
+
10
+ ### Added
11
+
12
+ - **Environment variables.** `${env.NAME}` is resolved when a config file is
13
+ loaded, in any value or key, including `base_url`. A missing variable is a
14
+ configuration error that names the variable and where it is used.
15
+ - **Retries.** `retries` and `retry_delay_seconds` (per scenario or under
16
+ `global`) re-run the whole scenario before a failure counts. Results show
17
+ `Attempts: N`. Retries also work in run-once mode.
18
+ - **Thresholds.** `failure_threshold` and `recovery_threshold` count consecutive
19
+ runs before a scenario becomes `FAILING` or recovers. The defaults (`1`, `1`)
20
+ keep the previous behavior.
21
+ - **Per-scenario scheduling.** Every scenario runs on its own `interval_seconds`,
22
+ with jitter. A slow scenario does not delay another, and a scenario never
23
+ overlaps with itself. `interval_seconds` can also be set under `global`.
24
+ - **Metrics.** `--metrics-port` (and `--metrics-host`) serve
25
+ `/metrics` and `/health` in daemon mode. Metrics: `proofrun_scenario_up`,
26
+ `_runs_total`, `_failures_total`, `_duration_seconds`,
27
+ `_last_success_timestamp_seconds`, `_last_failure_timestamp_seconds`. The only
28
+ label is `scenario`. The server binds to loopback by default.
29
+ - **`--validate`.** Checks a configuration, including environment references,
30
+ without sending requests.
31
+ - **Docker image** for `linux/amd64` and `linux/arm64`, published to
32
+ `ghcr.io/kishan-thanki/proofrun` by the release pipeline (after the tests pass and
33
+ the tag matches the package version), running as a non-root user.
34
+ - **Deployment examples:** a hardened systemd unit and environment file in
35
+ `deploy/systemd/`, and `deploy/docker-compose.yaml`.
36
+ - `scenarios/resilient.yaml`, an offline example of the features above.
37
+ - A warning when `--webhook-url` or `--metrics-port` is given in run-once mode,
38
+ where they have no effect.
39
+ - Duplicate scenario names and extract variable names starting with `env.` are
40
+ rejected when the config is loaded.
41
+ - PyPI metadata: keywords, classifiers, and project URLs.
42
+
43
+ ### Changed
44
+
45
+ - The daemon is now event-driven per scenario instead of running every scenario
46
+ in lockstep. Configuration changes are picked up within about a second.
47
+ - An invalid configuration file is parsed once per change and its error is
48
+ printed once, instead of on every cycle.
49
+ - Configuration validation errors show the field location and message without
50
+ echoing the offending input, so resolved secrets cannot leak.
51
+ - Rich markup in scenario names, step names, and error text is escaped.
52
+ - `uvloop` is installed only where it is available (not on Windows), and Proofrun
53
+ falls back to the standard `asyncio` loop. `orjson`, which was never used, is no
54
+ longer a dependency. The minimum `pydantic` is now 2.7.
55
+ - The source is organized into packages by concern (`cli`, `config`, `runner`,
56
+ `monitor`, `notify`, `metrics`, plus `health`) instead of a single `core` package.
57
+ Only files moved; behavior is unchanged.
58
+ - Integration scenarios and the CI and release pipelines run against the local demo
59
+ API (`make integration`), with no dependency on a third-party host.
60
+
61
+ ### Fixed
62
+
63
+ - A failed webhook delivery printed the full webhook URL, which often contains a secret
64
+ token, and a timeout printed nothing useful. Failures now report only the reason (an
65
+ HTTP status, a timeout, or a connection error) and the scenario name.
66
+ - The daemon kept running with no valid configuration, looking alive while monitoring
67
+ nothing. An invalid configuration at startup now exits with code 1. An invalid edit
68
+ while running still keeps the last working configuration.
69
+ - The daemon was killed abruptly by `SIGTERM`, and as PID 1 in a container it never
70
+ received the signal, so `docker stop` waited and then killed it. `SIGTERM` now stops
71
+ it cleanly.
72
+ - `expect.status` accepted an empty list and codes outside 100 to 599, which can never
73
+ match a response. Both are now configuration errors.
74
+ - `--interval` and `--metrics-host` were silently ignored in run-once mode. They now
75
+ produce the same warning as `--webhook-url` and `--metrics-port`.
76
+ - A configuration with no scenarios, or a scenario with no steps, used to pass and report
77
+ success without making a request. Both are now configuration errors.
78
+ - Misspelled field names were silently ignored, so the check they were meant to
79
+ configure never ran. Unknown fields are now rejected with their location.
80
+ - Header mismatch errors no longer print the values of sensitive headers (names
81
+ containing auth, cookie, token, secret, key, password, or session), so they cannot
82
+ reach the console or webhook alerts.
83
+ - Dictionary keys that interpolate to the same name now fail the step instead of
84
+ silently dropping one of them.
85
+ - Scenarios that ran at the same time shared one HTTP client, so a run could clear
86
+ or read another run's cookies. Every run now has its own client.
87
+ - Removed stale `proof` naming (badges, example headers and query values, a hard-coded
88
+ User-Agent version, and the fallback package version).
89
+
90
+ ### Breaking changes
91
+
92
+ - **A daemon with an invalid configuration at startup now exits with code 1** instead of
93
+ waiting for the file to be fixed. Under systemd or Docker, a restart policy will keep
94
+ retrying until the file is valid.
95
+ - **Configuration validation is strict.** A file with a misspelled or unknown field, no
96
+ scenarios, or a scenario without steps now fails to load. Run `proofrun --validate`
97
+ on your files before upgrading.
98
+ - **The webhook environment variable is `PROOFRUN_WEBHOOK_URL`.** `PROOF_WEBHOOK_URL`
99
+ is no longer read, and there is no alias. If you set the old name, alerts stop
100
+ until you rename it.
101
+ - **`interval_seconds` is now per scenario.** Before, all scenarios ran together on
102
+ the smallest interval in the file. Scenarios with different intervals now run at
103
+ different rates. `--interval N` still runs everything every N seconds.
104
+ - Configuration validation error text has a new format.
105
+ - `${env.NAME}` is resolved at load time, so a config that contained that literal text
106
+ needs the variable to exist (it would previously have failed at run time).
107
+ - Python imports changed. `proofrun.core` no longer exists; for example
108
+ `proofrun.core.daemon.Daemon` is now `proofrun.monitor.daemon.Daemon`, and
109
+ `proofrun.cli.execute_config` is replaced by `run_once` in `proofrun.cli.commands`.
110
+ The command line is the supported interface; there is no stable Python API yet.
111
+
112
+ ## [0.1.1]
113
+
114
+ Initial public release: YAML scenarios, multi-step requests with JSONPath
115
+ extraction, status, latency, header, and JSON Schema assertions, run-once and
116
+ daemon modes, webhook alerts on health changes, and hot configuration reload.
@@ -0,0 +1,31 @@
1
+ # syntax=docker/dockerfile:1
2
+
3
+ FROM python:3.12.15-alpine AS build
4
+
5
+ RUN apk upgrade --no-cache
6
+
7
+ ENV PIP_DISABLE_PIP_VERSION_CHECK=1 \
8
+ PIP_NO_CACHE_DIR=1
9
+
10
+ WORKDIR /src
11
+ COPY pyproject.toml README.md LICENSE ./
12
+ COPY src ./src
13
+
14
+ RUN python -m venv /opt/venv \
15
+ && /opt/venv/bin/pip install .
16
+
17
+ FROM python:3.12.15-alpine
18
+
19
+ COPY --from=build /opt/venv /opt/venv
20
+
21
+ RUN apk upgrade --no-cache \
22
+ && adduser -S -D -H -u 10001 -s /bin/false proofrun
23
+
24
+ ENV PATH="/opt/venv/bin:${PATH}" \
25
+ PYTHONUNBUFFERED=1
26
+
27
+ USER proofrun
28
+ WORKDIR /monitors
29
+
30
+ ENTRYPOINT ["proofrun"]
31
+ CMD ["--help"]
@@ -0,0 +1,89 @@
1
+ PYTHON ?= python3
2
+
3
+ .PHONY: install test coverage coverage-html lint format format-check typecheck check \
4
+ serve integration build dist-smoke clean full
5
+
6
+ full: clean install check build
7
+
8
+ install:
9
+ uv sync --group dev
10
+
11
+ test:
12
+ uv run pytest -q
13
+
14
+ coverage:
15
+ uv run pytest -q --cov=proofrun --cov-branch \
16
+ --cov-report=term-missing \
17
+ --cov-fail-under=100
18
+
19
+ coverage-html:
20
+ uv run pytest -q --cov=proofrun --cov-branch \
21
+ --cov-report=html
22
+ @echo "Coverage report generated: htmlcov/index.html"
23
+
24
+ lint:
25
+ uv run ruff check src/ tests/
26
+
27
+ format:
28
+ uv run ruff format src/ tests/
29
+
30
+ format-check:
31
+ uv run ruff format --check src/ tests/
32
+ uv run ruff check src/ tests/
33
+
34
+ typecheck:
35
+ uv run pyright
36
+
37
+ check: lint format-check typecheck coverage
38
+
39
+ serve:
40
+ $(PYTHON) scenarios/server.py
41
+
42
+ integration:
43
+ @$(PYTHON) scenarios/server.py & \
44
+ SERVER_PID=$$!; \
45
+ trap 'kill $$SERVER_PID 2>/dev/null || true' EXIT; \
46
+ up=0; \
47
+ for i in $$(seq 1 50); do \
48
+ $(PYTHON) -c "import urllib.request as u; u.urlopen('http://127.0.0.1:8099/health')" \
49
+ >/dev/null 2>&1 && up=1 && break; \
50
+ sleep 0.2; \
51
+ done; \
52
+ if [ $$up -ne 1 ]; then \
53
+ echo "The demo API did not start on 127.0.0.1:8099. Is '$(PYTHON)' installed and the port free?"; \
54
+ echo "Try: make integration PYTHON=/path/to/python3"; \
55
+ exit 1; \
56
+ fi; \
57
+ export DEMO_PASSWORD=demo-password; \
58
+ status=0; \
59
+ for name in profile auth chain crud resilient; do \
60
+ echo "==> scenarios/$$name.yaml"; \
61
+ uv run proofrun scenarios/$$name.yaml --validate >/dev/null || status=1; \
62
+ uv run proofrun scenarios/$$name.yaml || status=1; \
63
+ done; \
64
+ exit $$status
65
+
66
+ dist-smoke:
67
+ @set -e; tmp=$$(mktemp -d); trap 'rm -rf "$$tmp"' EXIT; \
68
+ for pkg in dist/*.whl dist/*.tar.gz; do \
69
+ echo "==> installing $$pkg in a clean environment"; \
70
+ $(PYTHON) -m venv "$$tmp/venv"; \
71
+ "$$tmp/venv/bin/pip" install --quiet "$$pkg"; \
72
+ "$$tmp/venv/bin/proofrun" --version; \
73
+ DEMO_PASSWORD=smoke "$$tmp/venv/bin/proofrun" scenarios/resilient.yaml --validate >/dev/null; \
74
+ rm -rf "$$tmp/venv"; \
75
+ done
76
+
77
+ build:
78
+ uv build
79
+
80
+ clean:
81
+ rm -rf dist/ \
82
+ .ruff_cache/ \
83
+ .pytest_cache/ \
84
+ .pyright_cache/ \
85
+ .coverage \
86
+ .coverage.* \
87
+ htmlcov/ \
88
+ __pycache__/ \
89
+ *.egg-info/