pytest-allure-host 0.1.1__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.
- pytest_allure_host-0.1.1/LICENSE +21 -0
- pytest_allure_host-0.1.1/PKG-INFO +305 -0
- pytest_allure_host-0.1.1/README.md +275 -0
- pytest_allure_host-0.1.1/pyproject.toml +93 -0
- pytest_allure_host-0.1.1/pytest_allure_host/__init__.py +6 -0
- pytest_allure_host-0.1.1/pytest_allure_host/__main__.py +4 -0
- pytest_allure_host-0.1.1/pytest_allure_host/cli.py +104 -0
- pytest_allure_host-0.1.1/pytest_allure_host/config.py +141 -0
- pytest_allure_host-0.1.1/pytest_allure_host/plugin.py +127 -0
- pytest_allure_host-0.1.1/pytest_allure_host/publisher.py +716 -0
- pytest_allure_host-0.1.1/pytest_allure_host/utils.py +119 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 Allure Hosting Contributors
|
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,305 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: pytest-allure-host
|
3
|
+
Version: 0.1.1
|
4
|
+
Summary: Publish Allure static reports to private S3 behind CloudFront with history preservation
|
5
|
+
License-Expression: MIT
|
6
|
+
License-File: LICENSE
|
7
|
+
Keywords: allure,pytest,aws,s3,cloudfront,reporting
|
8
|
+
Author: Allure Hosting Maintainers
|
9
|
+
Requires-Python: >=3.9,<4.0
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
11
|
+
Classifier: Programming Language :: Python :: 3.9
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
16
|
+
Classifier: Intended Audience :: Developers
|
17
|
+
Classifier: Topic :: Software Development :: Testing
|
18
|
+
Classifier: Framework :: Pytest
|
19
|
+
Classifier: Development Status :: 3 - Alpha
|
20
|
+
Classifier: Operating System :: OS Independent
|
21
|
+
Requires-Dist: PyYAML (>=6,<7)
|
22
|
+
Requires-Dist: boto3 (>=1.28,<2.0)
|
23
|
+
Project-URL: Bug Tracker, https://github.com/darrenrabbs/allurehosting/issues
|
24
|
+
Project-URL: Changelog, https://github.com/darrenrabbs/allurehosting/releases
|
25
|
+
Project-URL: Documentation, https://github.com/darrenrabbs/allurehosting#readme
|
26
|
+
Project-URL: Homepage, https://github.com/darrenrabbs/allurehosting
|
27
|
+
Project-URL: Repository, https://github.com/darrenrabbs/allurehosting
|
28
|
+
Description-Content-Type: text/markdown
|
29
|
+
|
30
|
+
# pytest-allure-host
|
31
|
+
|
32
|
+

|
33
|
+

|
34
|
+

|
35
|
+

|
36
|
+
|
37
|
+
Publish Allure static reports to private S3 behind CloudFront with history preservation and SPA-friendly routing.
|
38
|
+
|
39
|
+
See `docs/architecture.md` and `.github/copilot-instructions.md` for architecture and design constraints.
|
40
|
+
|
41
|
+
## Features
|
42
|
+
|
43
|
+
- Generate Allure static report from `allure-results`
|
44
|
+
- Preserve history by pulling `latest/history` before generation
|
45
|
+
- Upload to S3 under `<project>/<branch>/<run_id>/` and update `<project>/<branch>/latest/`
|
46
|
+
- Two-phase latest update: upload to `latest_tmp/`, swap into `latest/`, write `LATEST_READY` marker
|
47
|
+
- Optional retention: keep only N newest runs (`--max-keep-runs`)
|
48
|
+
- Correct caching headers: `index.html` and `widgets/` → `no-cache`; assets → immutable
|
49
|
+
- Optional TTL tagging on objects (`--ttl-days`) for S3 lifecycle policies
|
50
|
+
- Optional summary JSON output for CI
|
51
|
+
- Best-effort manifest at `runs/index.json` with new run metadata
|
52
|
+
- Lightweight pointer file `latest.json` (branch root)
|
53
|
+
- Human-friendly HTML index at `runs/index.html` for navigating past runs
|
54
|
+
- Columns: Run ID, raw epoch, UTC Time (human readable), Size (pretty units), P/F/B (passed/failed/broken counts), links to the immutable run and the moving latest
|
55
|
+
- Newest run highlighted with a star (★) and soft background
|
56
|
+
|
57
|
+
## Requirements
|
58
|
+
|
59
|
+
- Python 3.9+
|
60
|
+
- AWS credentials with S3 access to the target bucket
|
61
|
+
- Allure commandline available on PATH (e.g., via Allure CLI or allure-pytest)
|
62
|
+
|
63
|
+
## S3 layout and caching
|
64
|
+
|
65
|
+
- Keys:
|
66
|
+
- `s3://<bucket>/<prefix>/<project>/<branch>/<run_id>/...`
|
67
|
+
- `s3://<bucket>/<prefix>/<project>/<branch>/latest/...`
|
68
|
+
- `s3://<bucket>/<prefix>/<project>/<branch>/runs/index.json` (manifest)
|
69
|
+
- `s3://<bucket>/<prefix>/<project>/<branch>/runs/index.html` (HTML index)
|
70
|
+
- `s3://<bucket>/<prefix>/<project>/<branch>/latest.json` (pointer)
|
71
|
+
- Two-phase swap writes a `LATEST_READY` marker file under `latest/` when ready.
|
72
|
+
- Cache-Control:
|
73
|
+
- `index.html`: `no-cache`
|
74
|
+
- files under `widgets/`: `no-cache`
|
75
|
+
- everything else: `public, max-age=31536000, immutable`
|
76
|
+
|
77
|
+
## CLI usage
|
78
|
+
|
79
|
+
Install locally for development:
|
80
|
+
|
81
|
+
```bash
|
82
|
+
pip install -e .[dev]
|
83
|
+
```
|
84
|
+
|
85
|
+
Run the publisher after tests generate `allure-results`:
|
86
|
+
|
87
|
+
```bash
|
88
|
+
publish-allure \
|
89
|
+
--bucket your-bucket \
|
90
|
+
--prefix reports \
|
91
|
+
--project demo \
|
92
|
+
--branch main \
|
93
|
+
--cloudfront https://reports.example.com \
|
94
|
+
--ttl-days 30 \
|
95
|
+
--max-keep-runs 10
|
96
|
+
```
|
97
|
+
|
98
|
+
Flags (CLI):
|
99
|
+
|
100
|
+
- `--bucket` (required): S3 bucket name
|
101
|
+
- `--prefix` (default: `reports`): Root prefix
|
102
|
+
- `--project` (required): Project name
|
103
|
+
- `--branch` (default: `$GIT_BRANCH` or `main`)
|
104
|
+
- `--run-id` (default: `$ALLURE_RUN_ID` or `YYYYMMDD-HHMMSS`)
|
105
|
+
- `--cloudfront` (optional; default: `$ALLURE_CLOUDFRONT`)
|
106
|
+
- `--results` (default: `allure-results`): Input directory
|
107
|
+
- `--report` (default: `allure-report`): Output directory
|
108
|
+
- `--ttl-days` (optional): Add `ttl-days=<N>` object tag
|
109
|
+
- `--max-keep-runs` (optional): Keep N newest run prefixes, delete older
|
110
|
+
- `--summary-json <path>`: Write machine-readable summary
|
111
|
+
- `--check`: Preflight validation (AWS access, allure, inputs)
|
112
|
+
- `--dry-run`: Print planned prefixes and sample headers, no upload
|
113
|
+
- `--s3-endpoint`: Custom S3 endpoint (e.g. `http://localhost:4566` for LocalStack)
|
114
|
+
|
115
|
+
Environment fallbacks:
|
116
|
+
|
117
|
+
- `GIT_BRANCH` → `--branch` default
|
118
|
+
- `ALLURE_RUN_ID` → `--run-id` default
|
119
|
+
- `ALLURE_CLOUDFRONT` → `--cloudfront` default
|
120
|
+
- `ALLURE_S3_ENDPOINT` → `--s3-endpoint` default (LocalStack / custom S3)
|
121
|
+
|
122
|
+
## Pytest plugin usage
|
123
|
+
|
124
|
+
Run tests and publish during terminal summary:
|
125
|
+
|
126
|
+
```bash
|
127
|
+
pytest \
|
128
|
+
--allure-bucket your-bucket \
|
129
|
+
--allure-prefix reports \
|
130
|
+
--allure-project demo \
|
131
|
+
--allure-branch main \
|
132
|
+
--allure-cloudfront https://reports.example.com \
|
133
|
+
--allure-ttl-days 30 \
|
134
|
+
--allure-max-keep-runs 10
|
135
|
+
```
|
136
|
+
|
137
|
+
Flags (pytest):
|
138
|
+
|
139
|
+
- `--allure-bucket` (required)
|
140
|
+
- `--allure-prefix` (default: `reports`)
|
141
|
+
- `--allure-project` (required)
|
142
|
+
- `--allure-branch` (default: `$GIT_BRANCH` or `main`)
|
143
|
+
- `--allure-run-id` (default: `$ALLURE_RUN_ID` or `YYYYMMDD-HHMMSS`)
|
144
|
+
- `--allure-cloudfront` (optional; default: `$ALLURE_CLOUDFRONT`)
|
145
|
+
- `--allure-ttl-days` (optional)
|
146
|
+
- `--allure-max-keep-runs` (optional)
|
147
|
+
- `--allure-summary-json <path>` (optional)
|
148
|
+
- `--allure-check` / `--allure-dry-run` (optional)
|
149
|
+
|
150
|
+
## Preflight and dry-run
|
151
|
+
|
152
|
+
- `--check`/`--allure-check` verifies:
|
153
|
+
- S3 bucket reachability (HeadBucket/List)
|
154
|
+
- `allure-results` exists and is non-empty
|
155
|
+
- Allure CLI exists on PATH
|
156
|
+
- `--dry-run`/`--allure-dry-run` prints planned prefixes and sample headers; no uploads occur.
|
157
|
+
|
158
|
+
## Outputs
|
159
|
+
|
160
|
+
- S3 prefixes: run and latest
|
161
|
+
- Optional CDN URLs (if `--cloudfront` provided)
|
162
|
+
- `runs/index.json` manifest updated with new run entry
|
163
|
+
- `runs/index.html` HTML table of recent runs (newest first) with columns: Run ID, Epoch, UTC Time, Size, P/F/B, Run, Latest (newest row highlighted with ★)
|
164
|
+
- `latest.json` pointer to current run (simple machine-readable metadata)
|
165
|
+
- Optional `--summary-json` with sizes, file counts, and destination URLs
|
166
|
+
- `latest/LATEST_READY` marker indicates the swap is complete
|
167
|
+
|
168
|
+
## Security
|
169
|
+
|
170
|
+
See `SECURITY.md` for how to report vulnerabilities. Never open a public issue containing sensitive details.
|
171
|
+
|
172
|
+
## Badges / Status
|
173
|
+
|
174
|
+
- CI: multi-version test matrix + lint/security
|
175
|
+
- CodeQL: static code analysis
|
176
|
+
|
177
|
+
## Contributing
|
178
|
+
|
179
|
+
See `CONTRIBUTING.md` and follow the pre-commit hooks (`pre-commit install`).
|
180
|
+
|
181
|
+
## Release
|
182
|
+
|
183
|
+
Tagged versions (`vX.Y.Z`) are published to PyPI automatically via GitHub OIDC.
|
184
|
+
|
185
|
+
## CI examples
|
186
|
+
|
187
|
+
GitHub Actions (CLI):
|
188
|
+
|
189
|
+
```yaml
|
190
|
+
jobs:
|
191
|
+
tests:
|
192
|
+
runs-on: ubuntu-latest
|
193
|
+
steps:
|
194
|
+
- uses: actions/checkout@v4
|
195
|
+
- uses: actions/setup-python@v5
|
196
|
+
with: { python-version: "3.11" }
|
197
|
+
- run: pip install .[dev]
|
198
|
+
- run: pytest -q
|
199
|
+
- name: Publish Allure
|
200
|
+
env:
|
201
|
+
AWS_REGION: us-east-1
|
202
|
+
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
203
|
+
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
204
|
+
GIT_BRANCH: ${{ github.ref_name }}
|
205
|
+
run: >-
|
206
|
+
publish-allure --bucket $BUCKET --prefix reports --project demo
|
207
|
+
--branch "$GIT_BRANCH" --cloudfront https://reports.example.com
|
208
|
+
--ttl-days 30 --max-keep-runs 10
|
209
|
+
```
|
210
|
+
|
211
|
+
Pytest-driven (plugin):
|
212
|
+
|
213
|
+
```yaml
|
214
|
+
- run: pytest -q \
|
215
|
+
--allure-bucket $BUCKET \
|
216
|
+
--allure-prefix reports \
|
217
|
+
--allure-project demo \
|
218
|
+
--allure-branch "$GIT_BRANCH" \
|
219
|
+
--allure-cloudfront https://reports.example.com \
|
220
|
+
--allure-ttl-days 30 \
|
221
|
+
--allure-max-keep-runs 10
|
222
|
+
```
|
223
|
+
|
224
|
+
## Troubleshooting
|
225
|
+
|
226
|
+
- Missing Allure binary: ensure the Allure CLI is installed and on PATH.
|
227
|
+
- Access denied: verify AWS credentials and bucket IAM for Put/Get/List/Delete.
|
228
|
+
- SPA routing 403/404: configure CloudFront error mapping to `/index.html`.
|
229
|
+
|
230
|
+
## Development
|
231
|
+
|
232
|
+
- Install with Poetry: `poetry install`
|
233
|
+
- Run tests: `poetry run pytest -q`
|
234
|
+
- Lint (security quick): `poetry run bandit -r pytest_allure_host`
|
235
|
+
- Unified lint helper (mirrors CI):
|
236
|
+
```bash
|
237
|
+
scripts/lint.sh # check mode (ruff lint+format check, bandit, pip-audit)
|
238
|
+
scripts/lint.sh --fix # apply ruff fixes + format
|
239
|
+
scripts/lint.sh pre-commit # also run pre-commit hooks on all files
|
240
|
+
```
|
241
|
+
|
242
|
+
## Quick local trial (macOS)
|
243
|
+
|
244
|
+
This section walks you through a minimal end-to-end run locally.
|
245
|
+
|
246
|
+
1. Prereqs
|
247
|
+
|
248
|
+
- AWS credentials configured (via `AWS_PROFILE` or access keys); set `AWS_REGION`.
|
249
|
+
- Allure CLI installed on PATH:
|
250
|
+
```bash
|
251
|
+
brew install allure
|
252
|
+
```
|
253
|
+
- Python deps installed:
|
254
|
+
```bash
|
255
|
+
poetry install
|
256
|
+
# or
|
257
|
+
pip install -e .[dev]
|
258
|
+
```
|
259
|
+
|
260
|
+
2. Generate Allure results
|
261
|
+
|
262
|
+
- Create a tiny test (optional example):
|
263
|
+
```bash
|
264
|
+
mkdir -p tests
|
265
|
+
cat > tests/test_sample.py <<'PY'
|
266
|
+
def test_ok():
|
267
|
+
assert True
|
268
|
+
PY
|
269
|
+
```
|
270
|
+
- Run pytest to emit results:
|
271
|
+
```bash
|
272
|
+
poetry run pytest --alluredir=allure-results
|
273
|
+
```
|
274
|
+
|
275
|
+
3. Preflight and dry-run
|
276
|
+
|
277
|
+
```bash
|
278
|
+
poetry run publish-allure \
|
279
|
+
--bucket <bucket> \
|
280
|
+
--prefix reports \
|
281
|
+
--project demo \
|
282
|
+
--branch $(git rev-parse --abbrev-ref HEAD) \
|
283
|
+
--cloudfront https://<cloudfront_domain> \
|
284
|
+
--check \
|
285
|
+
--dry-run
|
286
|
+
```
|
287
|
+
|
288
|
+
4. Publish
|
289
|
+
|
290
|
+
```bash
|
291
|
+
poetry run publish-allure \
|
292
|
+
--bucket <bucket> \
|
293
|
+
--prefix reports \
|
294
|
+
--project demo \
|
295
|
+
--branch $(git rev-parse --abbrev-ref HEAD) \
|
296
|
+
--cloudfront https://<cloudfront_domain> \
|
297
|
+
--ttl-days 30 \
|
298
|
+
--max-keep-runs 5
|
299
|
+
```
|
300
|
+
|
301
|
+
5. Verify
|
302
|
+
|
303
|
+
- S3: `reports/demo/<branch>/<run_id>/...` and `reports/demo/<branch>/latest/` with `LATEST_READY`.
|
304
|
+
- CDN: open printed `run_url` / `latest_url`.
|
305
|
+
|
@@ -0,0 +1,275 @@
|
|
1
|
+
# pytest-allure-host
|
2
|
+
|
3
|
+

|
4
|
+

|
5
|
+

|
6
|
+

|
7
|
+
|
8
|
+
Publish Allure static reports to private S3 behind CloudFront with history preservation and SPA-friendly routing.
|
9
|
+
|
10
|
+
See `docs/architecture.md` and `.github/copilot-instructions.md` for architecture and design constraints.
|
11
|
+
|
12
|
+
## Features
|
13
|
+
|
14
|
+
- Generate Allure static report from `allure-results`
|
15
|
+
- Preserve history by pulling `latest/history` before generation
|
16
|
+
- Upload to S3 under `<project>/<branch>/<run_id>/` and update `<project>/<branch>/latest/`
|
17
|
+
- Two-phase latest update: upload to `latest_tmp/`, swap into `latest/`, write `LATEST_READY` marker
|
18
|
+
- Optional retention: keep only N newest runs (`--max-keep-runs`)
|
19
|
+
- Correct caching headers: `index.html` and `widgets/` → `no-cache`; assets → immutable
|
20
|
+
- Optional TTL tagging on objects (`--ttl-days`) for S3 lifecycle policies
|
21
|
+
- Optional summary JSON output for CI
|
22
|
+
- Best-effort manifest at `runs/index.json` with new run metadata
|
23
|
+
- Lightweight pointer file `latest.json` (branch root)
|
24
|
+
- Human-friendly HTML index at `runs/index.html` for navigating past runs
|
25
|
+
- Columns: Run ID, raw epoch, UTC Time (human readable), Size (pretty units), P/F/B (passed/failed/broken counts), links to the immutable run and the moving latest
|
26
|
+
- Newest run highlighted with a star (★) and soft background
|
27
|
+
|
28
|
+
## Requirements
|
29
|
+
|
30
|
+
- Python 3.9+
|
31
|
+
- AWS credentials with S3 access to the target bucket
|
32
|
+
- Allure commandline available on PATH (e.g., via Allure CLI or allure-pytest)
|
33
|
+
|
34
|
+
## S3 layout and caching
|
35
|
+
|
36
|
+
- Keys:
|
37
|
+
- `s3://<bucket>/<prefix>/<project>/<branch>/<run_id>/...`
|
38
|
+
- `s3://<bucket>/<prefix>/<project>/<branch>/latest/...`
|
39
|
+
- `s3://<bucket>/<prefix>/<project>/<branch>/runs/index.json` (manifest)
|
40
|
+
- `s3://<bucket>/<prefix>/<project>/<branch>/runs/index.html` (HTML index)
|
41
|
+
- `s3://<bucket>/<prefix>/<project>/<branch>/latest.json` (pointer)
|
42
|
+
- Two-phase swap writes a `LATEST_READY` marker file under `latest/` when ready.
|
43
|
+
- Cache-Control:
|
44
|
+
- `index.html`: `no-cache`
|
45
|
+
- files under `widgets/`: `no-cache`
|
46
|
+
- everything else: `public, max-age=31536000, immutable`
|
47
|
+
|
48
|
+
## CLI usage
|
49
|
+
|
50
|
+
Install locally for development:
|
51
|
+
|
52
|
+
```bash
|
53
|
+
pip install -e .[dev]
|
54
|
+
```
|
55
|
+
|
56
|
+
Run the publisher after tests generate `allure-results`:
|
57
|
+
|
58
|
+
```bash
|
59
|
+
publish-allure \
|
60
|
+
--bucket your-bucket \
|
61
|
+
--prefix reports \
|
62
|
+
--project demo \
|
63
|
+
--branch main \
|
64
|
+
--cloudfront https://reports.example.com \
|
65
|
+
--ttl-days 30 \
|
66
|
+
--max-keep-runs 10
|
67
|
+
```
|
68
|
+
|
69
|
+
Flags (CLI):
|
70
|
+
|
71
|
+
- `--bucket` (required): S3 bucket name
|
72
|
+
- `--prefix` (default: `reports`): Root prefix
|
73
|
+
- `--project` (required): Project name
|
74
|
+
- `--branch` (default: `$GIT_BRANCH` or `main`)
|
75
|
+
- `--run-id` (default: `$ALLURE_RUN_ID` or `YYYYMMDD-HHMMSS`)
|
76
|
+
- `--cloudfront` (optional; default: `$ALLURE_CLOUDFRONT`)
|
77
|
+
- `--results` (default: `allure-results`): Input directory
|
78
|
+
- `--report` (default: `allure-report`): Output directory
|
79
|
+
- `--ttl-days` (optional): Add `ttl-days=<N>` object tag
|
80
|
+
- `--max-keep-runs` (optional): Keep N newest run prefixes, delete older
|
81
|
+
- `--summary-json <path>`: Write machine-readable summary
|
82
|
+
- `--check`: Preflight validation (AWS access, allure, inputs)
|
83
|
+
- `--dry-run`: Print planned prefixes and sample headers, no upload
|
84
|
+
- `--s3-endpoint`: Custom S3 endpoint (e.g. `http://localhost:4566` for LocalStack)
|
85
|
+
|
86
|
+
Environment fallbacks:
|
87
|
+
|
88
|
+
- `GIT_BRANCH` → `--branch` default
|
89
|
+
- `ALLURE_RUN_ID` → `--run-id` default
|
90
|
+
- `ALLURE_CLOUDFRONT` → `--cloudfront` default
|
91
|
+
- `ALLURE_S3_ENDPOINT` → `--s3-endpoint` default (LocalStack / custom S3)
|
92
|
+
|
93
|
+
## Pytest plugin usage
|
94
|
+
|
95
|
+
Run tests and publish during terminal summary:
|
96
|
+
|
97
|
+
```bash
|
98
|
+
pytest \
|
99
|
+
--allure-bucket your-bucket \
|
100
|
+
--allure-prefix reports \
|
101
|
+
--allure-project demo \
|
102
|
+
--allure-branch main \
|
103
|
+
--allure-cloudfront https://reports.example.com \
|
104
|
+
--allure-ttl-days 30 \
|
105
|
+
--allure-max-keep-runs 10
|
106
|
+
```
|
107
|
+
|
108
|
+
Flags (pytest):
|
109
|
+
|
110
|
+
- `--allure-bucket` (required)
|
111
|
+
- `--allure-prefix` (default: `reports`)
|
112
|
+
- `--allure-project` (required)
|
113
|
+
- `--allure-branch` (default: `$GIT_BRANCH` or `main`)
|
114
|
+
- `--allure-run-id` (default: `$ALLURE_RUN_ID` or `YYYYMMDD-HHMMSS`)
|
115
|
+
- `--allure-cloudfront` (optional; default: `$ALLURE_CLOUDFRONT`)
|
116
|
+
- `--allure-ttl-days` (optional)
|
117
|
+
- `--allure-max-keep-runs` (optional)
|
118
|
+
- `--allure-summary-json <path>` (optional)
|
119
|
+
- `--allure-check` / `--allure-dry-run` (optional)
|
120
|
+
|
121
|
+
## Preflight and dry-run
|
122
|
+
|
123
|
+
- `--check`/`--allure-check` verifies:
|
124
|
+
- S3 bucket reachability (HeadBucket/List)
|
125
|
+
- `allure-results` exists and is non-empty
|
126
|
+
- Allure CLI exists on PATH
|
127
|
+
- `--dry-run`/`--allure-dry-run` prints planned prefixes and sample headers; no uploads occur.
|
128
|
+
|
129
|
+
## Outputs
|
130
|
+
|
131
|
+
- S3 prefixes: run and latest
|
132
|
+
- Optional CDN URLs (if `--cloudfront` provided)
|
133
|
+
- `runs/index.json` manifest updated with new run entry
|
134
|
+
- `runs/index.html` HTML table of recent runs (newest first) with columns: Run ID, Epoch, UTC Time, Size, P/F/B, Run, Latest (newest row highlighted with ★)
|
135
|
+
- `latest.json` pointer to current run (simple machine-readable metadata)
|
136
|
+
- Optional `--summary-json` with sizes, file counts, and destination URLs
|
137
|
+
- `latest/LATEST_READY` marker indicates the swap is complete
|
138
|
+
|
139
|
+
## Security
|
140
|
+
|
141
|
+
See `SECURITY.md` for how to report vulnerabilities. Never open a public issue containing sensitive details.
|
142
|
+
|
143
|
+
## Badges / Status
|
144
|
+
|
145
|
+
- CI: multi-version test matrix + lint/security
|
146
|
+
- CodeQL: static code analysis
|
147
|
+
|
148
|
+
## Contributing
|
149
|
+
|
150
|
+
See `CONTRIBUTING.md` and follow the pre-commit hooks (`pre-commit install`).
|
151
|
+
|
152
|
+
## Release
|
153
|
+
|
154
|
+
Tagged versions (`vX.Y.Z`) are published to PyPI automatically via GitHub OIDC.
|
155
|
+
|
156
|
+
## CI examples
|
157
|
+
|
158
|
+
GitHub Actions (CLI):
|
159
|
+
|
160
|
+
```yaml
|
161
|
+
jobs:
|
162
|
+
tests:
|
163
|
+
runs-on: ubuntu-latest
|
164
|
+
steps:
|
165
|
+
- uses: actions/checkout@v4
|
166
|
+
- uses: actions/setup-python@v5
|
167
|
+
with: { python-version: "3.11" }
|
168
|
+
- run: pip install .[dev]
|
169
|
+
- run: pytest -q
|
170
|
+
- name: Publish Allure
|
171
|
+
env:
|
172
|
+
AWS_REGION: us-east-1
|
173
|
+
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
|
174
|
+
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
175
|
+
GIT_BRANCH: ${{ github.ref_name }}
|
176
|
+
run: >-
|
177
|
+
publish-allure --bucket $BUCKET --prefix reports --project demo
|
178
|
+
--branch "$GIT_BRANCH" --cloudfront https://reports.example.com
|
179
|
+
--ttl-days 30 --max-keep-runs 10
|
180
|
+
```
|
181
|
+
|
182
|
+
Pytest-driven (plugin):
|
183
|
+
|
184
|
+
```yaml
|
185
|
+
- run: pytest -q \
|
186
|
+
--allure-bucket $BUCKET \
|
187
|
+
--allure-prefix reports \
|
188
|
+
--allure-project demo \
|
189
|
+
--allure-branch "$GIT_BRANCH" \
|
190
|
+
--allure-cloudfront https://reports.example.com \
|
191
|
+
--allure-ttl-days 30 \
|
192
|
+
--allure-max-keep-runs 10
|
193
|
+
```
|
194
|
+
|
195
|
+
## Troubleshooting
|
196
|
+
|
197
|
+
- Missing Allure binary: ensure the Allure CLI is installed and on PATH.
|
198
|
+
- Access denied: verify AWS credentials and bucket IAM for Put/Get/List/Delete.
|
199
|
+
- SPA routing 403/404: configure CloudFront error mapping to `/index.html`.
|
200
|
+
|
201
|
+
## Development
|
202
|
+
|
203
|
+
- Install with Poetry: `poetry install`
|
204
|
+
- Run tests: `poetry run pytest -q`
|
205
|
+
- Lint (security quick): `poetry run bandit -r pytest_allure_host`
|
206
|
+
- Unified lint helper (mirrors CI):
|
207
|
+
```bash
|
208
|
+
scripts/lint.sh # check mode (ruff lint+format check, bandit, pip-audit)
|
209
|
+
scripts/lint.sh --fix # apply ruff fixes + format
|
210
|
+
scripts/lint.sh pre-commit # also run pre-commit hooks on all files
|
211
|
+
```
|
212
|
+
|
213
|
+
## Quick local trial (macOS)
|
214
|
+
|
215
|
+
This section walks you through a minimal end-to-end run locally.
|
216
|
+
|
217
|
+
1. Prereqs
|
218
|
+
|
219
|
+
- AWS credentials configured (via `AWS_PROFILE` or access keys); set `AWS_REGION`.
|
220
|
+
- Allure CLI installed on PATH:
|
221
|
+
```bash
|
222
|
+
brew install allure
|
223
|
+
```
|
224
|
+
- Python deps installed:
|
225
|
+
```bash
|
226
|
+
poetry install
|
227
|
+
# or
|
228
|
+
pip install -e .[dev]
|
229
|
+
```
|
230
|
+
|
231
|
+
2. Generate Allure results
|
232
|
+
|
233
|
+
- Create a tiny test (optional example):
|
234
|
+
```bash
|
235
|
+
mkdir -p tests
|
236
|
+
cat > tests/test_sample.py <<'PY'
|
237
|
+
def test_ok():
|
238
|
+
assert True
|
239
|
+
PY
|
240
|
+
```
|
241
|
+
- Run pytest to emit results:
|
242
|
+
```bash
|
243
|
+
poetry run pytest --alluredir=allure-results
|
244
|
+
```
|
245
|
+
|
246
|
+
3. Preflight and dry-run
|
247
|
+
|
248
|
+
```bash
|
249
|
+
poetry run publish-allure \
|
250
|
+
--bucket <bucket> \
|
251
|
+
--prefix reports \
|
252
|
+
--project demo \
|
253
|
+
--branch $(git rev-parse --abbrev-ref HEAD) \
|
254
|
+
--cloudfront https://<cloudfront_domain> \
|
255
|
+
--check \
|
256
|
+
--dry-run
|
257
|
+
```
|
258
|
+
|
259
|
+
4. Publish
|
260
|
+
|
261
|
+
```bash
|
262
|
+
poetry run publish-allure \
|
263
|
+
--bucket <bucket> \
|
264
|
+
--prefix reports \
|
265
|
+
--project demo \
|
266
|
+
--branch $(git rev-parse --abbrev-ref HEAD) \
|
267
|
+
--cloudfront https://<cloudfront_domain> \
|
268
|
+
--ttl-days 30 \
|
269
|
+
--max-keep-runs 5
|
270
|
+
```
|
271
|
+
|
272
|
+
5. Verify
|
273
|
+
|
274
|
+
- S3: `reports/demo/<branch>/<run_id>/...` and `reports/demo/<branch>/latest/` with `LATEST_READY`.
|
275
|
+
- CDN: open printed `run_url` / `latest_url`.
|
@@ -0,0 +1,93 @@
|
|
1
|
+
[build-system]
|
2
|
+
requires = ["poetry-core>=1.9.0"]
|
3
|
+
build-backend = "poetry.core.masonry.api"
|
4
|
+
|
5
|
+
[project]
|
6
|
+
name = "pytest-allure-host"
|
7
|
+
version = "0.1.1"
|
8
|
+
description = "Publish Allure static reports to private S3 behind CloudFront with history preservation"
|
9
|
+
readme = "README.md"
|
10
|
+
license = "MIT"
|
11
|
+
authors = [ { name = "Allure Hosting Maintainers" } ]
|
12
|
+
requires-python = ">=3.9,<4.0"
|
13
|
+
keywords = ["allure", "pytest", "aws", "s3", "cloudfront", "reporting"]
|
14
|
+
classifiers = [
|
15
|
+
"Programming Language :: Python :: 3",
|
16
|
+
"Programming Language :: Python :: 3.9",
|
17
|
+
"Programming Language :: Python :: 3.10",
|
18
|
+
"Programming Language :: Python :: 3.11",
|
19
|
+
"Programming Language :: Python :: 3.12",
|
20
|
+
"Programming Language :: Python :: 3.13",
|
21
|
+
"Intended Audience :: Developers",
|
22
|
+
"Topic :: Software Development :: Testing",
|
23
|
+
"Framework :: Pytest",
|
24
|
+
"Development Status :: 3 - Alpha",
|
25
|
+
"Operating System :: OS Independent"
|
26
|
+
]
|
27
|
+
|
28
|
+
dependencies = [
|
29
|
+
"boto3>=1.28,<2.0",
|
30
|
+
"PyYAML>=6,<7"
|
31
|
+
]
|
32
|
+
|
33
|
+
[project.optional-dependencies]
|
34
|
+
# (Reserved for runtime extras; dev tooling now uses a Poetry dependency group below.)
|
35
|
+
|
36
|
+
[tool.poetry.group.dev]
|
37
|
+
optional = true
|
38
|
+
|
39
|
+
[tool.poetry.group.dev.dependencies]
|
40
|
+
pytest = ">=7,<9"
|
41
|
+
moto = {version = ">=5,<6", extras=["s3"]}
|
42
|
+
bandit = ">=1.7,<2.0"
|
43
|
+
allure-pytest = ">=2,<3"
|
44
|
+
pytest-cov = ">=4,<5"
|
45
|
+
ruff = ">=0.5,<1.0"
|
46
|
+
pip-audit = ">=2.7,<3.0"
|
47
|
+
black = ">=24,<25"
|
48
|
+
|
49
|
+
[project.scripts]
|
50
|
+
publish-allure = "pytest_allure_host.cli:main"
|
51
|
+
|
52
|
+
[project.entry-points."pytest11"]
|
53
|
+
pytest_allure_host = "pytest_allure_host.plugin"
|
54
|
+
|
55
|
+
[project.urls]
|
56
|
+
Homepage = "https://github.com/darrenrabbs/allurehosting"
|
57
|
+
Repository = "https://github.com/darrenrabbs/allurehosting"
|
58
|
+
Documentation = "https://github.com/darrenrabbs/allurehosting#readme"
|
59
|
+
"Bug Tracker" = "https://github.com/darrenrabbs/allurehosting/issues"
|
60
|
+
Changelog = "https://github.com/darrenrabbs/allurehosting/releases"
|
61
|
+
|
62
|
+
# Package include (PEP 621 doesn't specify this; still handled by Poetry configuration)
|
63
|
+
[tool.poetry]
|
64
|
+
packages = [{ include = "pytest_allure_host" }]
|
65
|
+
# PEP 621 is authoritative; legacy duplicate metadata removed (require Poetry 2.2.1+)
|
66
|
+
|
67
|
+
[tool.poetry.dependencies]
|
68
|
+
# Retained only for Poetry's internal processing of the runtime dependency group.
|
69
|
+
python = ">=3.9,<4.0"
|
70
|
+
|
71
|
+
|
72
|
+
[tool.ruff]
|
73
|
+
line-length = 100
|
74
|
+
target-version = "py39"
|
75
|
+
|
76
|
+
[tool.ruff.lint]
|
77
|
+
select = ["E", "F", "I", "B", "UP", "S", "W", "C90"]
|
78
|
+
ignore = ["E203", "E501"]
|
79
|
+
|
80
|
+
[tool.ruff.lint.per-file-ignores]
|
81
|
+
"tests/**" = ["S101"] # allow bare asserts in test modules
|
82
|
+
|
83
|
+
[tool.ruff.format]
|
84
|
+
quote-style = "double"
|
85
|
+
indent-style = "space"
|
86
|
+
skip-magic-trailing-comma = false
|
87
|
+
line-ending = "lf"
|
88
|
+
|
89
|
+
[tool.black]
|
90
|
+
line-length = 100
|
91
|
+
target-version = ["py39"]
|
92
|
+
skip-string-normalization = false
|
93
|
+
color = true
|