revtrend 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.
- revtrend-0.1.0/LICENSE +21 -0
- revtrend-0.1.0/PKG-INFO +136 -0
- revtrend-0.1.0/README.md +105 -0
- revtrend-0.1.0/pyproject.toml +108 -0
- revtrend-0.1.0/pyproject.toml.orig +121 -0
- revtrend-0.1.0/src/revtrend/__init__.py +0 -0
- revtrend-0.1.0/src/revtrend/api.py +522 -0
- revtrend-0.1.0/src/revtrend/auth.py +169 -0
- revtrend-0.1.0/src/revtrend/cli.py +352 -0
- revtrend-0.1.0/src/revtrend/config.py +183 -0
- revtrend-0.1.0/src/revtrend/db.py +82 -0
- revtrend-0.1.0/src/revtrend/migrations/001_initial.sql +21 -0
- revtrend-0.1.0/src/revtrend/migrations/002_submitted_name.sql +2 -0
- revtrend-0.1.0/src/revtrend/migrations/__init__.py +0 -0
- revtrend-0.1.0/src/revtrend/mirror.py +310 -0
- revtrend-0.1.0/src/revtrend/observability.py +96 -0
- revtrend-0.1.0/src/revtrend/relay.py +65 -0
- revtrend-0.1.0/src/revtrend/server.py +145 -0
- revtrend-0.1.0/src/revtrend/store.py +158 -0
revtrend-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Simon Holesch
|
|
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.
|
revtrend-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: revtrend
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Track numeric metrics per git commit and visualize trends in Grafana
|
|
5
|
+
Author: Simon Holesch
|
|
6
|
+
Author-email: Simon Holesch <simon@holesch.de>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Framework :: FastAPI
|
|
11
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
19
|
+
Classifier: Topic :: System :: Monitoring
|
|
20
|
+
Requires-Dist: fastapi
|
|
21
|
+
Requires-Dist: httpx
|
|
22
|
+
Requires-Dist: prometheus-client>=0.26.0
|
|
23
|
+
Requires-Dist: pydantic>=2.14.3
|
|
24
|
+
Requires-Dist: pyjwt[crypto]
|
|
25
|
+
Requires-Dist: uvicorn
|
|
26
|
+
Requires-Python: >=3.11
|
|
27
|
+
Project-URL: Homepage, https://github.com/holesch/revtrend
|
|
28
|
+
Project-URL: Source, https://github.com/holesch/revtrend
|
|
29
|
+
Project-URL: Issues, https://github.com/holesch/revtrend/issues
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# revtrend
|
|
33
|
+
|
|
34
|
+
Track numeric metrics per git commit (image size, binary size, test duration,
|
|
35
|
+
coverage, …) and visualize them over time in Grafana.
|
|
36
|
+
|
|
37
|
+
Data is keyed by commit SHA. Which commits belong to a view is answered from
|
|
38
|
+
a bare mirror of the project's repository: the first-parent history of the
|
|
39
|
+
selected ref, compared against a base ref.
|
|
40
|
+
|
|
41
|
+
## Service
|
|
42
|
+
|
|
43
|
+
`revtrend-server --config /etc/revtrend/config.toml`, see
|
|
44
|
+
[contrib/config.example.toml](https://github.com/holesch/revtrend/blob/master/contrib/config.example.toml) and
|
|
45
|
+
[contrib/revtrend.service](https://github.com/holesch/revtrend/blob/master/contrib/revtrend.service).
|
|
46
|
+
|
|
47
|
+
All `/api/v1` endpoints require a bearer JWT from one of the configured
|
|
48
|
+
issuers. Roles per project: `reader` < `writer` < `admin`.
|
|
49
|
+
|
|
50
|
+
| Endpoint | Role | |
|
|
51
|
+
|---|---|---|
|
|
52
|
+
| `POST /api/v1/projects/{project}/measurements` | writer | ingest one run for a commit |
|
|
53
|
+
| `GET /api/v1/projects/{project}/series` | reader | flat rows for Grafana (`metric`, `ref`, `base`, `from`, `to`, `labels`, `agg`) |
|
|
54
|
+
| `GET /api/v1/projects/{project}/compare` | reader | head vs. nearest measured commit from the merge base with `base` |
|
|
55
|
+
| `GET /api/v1/projects` | any | projects the caller can read |
|
|
56
|
+
| `GET /api/v1/projects/{project}/refs` | reader | branches (`active_since`, `match`) |
|
|
57
|
+
| `GET /api/v1/projects/{project}/metrics` | reader | metric names and label values |
|
|
58
|
+
| `DELETE /api/v1/projects/{project}/measurements` | admin | delete by `run_id` or `metric` |
|
|
59
|
+
| `GET /auth/cli/{config,callback,poll}` | none | PKCE code relay for the CLI |
|
|
60
|
+
| `GET /healthz`, `GET /metrics` | none | health and Prometheus metrics |
|
|
61
|
+
|
|
62
|
+
`/metrics` is unauthenticated; don't expose it through the reverse proxy.
|
|
63
|
+
|
|
64
|
+
Ingest example:
|
|
65
|
+
|
|
66
|
+
```sh
|
|
67
|
+
curl -fsS -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
|
|
68
|
+
--data '{"sha": "<40 hex>", "run_id": "'"$BUILD_URL"'", "metrics": [
|
|
69
|
+
{"name": "image.size_bytes", "value": 81234432,
|
|
70
|
+
"labels": {"machine": "amd64", "image": "core-image"}}]}' \
|
|
71
|
+
https://revtrend.example/api/v1/projects/myproject/measurements
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The measurement `source` (`ci` or `manual`) is derived from the token issuer,
|
|
75
|
+
never from the request. Per commit, CI runs take precedence over manual runs.
|
|
76
|
+
|
|
77
|
+
Each measurement records the submitter as `<issuer name>:<sub>`, the stable
|
|
78
|
+
OIDC identifier. For a readable audit trail, set `display_claims` on an issuer
|
|
79
|
+
(e.g. `["preferred_username", "name"]`): the first claim present in the token
|
|
80
|
+
is stored as `submitted_name`.
|
|
81
|
+
|
|
82
|
+
## CLI
|
|
83
|
+
|
|
84
|
+
```sh
|
|
85
|
+
pipx install revtrend
|
|
86
|
+
export REVTREND_URL=https://revtrend.example
|
|
87
|
+
|
|
88
|
+
revtrend login
|
|
89
|
+
revtrend push --project myproject --sha HEAD metrics.json
|
|
90
|
+
revtrend compare --project myproject --head HEAD --base release/1.0
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
`login` prints a URL to open in any browser, also from an ssh session: the
|
|
94
|
+
service receives the login redirect and relays the authorization code to the
|
|
95
|
+
CLI, which redeems it with its PKCE verifier. Tokens are cached in
|
|
96
|
+
`~/.cache/revtrend/sessions.json` and refreshed automatically.
|
|
97
|
+
`$REVTREND_TOKEN` overrides the cached session.
|
|
98
|
+
|
|
99
|
+
`push` takes a JSON array of metrics (`-` reads stdin):
|
|
100
|
+
|
|
101
|
+
```json
|
|
102
|
+
[{"name": "image.size_bytes", "value": 81234432,
|
|
103
|
+
"labels": {"machine": "amd64", "image": "core-image"}}]
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
`--sha` and `--head` are resolved in the current repository, so backfilling
|
|
107
|
+
means checking out an old commit, measuring and pushing. The commit must exist
|
|
108
|
+
in the remote. The run id defaults to `manual-<user>-<timestamp>`; pass
|
|
109
|
+
`--run-id` to make a retry idempotent.
|
|
110
|
+
|
|
111
|
+
`compare` prints head vs. baseline per series, or the raw response with
|
|
112
|
+
`--json`.
|
|
113
|
+
|
|
114
|
+
## Development
|
|
115
|
+
|
|
116
|
+
```sh
|
|
117
|
+
uv sync
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Tests:
|
|
121
|
+
|
|
122
|
+
```sh
|
|
123
|
+
uv run pytest
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Static checks:
|
|
127
|
+
|
|
128
|
+
```sh
|
|
129
|
+
uv run ruff check
|
|
130
|
+
uv run ruff format --check
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Entry points:
|
|
134
|
+
|
|
135
|
+
- `revtrend-server` — HTTP API (FastAPI + uvicorn)
|
|
136
|
+
- `revtrend` — CLI for pushing measurements and comparing commits
|
revtrend-0.1.0/README.md
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# revtrend
|
|
2
|
+
|
|
3
|
+
Track numeric metrics per git commit (image size, binary size, test duration,
|
|
4
|
+
coverage, …) and visualize them over time in Grafana.
|
|
5
|
+
|
|
6
|
+
Data is keyed by commit SHA. Which commits belong to a view is answered from
|
|
7
|
+
a bare mirror of the project's repository: the first-parent history of the
|
|
8
|
+
selected ref, compared against a base ref.
|
|
9
|
+
|
|
10
|
+
## Service
|
|
11
|
+
|
|
12
|
+
`revtrend-server --config /etc/revtrend/config.toml`, see
|
|
13
|
+
[contrib/config.example.toml](https://github.com/holesch/revtrend/blob/master/contrib/config.example.toml) and
|
|
14
|
+
[contrib/revtrend.service](https://github.com/holesch/revtrend/blob/master/contrib/revtrend.service).
|
|
15
|
+
|
|
16
|
+
All `/api/v1` endpoints require a bearer JWT from one of the configured
|
|
17
|
+
issuers. Roles per project: `reader` < `writer` < `admin`.
|
|
18
|
+
|
|
19
|
+
| Endpoint | Role | |
|
|
20
|
+
|---|---|---|
|
|
21
|
+
| `POST /api/v1/projects/{project}/measurements` | writer | ingest one run for a commit |
|
|
22
|
+
| `GET /api/v1/projects/{project}/series` | reader | flat rows for Grafana (`metric`, `ref`, `base`, `from`, `to`, `labels`, `agg`) |
|
|
23
|
+
| `GET /api/v1/projects/{project}/compare` | reader | head vs. nearest measured commit from the merge base with `base` |
|
|
24
|
+
| `GET /api/v1/projects` | any | projects the caller can read |
|
|
25
|
+
| `GET /api/v1/projects/{project}/refs` | reader | branches (`active_since`, `match`) |
|
|
26
|
+
| `GET /api/v1/projects/{project}/metrics` | reader | metric names and label values |
|
|
27
|
+
| `DELETE /api/v1/projects/{project}/measurements` | admin | delete by `run_id` or `metric` |
|
|
28
|
+
| `GET /auth/cli/{config,callback,poll}` | none | PKCE code relay for the CLI |
|
|
29
|
+
| `GET /healthz`, `GET /metrics` | none | health and Prometheus metrics |
|
|
30
|
+
|
|
31
|
+
`/metrics` is unauthenticated; don't expose it through the reverse proxy.
|
|
32
|
+
|
|
33
|
+
Ingest example:
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
curl -fsS -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
|
|
37
|
+
--data '{"sha": "<40 hex>", "run_id": "'"$BUILD_URL"'", "metrics": [
|
|
38
|
+
{"name": "image.size_bytes", "value": 81234432,
|
|
39
|
+
"labels": {"machine": "amd64", "image": "core-image"}}]}' \
|
|
40
|
+
https://revtrend.example/api/v1/projects/myproject/measurements
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The measurement `source` (`ci` or `manual`) is derived from the token issuer,
|
|
44
|
+
never from the request. Per commit, CI runs take precedence over manual runs.
|
|
45
|
+
|
|
46
|
+
Each measurement records the submitter as `<issuer name>:<sub>`, the stable
|
|
47
|
+
OIDC identifier. For a readable audit trail, set `display_claims` on an issuer
|
|
48
|
+
(e.g. `["preferred_username", "name"]`): the first claim present in the token
|
|
49
|
+
is stored as `submitted_name`.
|
|
50
|
+
|
|
51
|
+
## CLI
|
|
52
|
+
|
|
53
|
+
```sh
|
|
54
|
+
pipx install revtrend
|
|
55
|
+
export REVTREND_URL=https://revtrend.example
|
|
56
|
+
|
|
57
|
+
revtrend login
|
|
58
|
+
revtrend push --project myproject --sha HEAD metrics.json
|
|
59
|
+
revtrend compare --project myproject --head HEAD --base release/1.0
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`login` prints a URL to open in any browser, also from an ssh session: the
|
|
63
|
+
service receives the login redirect and relays the authorization code to the
|
|
64
|
+
CLI, which redeems it with its PKCE verifier. Tokens are cached in
|
|
65
|
+
`~/.cache/revtrend/sessions.json` and refreshed automatically.
|
|
66
|
+
`$REVTREND_TOKEN` overrides the cached session.
|
|
67
|
+
|
|
68
|
+
`push` takes a JSON array of metrics (`-` reads stdin):
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
[{"name": "image.size_bytes", "value": 81234432,
|
|
72
|
+
"labels": {"machine": "amd64", "image": "core-image"}}]
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
`--sha` and `--head` are resolved in the current repository, so backfilling
|
|
76
|
+
means checking out an old commit, measuring and pushing. The commit must exist
|
|
77
|
+
in the remote. The run id defaults to `manual-<user>-<timestamp>`; pass
|
|
78
|
+
`--run-id` to make a retry idempotent.
|
|
79
|
+
|
|
80
|
+
`compare` prints head vs. baseline per series, or the raw response with
|
|
81
|
+
`--json`.
|
|
82
|
+
|
|
83
|
+
## Development
|
|
84
|
+
|
|
85
|
+
```sh
|
|
86
|
+
uv sync
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Tests:
|
|
90
|
+
|
|
91
|
+
```sh
|
|
92
|
+
uv run pytest
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Static checks:
|
|
96
|
+
|
|
97
|
+
```sh
|
|
98
|
+
uv run ruff check
|
|
99
|
+
uv run ruff format --check
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Entry points:
|
|
103
|
+
|
|
104
|
+
- `revtrend-server` — HTTP API (FastAPI + uvicorn)
|
|
105
|
+
- `revtrend` — CLI for pushing measurements and comparing commits
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["uv_build>=0.13.7,<0.14"]
|
|
3
|
+
build-backend = "uv_build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "revtrend"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Track numeric metrics per git commit and visualize trends in Grafana"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = ["LICENSE"]
|
|
12
|
+
requires-python = ">=3.11"
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Development Status :: 3 - Alpha",
|
|
15
|
+
"Framework :: FastAPI",
|
|
16
|
+
"Operating System :: POSIX :: Linux",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
19
|
+
"Programming Language :: Python :: 3.11",
|
|
20
|
+
"Programming Language :: Python :: 3.12",
|
|
21
|
+
"Programming Language :: Python :: 3.13",
|
|
22
|
+
"Programming Language :: Python :: 3.14",
|
|
23
|
+
"Topic :: Software Development :: Quality Assurance",
|
|
24
|
+
"Topic :: System :: Monitoring",
|
|
25
|
+
]
|
|
26
|
+
dependencies = [
|
|
27
|
+
"fastapi",
|
|
28
|
+
"httpx",
|
|
29
|
+
"prometheus-client>=0.26.0",
|
|
30
|
+
"pydantic>=2.14.3",
|
|
31
|
+
"PyJWT[crypto]",
|
|
32
|
+
"uvicorn",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
[[project.authors]]
|
|
36
|
+
name = "Simon Holesch"
|
|
37
|
+
email = "simon@holesch.de"
|
|
38
|
+
|
|
39
|
+
[project.urls]
|
|
40
|
+
Homepage = "https://github.com/holesch/revtrend"
|
|
41
|
+
Source = "https://github.com/holesch/revtrend"
|
|
42
|
+
Issues = "https://github.com/holesch/revtrend/issues"
|
|
43
|
+
|
|
44
|
+
[project.scripts]
|
|
45
|
+
revtrend = "revtrend.cli:main"
|
|
46
|
+
revtrend-server = "revtrend.server:main"
|
|
47
|
+
|
|
48
|
+
[dependency-groups]
|
|
49
|
+
dev = [
|
|
50
|
+
"pytest>=9.2.0",
|
|
51
|
+
"pytest-asyncio>=1.4.1.post1",
|
|
52
|
+
"ruff==0.14.7",
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
[tool.pytest.ini_options]
|
|
56
|
+
testpaths = ["tests"]
|
|
57
|
+
asyncio_mode = "auto"
|
|
58
|
+
asyncio_default_fixture_loop_scope = "function"
|
|
59
|
+
|
|
60
|
+
[tool.ruff.lint]
|
|
61
|
+
select = [
|
|
62
|
+
"F",
|
|
63
|
+
"E",
|
|
64
|
+
"W",
|
|
65
|
+
"I",
|
|
66
|
+
"N",
|
|
67
|
+
"UP",
|
|
68
|
+
"ASYNC",
|
|
69
|
+
"S",
|
|
70
|
+
"B",
|
|
71
|
+
"A",
|
|
72
|
+
"C4",
|
|
73
|
+
"ISC",
|
|
74
|
+
"LOG",
|
|
75
|
+
"G",
|
|
76
|
+
"PIE",
|
|
77
|
+
"T20",
|
|
78
|
+
"PT",
|
|
79
|
+
"RSE",
|
|
80
|
+
"SIM",
|
|
81
|
+
"TID",
|
|
82
|
+
"ARG",
|
|
83
|
+
"PTH",
|
|
84
|
+
"PL",
|
|
85
|
+
"FLY",
|
|
86
|
+
"FURB",
|
|
87
|
+
"RUF",
|
|
88
|
+
]
|
|
89
|
+
ignore = [
|
|
90
|
+
"E501",
|
|
91
|
+
"PLW2901",
|
|
92
|
+
"PLR0402",
|
|
93
|
+
"PTH123",
|
|
94
|
+
"S603",
|
|
95
|
+
"SIM108",
|
|
96
|
+
]
|
|
97
|
+
|
|
98
|
+
[tool.ruff.lint.per-file-ignores]
|
|
99
|
+
"tests/**.py" = [
|
|
100
|
+
"PLR2004",
|
|
101
|
+
"S101",
|
|
102
|
+
"S607",
|
|
103
|
+
"ARG001",
|
|
104
|
+
"PLR0913",
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
[tool.ruff.lint.flake8-tidy-imports]
|
|
108
|
+
ban-relative-imports = "all"
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["uv_build>=0.13.7,<0.14"]
|
|
3
|
+
build-backend = "uv_build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "revtrend"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Track numeric metrics per git commit and visualize trends in Grafana"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = ["LICENSE"]
|
|
12
|
+
authors = [{ name = "Simon Holesch", email = "simon@holesch.de" }]
|
|
13
|
+
requires-python = ">=3.11"
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Framework :: FastAPI",
|
|
17
|
+
"Operating System :: POSIX :: Linux",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
20
|
+
"Programming Language :: Python :: 3.11",
|
|
21
|
+
"Programming Language :: Python :: 3.12",
|
|
22
|
+
"Programming Language :: Python :: 3.13",
|
|
23
|
+
"Programming Language :: Python :: 3.14",
|
|
24
|
+
"Topic :: Software Development :: Quality Assurance",
|
|
25
|
+
"Topic :: System :: Monitoring",
|
|
26
|
+
]
|
|
27
|
+
dependencies = [
|
|
28
|
+
"fastapi",
|
|
29
|
+
"httpx",
|
|
30
|
+
"prometheus-client>=0.26.0",
|
|
31
|
+
"pydantic>=2.14.3",
|
|
32
|
+
"PyJWT[crypto]",
|
|
33
|
+
"uvicorn",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[project.urls]
|
|
37
|
+
Homepage = "https://github.com/holesch/revtrend"
|
|
38
|
+
Source = "https://github.com/holesch/revtrend"
|
|
39
|
+
Issues = "https://github.com/holesch/revtrend/issues"
|
|
40
|
+
|
|
41
|
+
[project.scripts]
|
|
42
|
+
revtrend = "revtrend.cli:main"
|
|
43
|
+
revtrend-server = "revtrend.server:main"
|
|
44
|
+
|
|
45
|
+
[dependency-groups]
|
|
46
|
+
dev = [
|
|
47
|
+
"pytest>=9.2.0",
|
|
48
|
+
"pytest-asyncio>=1.4.1.post1",
|
|
49
|
+
"ruff==0.14.7",
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
[tool.pytest.ini_options]
|
|
53
|
+
testpaths = ["tests"]
|
|
54
|
+
asyncio_mode = "auto"
|
|
55
|
+
asyncio_default_fixture_loop_scope = "function"
|
|
56
|
+
|
|
57
|
+
[tool.ruff.lint]
|
|
58
|
+
select = [
|
|
59
|
+
"F", # Pyflakes
|
|
60
|
+
"E", "W", # pycodestyle
|
|
61
|
+
"I", # isort
|
|
62
|
+
"N", # pep8-naming
|
|
63
|
+
"UP", # pyupgrade
|
|
64
|
+
"ASYNC", # flake8-async
|
|
65
|
+
"S", # flake8-bandit
|
|
66
|
+
"B", # flake8-bugbear
|
|
67
|
+
"A", # flake8-builtins
|
|
68
|
+
"C4", # flake8-comprehensions
|
|
69
|
+
"ISC", # flake8-implicit-str-concat
|
|
70
|
+
"LOG", # flake8-logging
|
|
71
|
+
"G", # flake8-logging-format
|
|
72
|
+
"PIE", # flake8-pie
|
|
73
|
+
"T20", # flake8-print
|
|
74
|
+
"PT", # flake8-pytest-style
|
|
75
|
+
"RSE", # flake8-raise
|
|
76
|
+
"SIM", # flake8-simplify
|
|
77
|
+
"TID", # flake8-tidy-imports
|
|
78
|
+
"ARG", # flake8-unused-arguments
|
|
79
|
+
"PTH", # flake8-use-pathlib
|
|
80
|
+
"PL", # Pylint
|
|
81
|
+
"FLY", # flynt
|
|
82
|
+
"FURB", # refurb
|
|
83
|
+
"RUF", # Ruff-specific rules
|
|
84
|
+
]
|
|
85
|
+
ignore = [
|
|
86
|
+
# "Line too long"
|
|
87
|
+
# -> ruff format handles code, long strings are fine
|
|
88
|
+
"E501",
|
|
89
|
+
# "for loop variable overwritten by assignment target"
|
|
90
|
+
"PLW2901",
|
|
91
|
+
# "Use `from x import y` in lieu of alias"
|
|
92
|
+
# -> style: absolute module imports only, aliased where necessary
|
|
93
|
+
"PLR0402",
|
|
94
|
+
# "open() should be replaced by Path.open()"
|
|
95
|
+
# -> creating a Path object just to open a file is overkill
|
|
96
|
+
"PTH123",
|
|
97
|
+
# "subprocess call: check for execution of untrusted input"
|
|
98
|
+
# -> false positives, git is called with argument lists
|
|
99
|
+
"S603",
|
|
100
|
+
# "Use ternary operator instead of if-else-block"
|
|
101
|
+
# -> can make the code less readable
|
|
102
|
+
"SIM108",
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
[tool.ruff.lint.per-file-ignores]
|
|
106
|
+
"tests/**.py" = [
|
|
107
|
+
# "Magic value used in comparison"
|
|
108
|
+
"PLR2004",
|
|
109
|
+
# "Use of assert detected"
|
|
110
|
+
"S101",
|
|
111
|
+
# "Starting a process with a partial executable path"
|
|
112
|
+
"S607",
|
|
113
|
+
# "Unused function argument"
|
|
114
|
+
# -> fixtures requested for their side effects
|
|
115
|
+
"ARG001",
|
|
116
|
+
# "Too many arguments in function definition"
|
|
117
|
+
"PLR0913",
|
|
118
|
+
]
|
|
119
|
+
|
|
120
|
+
[tool.ruff.lint.flake8-tidy-imports]
|
|
121
|
+
ban-relative-imports = "all"
|
|
File without changes
|