kuma-stats 0.3.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.
- kuma_stats-0.3.0/.env.example +9 -0
- kuma_stats-0.3.0/.github/workflows/ci.yml +40 -0
- kuma_stats-0.3.0/.github/workflows/live-kuma.yml +252 -0
- kuma_stats-0.3.0/.gitignore +12 -0
- kuma_stats-0.3.0/CHANGELOG.md +42 -0
- kuma_stats-0.3.0/CONTRIBUTING.md +24 -0
- kuma_stats-0.3.0/LICENSE +21 -0
- kuma_stats-0.3.0/Makefile +32 -0
- kuma_stats-0.3.0/PKG-INFO +197 -0
- kuma_stats-0.3.0/README.md +157 -0
- kuma_stats-0.3.0/RESEARCH.md +68 -0
- kuma_stats-0.3.0/SECURITY.md +14 -0
- kuma_stats-0.3.0/docs/RELEASING.md +155 -0
- kuma_stats-0.3.0/pyproject.toml +85 -0
- kuma_stats-0.3.0/renovate.json +61 -0
- kuma_stats-0.3.0/scripts/bump-version.sh +142 -0
- kuma_stats-0.3.0/scripts/prep-release.sh +67 -0
- kuma_stats-0.3.0/scripts/release.sh +171 -0
- kuma_stats-0.3.0/src/kuma_stats/__init__.py +3 -0
- kuma_stats-0.3.0/src/kuma_stats/__main__.py +5 -0
- kuma_stats-0.3.0/src/kuma_stats/cli.py +328 -0
- kuma_stats-0.3.0/src/kuma_stats/core/__init__.py +1 -0
- kuma_stats-0.3.0/src/kuma_stats/core/adapter.py +103 -0
- kuma_stats-0.3.0/src/kuma_stats/core/config.py +94 -0
- kuma_stats-0.3.0/src/kuma_stats/core/errors.py +44 -0
- kuma_stats-0.3.0/src/kuma_stats/core/retry.py +51 -0
- kuma_stats-0.3.0/src/kuma_stats/core/session.py +21 -0
- kuma_stats-0.3.0/src/kuma_stats/output/__init__.py +54 -0
- kuma_stats-0.3.0/src/kuma_stats/py.typed +0 -0
- kuma_stats-0.3.0/src/kuma_stats/services/__init__.py +1 -0
- kuma_stats-0.3.0/src/kuma_stats/services/monitors.py +111 -0
- kuma_stats-0.3.0/tests/integration/test_installed_cli.py +95 -0
- kuma_stats-0.3.0/tests/integration/test_live_kuma.py +136 -0
- kuma_stats-0.3.0/tests/test_cli.py +269 -0
- kuma_stats-0.3.0/tests/test_release_scripts.py +280 -0
- kuma_stats-0.3.0/uv.lock +1154 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
test:
|
|
13
|
+
runs-on: ubicloud-standard-2
|
|
14
|
+
strategy:
|
|
15
|
+
fail-fast: false
|
|
16
|
+
matrix:
|
|
17
|
+
python-version: ['3.10', '3.11', '3.12']
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v4
|
|
20
|
+
- uses: actions/setup-python@v5
|
|
21
|
+
with:
|
|
22
|
+
python-version: ${{ matrix.python-version }}
|
|
23
|
+
- run: python -m pip install --upgrade pip
|
|
24
|
+
- run: python -m pip install '.[dev]' build twine
|
|
25
|
+
- run: python -m ruff check .
|
|
26
|
+
- run: python -m mypy src/kuma_stats
|
|
27
|
+
- run: python -m pytest -q
|
|
28
|
+
- run: python -m build
|
|
29
|
+
- run: python -m twine check dist/*
|
|
30
|
+
- name: Verify wheel installation
|
|
31
|
+
run: |
|
|
32
|
+
python -m venv /tmp/wheel-venv
|
|
33
|
+
/tmp/wheel-venv/bin/python -m pip install dist/*.whl
|
|
34
|
+
/tmp/wheel-venv/bin/kuma-stats --help
|
|
35
|
+
/tmp/wheel-venv/bin/python -m kuma_stats --help
|
|
36
|
+
- name: Verify sdist installation
|
|
37
|
+
run: |
|
|
38
|
+
python -m venv /tmp/sdist-venv
|
|
39
|
+
/tmp/sdist-venv/bin/python -m pip install dist/*.tar.gz
|
|
40
|
+
/tmp/sdist-venv/bin/kuma-stats --help
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
name: Live Kuma smoke test
|
|
2
|
+
|
|
3
|
+
# Maintainer-only Docker-backed Uptime Kuma tests.
|
|
4
|
+
#
|
|
5
|
+
# Preferred entry point: comment `/run-live-tests` on a same-repository PR.
|
|
6
|
+
# The manual dispatch path is retained for the Actions UI; both paths are
|
|
7
|
+
# restricted to the repository owner.
|
|
8
|
+
on:
|
|
9
|
+
issue_comment:
|
|
10
|
+
types: [created]
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
inputs:
|
|
13
|
+
pr_number:
|
|
14
|
+
description: PR number for a PR check and result comment
|
|
15
|
+
type: string
|
|
16
|
+
required: false
|
|
17
|
+
pr_sha:
|
|
18
|
+
description: PR head SHA to test (defaults to the workflow ref SHA)
|
|
19
|
+
type: string
|
|
20
|
+
required: false
|
|
21
|
+
|
|
22
|
+
permissions:
|
|
23
|
+
contents: read
|
|
24
|
+
|
|
25
|
+
jobs:
|
|
26
|
+
prepare:
|
|
27
|
+
name: Authorize Live Kuma Tests
|
|
28
|
+
# issue_comment workflows always run from the default branch. Resolve the
|
|
29
|
+
# PR head explicitly, and verify both the initial and re-run actor.
|
|
30
|
+
if: |
|
|
31
|
+
(
|
|
32
|
+
github.event_name == 'issue_comment' &&
|
|
33
|
+
github.event.issue.pull_request &&
|
|
34
|
+
github.event.comment.body == '/run-live-tests' &&
|
|
35
|
+
github.actor == github.repository_owner &&
|
|
36
|
+
github.triggering_actor == github.repository_owner
|
|
37
|
+
) || (
|
|
38
|
+
github.event_name == 'workflow_dispatch' &&
|
|
39
|
+
github.actor == github.repository_owner &&
|
|
40
|
+
github.triggering_actor == github.repository_owner
|
|
41
|
+
)
|
|
42
|
+
runs-on: ubuntu-latest
|
|
43
|
+
permissions:
|
|
44
|
+
pull-requests: read
|
|
45
|
+
outputs:
|
|
46
|
+
pr_number: ${{ steps.pr.outputs.number }}
|
|
47
|
+
pr_sha: ${{ steps.pr.outputs.sha }}
|
|
48
|
+
|
|
49
|
+
steps:
|
|
50
|
+
- name: Restore originally authorized PR target on rerun
|
|
51
|
+
if: github.event_name == 'issue_comment' && github.run_attempt > 1
|
|
52
|
+
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
|
|
53
|
+
with:
|
|
54
|
+
name: live-kuma-target-${{ github.run_id }}
|
|
55
|
+
path: ${{ runner.temp }}/authorized-live-kuma-target
|
|
56
|
+
- name: Get PR information
|
|
57
|
+
id: pr
|
|
58
|
+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
|
59
|
+
env:
|
|
60
|
+
PR_NUMBER: ${{ inputs.pr_number }}
|
|
61
|
+
PR_SHA: ${{ inputs.pr_sha }}
|
|
62
|
+
RESTORED_TARGET: ${{ runner.temp }}/authorized-live-kuma-target/target.json
|
|
63
|
+
with:
|
|
64
|
+
script: |
|
|
65
|
+
const fs = require('node:fs');
|
|
66
|
+
let target;
|
|
67
|
+
|
|
68
|
+
if (context.eventName === 'issue_comment' && context.runAttempt > 1) {
|
|
69
|
+
target = JSON.parse(fs.readFileSync(process.env.RESTORED_TARGET, 'utf8'));
|
|
70
|
+
} else if (context.eventName === 'workflow_dispatch' && !process.env.PR_NUMBER) {
|
|
71
|
+
target = { number: '', sha: process.env.PR_SHA || context.sha };
|
|
72
|
+
} else {
|
|
73
|
+
const pullNumber = context.eventName === 'issue_comment'
|
|
74
|
+
? context.issue.number
|
|
75
|
+
: Number(process.env.PR_NUMBER);
|
|
76
|
+
const pr = await github.rest.pulls.get({
|
|
77
|
+
owner: context.repo.owner,
|
|
78
|
+
repo: context.repo.repo,
|
|
79
|
+
pull_number: pullNumber,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
if (context.eventName === 'issue_comment' && pr.data.head.repo.full_name !== pr.data.base.repo.full_name) {
|
|
83
|
+
core.setFailed('Live Kuma tests cannot run on fork PRs.');
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
target = { number: String(pr.data.number), sha: pr.data.head.sha };
|
|
88
|
+
if (process.env.PR_SHA && process.env.PR_SHA !== target.sha) {
|
|
89
|
+
core.setOutput('number', target.number);
|
|
90
|
+
core.setOutput('sha', target.sha);
|
|
91
|
+
core.setFailed('pr_sha must match the current head SHA of pr_number.');
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
core.setOutput('number', target.number);
|
|
97
|
+
core.setOutput('sha', target.sha);
|
|
98
|
+
fs.writeFileSync(`${process.env.RUNNER_TEMP}/target.json`, JSON.stringify(target));
|
|
99
|
+
- name: Save authorized PR target
|
|
100
|
+
if: github.event_name == 'issue_comment' && github.run_attempt == 1
|
|
101
|
+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
|
102
|
+
with:
|
|
103
|
+
name: live-kuma-target-${{ github.run_id }}
|
|
104
|
+
path: ${{ runner.temp }}/target.json
|
|
105
|
+
if-no-files-found: error
|
|
106
|
+
|
|
107
|
+
live-kuma:
|
|
108
|
+
name: Run Live Kuma Tests
|
|
109
|
+
needs: prepare
|
|
110
|
+
# A re-run can be initiated by another collaborator, so check the
|
|
111
|
+
# triggering actor again before executing PR-controlled code.
|
|
112
|
+
if: |
|
|
113
|
+
always() &&
|
|
114
|
+
!cancelled() &&
|
|
115
|
+
(
|
|
116
|
+
(
|
|
117
|
+
github.event_name == 'issue_comment' &&
|
|
118
|
+
needs.prepare.result == 'success' &&
|
|
119
|
+
github.actor == github.repository_owner &&
|
|
120
|
+
github.triggering_actor == github.repository_owner
|
|
121
|
+
) ||
|
|
122
|
+
(
|
|
123
|
+
github.event_name == 'workflow_dispatch' &&
|
|
124
|
+
needs.prepare.result == 'success' &&
|
|
125
|
+
github.actor == github.repository_owner &&
|
|
126
|
+
github.triggering_actor == github.repository_owner
|
|
127
|
+
)
|
|
128
|
+
)
|
|
129
|
+
runs-on: ubuntu-latest
|
|
130
|
+
timeout-minutes: 10
|
|
131
|
+
# This job executes PR-controlled code; it deliberately has no write token.
|
|
132
|
+
permissions:
|
|
133
|
+
contents: read
|
|
134
|
+
outputs:
|
|
135
|
+
pr_number: ${{ steps.meta.outputs.pr_number }}
|
|
136
|
+
pr_sha: ${{ steps.meta.outputs.pr_sha }}
|
|
137
|
+
|
|
138
|
+
steps:
|
|
139
|
+
- name: Resolve target metadata
|
|
140
|
+
id: meta
|
|
141
|
+
run: |
|
|
142
|
+
echo "pr_number=${{ needs.prepare.outputs.pr_number }}" >> "$GITHUB_OUTPUT"
|
|
143
|
+
echo "pr_sha=${{ needs.prepare.outputs.pr_sha }}" >> "$GITHUB_OUTPUT"
|
|
144
|
+
|
|
145
|
+
- uses: actions/checkout@v4
|
|
146
|
+
with:
|
|
147
|
+
ref: ${{ steps.meta.outputs.pr_sha }}
|
|
148
|
+
persist-credentials: false
|
|
149
|
+
- uses: actions/setup-python@v5
|
|
150
|
+
with:
|
|
151
|
+
python-version: '3.12'
|
|
152
|
+
- run: python -m pip install --upgrade pip
|
|
153
|
+
- run: python -m pip install '.[dev]' build
|
|
154
|
+
- run: python -m build
|
|
155
|
+
- name: Install built wheel into a clean environment
|
|
156
|
+
run: |
|
|
157
|
+
python -m venv /tmp/kuma-live-venv
|
|
158
|
+
/tmp/kuma-live-venv/bin/python -m pip install dist/*.whl
|
|
159
|
+
- name: Test installed CLI against disposable Uptime Kuma
|
|
160
|
+
env:
|
|
161
|
+
RUN_LIVE_KUMA_TESTS: '1'
|
|
162
|
+
KUMA_STATS_CLI: /tmp/kuma-live-venv/bin/kuma-stats
|
|
163
|
+
KUMA_LOG_PATH: ${{ runner.temp }}/kuma-container.log
|
|
164
|
+
run: python -m pytest -q tests/integration/test_live_kuma.py
|
|
165
|
+
- name: Upload Uptime Kuma container logs
|
|
166
|
+
if: always()
|
|
167
|
+
uses: actions/upload-artifact@v4
|
|
168
|
+
with:
|
|
169
|
+
name: kuma-container-logs
|
|
170
|
+
path: ${{ runner.temp }}/kuma-container.log
|
|
171
|
+
if-no-files-found: ignore
|
|
172
|
+
|
|
173
|
+
report:
|
|
174
|
+
name: Report Live Kuma Result
|
|
175
|
+
needs: [prepare, live-kuma]
|
|
176
|
+
if: |
|
|
177
|
+
always() &&
|
|
178
|
+
(
|
|
179
|
+
needs.live-kuma.result != 'skipped' ||
|
|
180
|
+
(
|
|
181
|
+
github.event_name == 'workflow_dispatch' &&
|
|
182
|
+
needs.prepare.result == 'failure'
|
|
183
|
+
)
|
|
184
|
+
) &&
|
|
185
|
+
(
|
|
186
|
+
(
|
|
187
|
+
github.event_name == 'issue_comment' &&
|
|
188
|
+
needs.prepare.result == 'success' &&
|
|
189
|
+
github.actor == github.repository_owner &&
|
|
190
|
+
github.triggering_actor == github.repository_owner
|
|
191
|
+
) ||
|
|
192
|
+
(
|
|
193
|
+
github.event_name == 'workflow_dispatch' &&
|
|
194
|
+
inputs.pr_number != '' &&
|
|
195
|
+
github.actor == github.repository_owner &&
|
|
196
|
+
github.triggering_actor == github.repository_owner
|
|
197
|
+
)
|
|
198
|
+
)
|
|
199
|
+
runs-on: ubuntu-latest
|
|
200
|
+
permissions:
|
|
201
|
+
checks: write
|
|
202
|
+
pull-requests: write
|
|
203
|
+
|
|
204
|
+
steps:
|
|
205
|
+
- name: Create check and comment on PR
|
|
206
|
+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
|
|
207
|
+
with:
|
|
208
|
+
script: |
|
|
209
|
+
const result = '${{ needs.live-kuma.result }}' === 'skipped'
|
|
210
|
+
? 'failure'
|
|
211
|
+
: '${{ needs.live-kuma.result }}';
|
|
212
|
+
const conclusion = result === 'success'
|
|
213
|
+
? 'success'
|
|
214
|
+
: result === 'cancelled'
|
|
215
|
+
? 'cancelled'
|
|
216
|
+
: 'failure';
|
|
217
|
+
const sha = '${{ needs.live-kuma.outputs.pr_sha }}' || '${{ needs.prepare.outputs.pr_sha }}';
|
|
218
|
+
const prNumber = Number('${{ needs.live-kuma.outputs.pr_number }}' || '${{ needs.prepare.outputs.pr_number }}');
|
|
219
|
+
const logsUrl = '${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}';
|
|
220
|
+
const title = conclusion === 'success'
|
|
221
|
+
? 'Live Kuma tests passed'
|
|
222
|
+
: conclusion === 'cancelled'
|
|
223
|
+
? 'Live Kuma tests cancelled'
|
|
224
|
+
: 'Live Kuma tests failed';
|
|
225
|
+
const body = conclusion === 'success'
|
|
226
|
+
? `✅ Live Kuma tests passed. Tested commit: \`${sha}\`. [View logs](${logsUrl})`
|
|
227
|
+
: conclusion === 'cancelled'
|
|
228
|
+
? `⚪ Live Kuma tests cancelled. Tested commit: \`${sha}\`. [View logs](${logsUrl})`
|
|
229
|
+
: `❌ Live Kuma tests failed. Tested commit: \`${sha}\`. [View logs](${logsUrl})`;
|
|
230
|
+
|
|
231
|
+
await github.rest.checks.create({
|
|
232
|
+
owner: context.repo.owner,
|
|
233
|
+
repo: context.repo.repo,
|
|
234
|
+
name: 'Live Kuma smoke test',
|
|
235
|
+
head_sha: sha,
|
|
236
|
+
status: 'completed',
|
|
237
|
+
conclusion,
|
|
238
|
+
details_url: logsUrl,
|
|
239
|
+
output: {
|
|
240
|
+
title,
|
|
241
|
+
summary: `[View live-test logs](${logsUrl})`,
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
if (Number.isFinite(prNumber) && prNumber > 0) {
|
|
246
|
+
await github.rest.issues.createComment({
|
|
247
|
+
owner: context.repo.owner,
|
|
248
|
+
repo: context.repo.repo,
|
|
249
|
+
issue_number: prNumber,
|
|
250
|
+
body,
|
|
251
|
+
});
|
|
252
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
This project follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and [Semantic Versioning](https://semver.org/).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
## [0.3.0] - 2026-07-20
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Public-release documentation, packaging metadata, CI validation, and security policy.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- Normalized Uptime Kuma errors and clarified configuration behavior.
|
|
19
|
+
- Build and package management migrated from setuptools to uv, enabling reproducible builds via a lock file. ([#23])
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- Source distributions no longer include local agent artifacts that could prevent installation. ([#25])
|
|
24
|
+
- Connection timeout and configuration-validation errors are now reliably enforced and surfaced instead of silently ignored. ([d5ad17d])
|
|
25
|
+
|
|
26
|
+
[d5ad17d]: https://github.com/crcatala/kuma-stats/commit/d5ad17d
|
|
27
|
+
[#23]: https://github.com/crcatala/kuma-stats/pull/23
|
|
28
|
+
[#25]: https://github.com/crcatala/kuma-stats/pull/25
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
## Release process
|
|
32
|
+
|
|
33
|
+
PyPI releases are immutable. Bump the version with:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
make bump # minor bump (0.2.0 → 0.3.0)
|
|
37
|
+
make bump/patch # patch bump (0.2.0 → 0.2.1)
|
|
38
|
+
make bump/major # major bump (0.2.0 → 1.0.0)
|
|
39
|
+
make bump/1.0.0 # explicit version
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
This updates `__version__` and promotes `## [Unreleased]` into a dated `## [X.Y.Z]` section. Review with `git diff`, commit, push, then use `make release-dry` before `make release`; publish the resulting `dist/*` artifacts separately with `uv run twine upload dist/*`.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in `kuma-stats`.
|
|
4
|
+
|
|
5
|
+
This is a personally maintained project. Code contributions, pull requests, and feature requests are not accepted at this time. Unsolicited pull requests may be closed without review.
|
|
6
|
+
|
|
7
|
+
## Bug reports
|
|
8
|
+
|
|
9
|
+
Bug reports are welcome when they include:
|
|
10
|
+
|
|
11
|
+
- clear reproduction steps;
|
|
12
|
+
- the `kuma-stats` version;
|
|
13
|
+
- operating system and Python version; and
|
|
14
|
+
- relevant, sanitized error output.
|
|
15
|
+
|
|
16
|
+
Please search existing issues before opening a new one. Do not include passwords, JWTs, server URLs, or other credentials in a public report.
|
|
17
|
+
|
|
18
|
+
## Security issues
|
|
19
|
+
|
|
20
|
+
Do not open a public issue for a security vulnerability. Follow the private reporting guidance in [SECURITY.md](SECURITY.md).
|
|
21
|
+
|
|
22
|
+
## Forks
|
|
23
|
+
|
|
24
|
+
You may fork and adapt this project under the terms of the [MIT License](LICENSE).
|
kuma_stats-0.3.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Christian Catalan
|
|
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.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
.PHONY: setup format lint typecheck test live-test build verify bump release-prep release release-dry
|
|
2
|
+
setup:
|
|
3
|
+
uv sync --all-extras
|
|
4
|
+
format:
|
|
5
|
+
uv run ruff format .
|
|
6
|
+
lint:
|
|
7
|
+
uv run ruff check .
|
|
8
|
+
typecheck:
|
|
9
|
+
uv run mypy src/kuma_stats
|
|
10
|
+
test:
|
|
11
|
+
uv run pytest -q
|
|
12
|
+
# Requires Docker; starts a disposable, pinned Uptime Kuma container.
|
|
13
|
+
live-test:
|
|
14
|
+
uv run pytest -q tests/integration/test_live_kuma.py
|
|
15
|
+
build:
|
|
16
|
+
uv build
|
|
17
|
+
uv run twine check dist/*
|
|
18
|
+
verify: setup lint typecheck test build
|
|
19
|
+
# Summarize changes since the last v* tag and print an LLM prompt for release notes.
|
|
20
|
+
bump:
|
|
21
|
+
./scripts/bump-version.sh
|
|
22
|
+
# Bump with explicit version or type: make bump VERSION=patch / make bump VERSION=1.2.3
|
|
23
|
+
bump/%:
|
|
24
|
+
./scripts/bump-version.sh $*
|
|
25
|
+
release-prep:
|
|
26
|
+
./scripts/prep-release.sh
|
|
27
|
+
# Preview the safeguards and commands for a GitHub release.
|
|
28
|
+
release-dry:
|
|
29
|
+
./scripts/release.sh --dry-run
|
|
30
|
+
# Validate, tag, and create a GitHub Release. PyPI publishing remains manual.
|
|
31
|
+
release:
|
|
32
|
+
./scripts/release.sh
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kuma-stats
|
|
3
|
+
Version: 0.3.0
|
|
4
|
+
Summary: Read-only CLI for Uptime Kuma monitor status, uptime, and heartbeat data
|
|
5
|
+
Project-URL: Homepage, https://github.com/crcatala/kuma-stats
|
|
6
|
+
Project-URL: Repository, https://github.com/crcatala/kuma-stats
|
|
7
|
+
Project-URL: Issues, https://github.com/crcatala/kuma-stats/issues
|
|
8
|
+
Project-URL: Security, https://github.com/crcatala/kuma-stats/security/policy
|
|
9
|
+
Author-email: Christian Catalan <crcatala@gmail.com>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: cli,monitoring,status,uptime,uptime-kuma
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Environment :: Console
|
|
15
|
+
Classifier: Intended Audience :: System Administrators
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: System :: Monitoring
|
|
23
|
+
Classifier: Topic :: Utilities
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Requires-Dist: click>=8.0
|
|
26
|
+
Requires-Dist: keyring>=24.0
|
|
27
|
+
Requires-Dist: platformdirs>=4.0
|
|
28
|
+
Requires-Dist: python-dotenv>=1.0
|
|
29
|
+
Requires-Dist: pyyaml>=6.0
|
|
30
|
+
Requires-Dist: rich>=13.0
|
|
31
|
+
Requires-Dist: tomli>=2.0; python_version < '3.11'
|
|
32
|
+
Requires-Dist: uptime-kuma-api>=1.2.1
|
|
33
|
+
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
35
|
+
Requires-Dist: mypy>=1.13; extra == 'dev'
|
|
36
|
+
Requires-Dist: pytest>=8.0; extra == 'dev'
|
|
37
|
+
Requires-Dist: ruff>=0.8; extra == 'dev'
|
|
38
|
+
Requires-Dist: twine>=5.0; extra == 'dev'
|
|
39
|
+
Description-Content-Type: text/markdown
|
|
40
|
+
|
|
41
|
+
# kuma-stats
|
|
42
|
+
|
|
43
|
+
[](https://github.com/crcatala/kuma-stats/actions/workflows/ci.yml)
|
|
44
|
+
[](https://pypi.org/project/kuma-stats/)
|
|
45
|
+
[](https://pypi.org/project/kuma-stats/)
|
|
46
|
+
[](LICENSE)
|
|
47
|
+
|
|
48
|
+
A read-only terminal dashboard for [Uptime Kuma](https://github.com/louislam/uptime-kuma): current monitor state, uptime percentages, response time, and heartbeat history.
|
|
49
|
+
|
|
50
|
+
> `kuma-stats` is an independent project and is not affiliated with or endorsed by Uptime Kuma.
|
|
51
|
+
|
|
52
|
+
## Install
|
|
53
|
+
|
|
54
|
+
Requires Python 3.10 or later.
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pip install kuma-stats
|
|
58
|
+
# or install as an isolated command-line tool
|
|
59
|
+
uv tool install kuma-stats
|
|
60
|
+
# pipx install kuma-stats
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Verify the installation:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
kuma-stats --version
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Quick start
|
|
70
|
+
|
|
71
|
+
Set the Uptime Kuma URL and a server-issued JWT token. Environment variables are preferred for automation; do not pass passwords or tokens as command-line arguments because they can be exposed in shell history or process listings.
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
export KUMA_URL=https://kuma.example.com
|
|
75
|
+
export KUMA_TOKEN=your-server-issued-jwt
|
|
76
|
+
kuma-stats list
|
|
77
|
+
kuma-stats --format json uptime
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Alternatively, create a `.env` file in the directory where you run the command:
|
|
81
|
+
|
|
82
|
+
```dotenv
|
|
83
|
+
KUMA_URL=https://kuma.example.com
|
|
84
|
+
KUMA_TOKEN=your-server-issued-jwt
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
`kuma-stats` loads this working-directory `.env` without overwriting environment variables. Keep it out of version control.
|
|
88
|
+
|
|
89
|
+
To create a token with username/password credentials already supplied through environment variables, use:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
export KUMA_USERNAME=your-username
|
|
93
|
+
export KUMA_PASSWORD=your-password
|
|
94
|
+
kuma-stats login --store-keyring
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The keyring is the preferred token store. `login --store-token` writes an owner-only `.env` file; use it only when the OS keyring is unavailable.
|
|
98
|
+
|
|
99
|
+
## Commands
|
|
100
|
+
|
|
101
|
+
| Command | Description |
|
|
102
|
+
| --- | --- |
|
|
103
|
+
| `login [--store-token \| --store-keyring]` | Authenticate and print or securely save a server-issued JWT |
|
|
104
|
+
| `list` | List all monitors and current telemetry |
|
|
105
|
+
| `status [ID…]` | Show details and recent heartbeats; omit IDs for all monitors |
|
|
106
|
+
| `beats ID [--hours N]` | Show heartbeat history for one monitor |
|
|
107
|
+
| `uptime` | Show 24-hour, 30-day, and one-year uptime |
|
|
108
|
+
|
|
109
|
+
Examples:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
kuma-stats list
|
|
113
|
+
kuma-stats status 1 2
|
|
114
|
+
kuma-stats beats 1 --hours 48
|
|
115
|
+
kuma-stats --format yaml uptime
|
|
116
|
+
kuma-stats --format json list
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Table output is the default. Use `--format json` or `--format yaml` for structured output. JSON and YAML errors are written to stderr with a stable code and message.
|
|
120
|
+
|
|
121
|
+
## Configuration
|
|
122
|
+
|
|
123
|
+
Values are resolved in this order, from highest to lowest precedence:
|
|
124
|
+
|
|
125
|
+
1. Command-line options
|
|
126
|
+
2. Environment variables
|
|
127
|
+
3. A `.env` file in the working directory
|
|
128
|
+
4. User configuration: `$XDG_CONFIG_HOME/kuma-stats/config.toml` on Linux
|
|
129
|
+
5. An OS-keyring token
|
|
130
|
+
|
|
131
|
+
Use `KUMA_CONFIG_FILE` to select a different TOML file. Example:
|
|
132
|
+
|
|
133
|
+
```toml
|
|
134
|
+
url = "https://kuma.example.com"
|
|
135
|
+
format = "table" # table, json, or yaml
|
|
136
|
+
timeout = 30
|
|
137
|
+
max_retries = 2
|
|
138
|
+
insecure = false
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
| Variable | Purpose |
|
|
142
|
+
| --- | --- |
|
|
143
|
+
| `KUMA_URL` | Uptime Kuma server URL |
|
|
144
|
+
| `KUMA_TOKEN` | Server-issued JWT token |
|
|
145
|
+
| `KUMA_USERNAME`, `KUMA_PASSWORD` | Login credentials; required for `login` without a token |
|
|
146
|
+
| `KUMA_FORMAT` | Default output format: `table`, `json`, or `yaml` |
|
|
147
|
+
| `KUMA_TIMEOUT` | Per-connection timeout and overall retry budget in seconds |
|
|
148
|
+
| `KUMA_MAX_RETRIES` | Retry count for transient connection failures |
|
|
149
|
+
| `KUMA_INSECURE` | Set to `true` only for a trusted self-signed server |
|
|
150
|
+
| `NO_COLOR` | Disable terminal colour |
|
|
151
|
+
|
|
152
|
+
TLS certificate verification is enabled by default. Use `--insecure` only for a trusted self-signed server. Invalid or unreadable TOML configuration files fail with an `INVALID_CONFIGURATION` error instead of being ignored.
|
|
153
|
+
|
|
154
|
+
## Compatibility
|
|
155
|
+
|
|
156
|
+
`kuma-stats` supports Python 3.10–3.12 and uses the maintained [`uptime-kuma-api`](https://github.com/lucasheld/uptime-kuma-api) client for Uptime Kuma communication. CI smoke-tests token authentication, password login, failed authentication, and `list` telemetry against a disposable [Uptime Kuma 1.23.16](https://hub.docker.com/layers/louislam/uptime-kuma/1.23.16/images/sha256-431fee3be822b04861cf0e35daf4beef6b7cb37391c5f26c3ad6e12ce280fe18) Docker container. It uses no external server or credentials.
|
|
157
|
+
|
|
158
|
+
## Development
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
make setup
|
|
162
|
+
make verify
|
|
163
|
+
make live-test # requires Docker
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
`make verify` runs linting, type checks, tests, builds wheel/sdist artifacts, and validates their metadata. `make live-test` runs the separately gated Docker compatibility smoke test; it creates disposable credentials and state and never contacts a production server.
|
|
167
|
+
|
|
168
|
+
### Releasing
|
|
169
|
+
|
|
170
|
+
Releases are intentionally manual. Draft notes from the commits since the last release:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
make release-prep
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Use the printed prompt with an LLM if useful, review its suggested Keep a Changelog entry, then update `CHANGELOG.md` and `src/kuma_stats/__init__.py`. Preview and create the GitHub Release:
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
make release-dry
|
|
180
|
+
make release
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
`make release` requires a clean `main` worktree, a new versioned changelog section, and confirmation. It validates the project, creates and pushes an annotated `vX.Y.Z` tag, then attaches the validated wheel and sdist to a GitHub Release. PyPI publishing is a separate deliberate step:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
uv run twine upload dist/*
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
See [docs/RELEASING.md](docs/RELEASING.md) for PyPI/TestPyPI account setup, local token storage, testing, and troubleshooting.
|
|
190
|
+
|
|
191
|
+
## Security and support
|
|
192
|
+
|
|
193
|
+
See [SECURITY.md](SECURITY.md) for private vulnerability reporting, [CONTRIBUTING.md](CONTRIBUTING.md) for the maintenance policy, and [CHANGELOG.md](CHANGELOG.md) for release history.
|
|
194
|
+
|
|
195
|
+
## License
|
|
196
|
+
|
|
197
|
+
Distributed under the [MIT License](LICENSE).
|