Skip to content

Commit c296907

Browse files
committed
upload: per-arch distributions in results JSON; optional logs/SBOM repos
1 parent b52aa57 commit c296907

25 files changed

+674
-44
lines changed

.cursor/rules/llm-development-guidelines.mdc

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,13 @@ When you do generate it, use a clear heading such as `### PR description (GitHub
6969
make test
7070
```
7171
**IMPORTANT**: Use the full test suite, not only a single test file, so regressions surface. If anything fails, fix it and **run `make test` again**. **Repeat** until all tests pass.
72-
7. **Verify 100% diff coverage for GitHub merge** - Every new or changed line in the PR must be executed by tests (CI blocks merge below 100% on the diff). Use coverage output from `make test` and/or:
72+
7. **Verify 100% diff coverage for GitHub merge** - CI uses `diff-cover` on the PR diff vs the base branch (same as `make test-diff-coverage`). After `git fetch origin`, run:
7373
```bash
74-
python3 -m pytest --cov=pulp_tool --cov-report=term-missing
74+
make test-diff-coverage
7575
```
76-
If the diff is not fully covered, add or extend tests and **return to step 6** until tests pass and the PR diff would satisfy diff coverage.
76+
For a PR targeting a branch other than `main`, use `make test-diff-coverage COMPARE_BRANCH=origin/<base>`. If this fails, add or extend tests and **return to step 6** until the diff is fully covered. Use `python3 -m pytest --cov=pulp_tool --cov-report=term-missing` only for debugging specific files; the **authoritative local gate** is `make test-diff-coverage`.
7777

78-
**Never skip linting, pre-commit (must finish with a fully passing run), or tests (must finish with a fully passing `make test` and diff-ready coverage)** - They will fail in CI/CD and waste pipeline resources.
78+
**Never skip linting, pre-commit (must finish with a fully passing run), or tests (must finish with a fully passing `make test` and `make test-diff-coverage` before a PR)** - They will fail in CI/CD and waste pipeline resources.
7979

8080
## Linting Tools
8181

@@ -189,6 +189,12 @@ pre-commit run flake8 --all-files
189189
# Run all tests with coverage (REQUIRED for new changes)
190190
make test
191191

192+
# Same as PR CI: 100% of lines changed vs merge base (run after git fetch origin)
193+
make test-diff-coverage
194+
195+
# Optional: non-main base branch
196+
make test-diff-coverage COMPARE_BRANCH=origin/my-release-branch
197+
192198
# Run tests without coverage (faster, but won't verify coverage)
193199
make test-fast
194200

@@ -199,15 +205,16 @@ python3 -m pytest tests/path/to/test_file.py -v
199205
python3 -m pytest --cov=pulp_tool/path/to/module --cov-report=term-missing tests/
200206
```
201207

202-
**IMPORTANT**: New changes require **100% coverage on the PR diff** for GitHub merge. Always run `make test` and confirm your branch would pass diff coverage before opening or updating a PR.
208+
**IMPORTANT**: New changes require **100% coverage on the PR diff** for GitHub merge. Always run `make test-diff-coverage` (not only `make test`) before opening or updating a PR, after ensuring the compare branch exists locally (`git fetch origin`).
203209

204210
### Comprehensive Checks
205211

206212
```bash
207213
# Run all checks (lint + test)
208214
make check
209215

210-
# Run comprehensive check script (lint + test + coverage)
216+
# Lint + tests + optional 100% diff-cover (see scripts/check-all.sh header)
217+
git fetch origin
211218
./scripts/check-all.sh
212219
```
213220

@@ -234,6 +241,7 @@ make format # Fix formatting if needed
234241
# Loop until pre-commit passes completely:
235242
pre-commit run --all-files # fix failures → run again → repeat until green
236243
make test # fix failures / coverage → run again → repeat until green
244+
make test-diff-coverage # before PR: 100% on git diff vs origin/main (git fetch origin first)
237245
```
238246

239247
### 2. Fix Linting Errors Immediately
@@ -283,21 +291,23 @@ When in doubt, check the configuration files:
283291
Run tests with coverage until the branch is PR-ready:
284292

285293
```bash
286-
make test # Full test suite with coverage (REQUIRED)
294+
make test # Full test suite with coverage (REQUIRED)
295+
make test-diff-coverage # After git fetch origin: 100% on PR diff vs origin/main (REQUIRED before PR)
287296
```
288297

289-
Review the coverage report for **lines that belong to your PR diff**. If anything is uncovered or tests fail:
298+
`make test-diff-coverage` runs `diff-cover` on `coverage.xml` and lists **only uncovered lines that are part of the git diff**—the same signal as GitHub PR CI. If anything is uncovered or tests fail:
290299

291300
1. Fix tests or implementation, add tests for uncovered paths (edge cases, branches, errors)
292-
2. Re-run `make test` until **all tests pass** and **100% of the diff** is covered (GitHub merge gate).
301+
2. Re-run `make test` then `make test-diff-coverage` until both pass.
293302

294303
Treat “green once” as insufficient if a later fix breaks coverage—re-run the full suite after each substantive change.
295304

296305
### 7. Use Scripts for Comprehensive Checks
297306

298-
The `scripts/check-all.sh` script runs all checks including tests:
307+
The `scripts/check-all.sh` script runs linters, tests (with `coverage.xml`), and—when `diff-cover` is installed and `origin/main` (or `DIFF_COVER_COMPARE_BRANCH`) exists—checks PR-style diff coverage at 100%:
299308

300309
```bash
310+
git fetch origin # recommended so diff-cover can compare
301311
./scripts/check-all.sh
302312
```
303313

@@ -360,13 +370,12 @@ Example addition under `[Unreleased]`:
360370

361371
**Solution**: The **merge gate is 100% coverage on the PR diff**. Ensure every new or changed line in the branch is executed by tests:
362372

363-
1. Run `make test` to see coverage report
364-
2. Identify uncovered lines in your changes (match them to the diff GitHub/CI reports)
365-
3. Write tests for all uncovered code paths
366-
4. Include edge cases, error conditions, and all branches
367-
5. Re-run `make test` until all tests pass **and** diff coverage is 100% on your changes
373+
1. Run `git fetch origin` (or your PR base remote ref) so the compare branch exists
374+
2. Run `make test-diff-coverage`; it prints only **diff** uncovered lines (same tool as CI)
375+
3. Write tests for all uncovered code paths (edge cases, errors, branches)
376+
4. Re-run `make test` then `make test-diff-coverage` until both pass
368377

369-
The CI/CD pipeline uses `diff-cover` (or equivalent) to check only new/changed lines against the merge base; **anything short of 100% on that diff blocks merging the PR in GitHub.** Keep extending tests and re-running `make test` until that bar is met.
378+
The CI/CD pipeline uses `diff-cover` against the merge base; **anything short of 100% on that diff blocks merging the PR in GitHub.**
370379

371380
## References
372381

@@ -385,14 +394,16 @@ The CI/CD pipeline uses `diff-cover` (or equivalent) to check only new/changed l
385394
1. ✅ Run `make lint` to check for linting errors
386395
2. ✅ Run `make format` to ensure proper formatting
387396
3. ✅ Run `pre-commit run --all-files` and **repeat** (fix → re-run) until **all hooks pass**
388-
4. ✅ Run `make test` (full suite) and **repeat** (fix → re-run) until **all tests pass** and **100% diff coverage** is satisfied for GitHub merge
389-
5. ✅ If there are substantive edits that could ship as a PR, **ask whether the user wants PR materials**; **only after they confirm**, draft the paste-ready GitHub PR description **and** update `CHANGELOG.md` when required (same turn)—see **GitHub PR description (ask first; generate on confirmation)** and **Update CHANGELOG.md when drafting the PR**
397+
4. ✅ Run `make test` (full suite) and **repeat** (fix → re-run) until **all tests pass**
398+
5. ✅ Run `make test-diff-coverage` after `git fetch origin` and **repeat** (fix → re-run) until **100% diff coverage** passes (same gate as PR CI)
399+
6. ✅ If there are substantive edits that could ship as a PR, **ask whether the user wants PR materials**; **only after they confirm**, draft the paste-ready GitHub PR description **and** update `CHANGELOG.md` when required (same turn)—see **GitHub PR description (ask first; generate on confirmation)** and **Update CHANGELOG.md when drafting the PR**
390400

391401
**Critical Requirements**:
392402
- **Pre-commit must end clean** - Run `pre-commit run --all-files` in a loop until zero failures; do not stop after one failed run without a subsequent fully passing run
393-
- **Tests must end green with diff coverage** - Run `make test` in a loop until the suite passes and new/changed lines are covered for the PR diff
394-
- **100% diff coverage for GitHub merge** - CI enforces this; extend tests and re-run until the diff is fully covered
403+
- **Tests must end green** - Run `make test` in a loop until the suite passes
404+
- **100% diff coverage before a PR** - Run `make test-diff-coverage` (compare branch defaults to `origin/main`); CI enforces the same; extend tests and re-run until the diff is fully covered
395405
- **Ask before PR text** - End with a short question about drafting the GitHub PR; provide the full paste-ready body only after the user says they are ready
396406
- **`CHANGELOG.md` at PR draft time only** - Do not touch the changelog on every iteration; add `[Unreleased]` entries when the user confirms PR drafting (unless they explicitly ask earlier)
407+
- **`make test-diff-coverage`** - Treat as required before declaring a branch PR-ready alongside `make test`
397408

398409
Following this workflow ensures your changes will pass CI/CD checks and avoids unnecessary pipeline runs.

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
## [Unreleased]
99

1010
### Added
11+
- `make test-diff-coverage` runs `diff-cover` at 100% vs `COMPARE_BRANCH` (default `origin/main`) after `make test`, matching the PR merge gate; `scripts/check-all.sh` also generates `coverage.xml` and runs `diff-cover` when the tool and compare ref exist (`DIFF_COVER_COMPARE_BRANCH` optional)
12+
- `upload --target-arch-repo`: `pulp_results.json` includes per-architecture RPM distribution base URLs under `distributions` with keys `rpm_<arch>` (e.g. `rpm_x86_64`); serialized `distributions` uses sorted keys for stable `{name: url}` output, alongside build-scoped entries when those repos exist
13+
- Upload optionally skips creating logs and SBOM repositories when no log or SBOM uploads are expected; `skip_logs_repo` / `skip_sbom_repo` on `UploadContext` and `PulpHelper.setup_repositories` (defaults preserve creating all repos for programmatic callers who omit the flags)
1114
- `upload --target-arch-repo`: per-architecture RPM repos/distributions (``{namespace}/{arch}/Packages/...``); logs/SBOM/artifacts stay build-scoped; lazy repo creation at upload; works with `--results-json`, `--signed-by`, and `--overwrite`; with `--signed-by`, same arch repo and `signed_by` is label-only
1215
- `upload --overwrite`: RPM-only; remove existing RPM package units in the target repo that match local file SHA256 (and `signed_by` when set) via `remove_content_units` before upload
1316
- `upload --results-json`: Upload artifacts from pulp_results.json; files resolved from JSON directory or --files-base-path; --build-id and --namespace optional (extracted from artifact labels)
@@ -21,6 +24,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2124
- Username/password (Basic Auth) support for packages.redhat.com
2225

2326
### Changed
27+
- `upload --target-arch-repo`: `pulp_results.json` `distributions` keys for per-arch RPM bases are `rpm_<arch>` instead of bare architecture names (e.g. `rpm_x86_64` not `x86_64`)
28+
- `upload` / `upload-files`: infer whether log and SBOM repos are needed before repository setup (directory `*.log` scan or `--results-json` artifact keys; SBOM via `--sbom-path` or SBOM-classified keys); omitted types are excluded from results `distributions`; clear errors if uploads are attempted without the matching repository
2429
- Upload orchestration uses `RpmUploadResult` per architecture instead of ad-hoc dicts; gather/collect uses `PulpContentRow`, `ExtraArtifactRef`, and `FileInfoMap` for clearer typed data flow
2530
- Upload flow populates `pulp_results.json` artifact entries incrementally as RPMs, logs, SBOMs, and generic files finish; final gather still reconciles via merge (keeps incremental entries when keys already exist)
2631
- Repository setup logs use the concrete repo slug (e.g. ``rpms-signed``) instead of a generic ``Rpms`` label; distribution creation logs state that ``name`` and ``base_path`` match the repository name on one line

CONTRIBUTING.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ def my_function(client: "PulpClient", value: Optional[str] = None) -> bool:
114114
# Run all tests with coverage (preferred; enforces 85%+)
115115
make test
116116

117+
# Before a PR: full suite + 100% coverage on git diff vs origin/main (matches CI)
118+
# git fetch origin # ensure compare branch exists
119+
make test-diff-coverage
120+
# Override base branch: make test-diff-coverage COMPARE_BRANCH=origin/my-base
121+
117122
# Or with pytest directly
118123
pytest -v --tb=short --cov=pulp_tool --cov-report=term-missing --cov-fail-under=85
119124

@@ -130,6 +135,7 @@ pytest -m integration
130135
- All new code must include tests
131136
- Overall test coverage must remain at or above 85%
132137
- New and changed lines must have 100% coverage (enforced in CI via diff coverage)
138+
- **Before opening or updating a PR**, run `make test-diff-coverage` after `git fetch origin` so your local report matches the merge gate (`diff-cover` vs `origin/main` by default). Use `make test-diff-coverage COMPARE_BRANCH=origin/<base>` if the PR targets another branch.
133139
- Tests should be fast and isolated
134140
- Use fixtures from `tests/conftest.py` when possible
135141
- Mark slow tests with `@pytest.mark.slow`
@@ -166,13 +172,15 @@ def test_upload_content_success():
166172
1. **Update CHANGELOG.md**: Add an entry describing your changes
167173
2. **Update documentation**: If adding features, update README.md as needed
168174
3. **Run all checks**: Ensure `make check` passes (or run `make lint`, then `pre-commit run --all-files` twice, then `make test`)
169-
4. **Write tests**: Add tests for new functionality (new/changed code requires 100% diff coverage)
170-
5. **Update type hints**: Ensure all functions have proper type annotations
175+
4. **Verify PR diff coverage**: Run `make test-diff-coverage` (requires `git fetch origin` so `origin/main` or your `COMPARE_BRANCH` exists); CI fails below 100% on the diff
176+
5. **Write tests**: Add tests for new functionality (new/changed code requires 100% diff coverage)
177+
6. **Update type hints**: Ensure all functions have proper type annotations
171178

172179
### PR Checklist
173180

174181
- [ ] Code follows the project's style guidelines
175182
- [ ] All tests pass (`make test`)
183+
- [ ] PR diff coverage is 100% (`make test-diff-coverage` after `git fetch origin`)
176184
- [ ] All linters pass (`make lint`)
177185
- [ ] Pre-commit hooks pass (`pre-commit run --all-files`, run twice after fixing issues)
178186
- [ ] Test coverage is maintained or improved (85%+ overall, 100% for new/changed lines)

Makefile

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
# Makefile for pulp-tool development tasks
22

3-
.PHONY: help install install-dev test lint format check clean
3+
COMPARE_BRANCH ?= origin/main
4+
5+
.PHONY: help install install-dev test test-diff-coverage lint format check clean
46

57
# Default target
68
help:
79
@echo "Available targets:"
810
@echo " make install - Install package"
911
@echo " make install-dev - Install package with dev dependencies"
1012
@echo " make test - Run tests with coverage"
13+
@echo " make test-diff-coverage - make test + diff-cover 100% vs COMPARE_BRANCH (same gate as PR CI)"
1114
@echo " make lint - Run all linters"
1215
@echo " make format - Format code with Black"
1316
@echo " make check - Run all checks (lint + test)"
1417
@echo " make clean - Clean build artifacts"
18+
@echo ""
19+
@echo " Diff coverage base: COMPARE_BRANCH=origin/main (override for e.g. origin/release-1.0)"
1520

1621
# Installation
1722
install:
@@ -25,6 +30,13 @@ install-dev:
2530
test:
2631
python3 -m pytest -v --tb=short --cov=pulp_tool --cov-report=term-missing --cov-report=html --cov-report=xml --cov-fail-under=85
2732

33+
# Same as GitHub Actions: 100% coverage on lines changed vs merge base (requires coverage.xml from test).
34+
# Requires diff-cover (included in pip install -e ".[dev]" / make install-dev).
35+
test-diff-coverage: test
36+
@command -v diff-cover >/dev/null 2>&1 || { echo "diff-cover not found. Run: make install-dev"; exit 1; }
37+
@echo "Diff coverage vs $(COMPARE_BRANCH) (fail under 100%)..."
38+
diff-cover coverage.xml --compare-branch=$(COMPARE_BRANCH) --fail-under=100
39+
2840
test-fast:
2941
python3 -m pytest -v --tb=short
3042

README.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ Upload RPM packages, logs, and SBOM files.
139139

140140
**Overwrite:** When `--overwrite` is set, for each RPM about to be uploaded the tool searches Pulp by the file’s SHA256 (same mechanism as `search-by` checksum mode), keeps only matches that exist in the target RPM repository’s latest version, then calls the repository modify API with `remove_content_units` before uploading and adding the new RPMs. Use with `--signed-by` to scope the search to signed packages.
141141

142-
**Target-arch-repo:** When `--target-arch-repo` is set, RPM repositories and distributions are named by architecture only (`{arch}`), including when `--signed-by` is set (no separate `rpms-signed` path). Published paths look like `…/pulp-content/{namespace}/{arch}/`. The aggregate `{build}/rpms` repo is not created; RPM repos are created when each arch is uploaded. Results JSON uses each artifact’s `arch` label to build RPM URLs. Logs, SBOM, and generic artifacts still use `{build}/logs`, `{build}/sbom`, and `{build}/artifacts`.
142+
**Target-arch-repo:** When `--target-arch-repo` is set, RPM repositories and distributions are named by architecture only (`{arch}`), including when `--signed-by` is set (no separate `rpms-signed` path). Published paths look like `…/pulp-content/{namespace}/{arch}/`. The aggregate `{build}/rpms` repo is not created; RPM repos are created when each arch is uploaded. `pulp_results.json` `distributions` maps string names to base URLs (sorted keys when serialized); per-arch RPM bases use keys `rpm_<arch>` (e.g. `rpm_x86_64`). Logs, SBOM, and generic artifacts still use `{build}/logs`, `{build}/sbom`, and `{build}/artifacts`.
143143

144144
### upload-files
145145

@@ -291,14 +291,15 @@ dist.pull_data(filename="pkg.rpm", file_url="...", arch="x86_64", artifact_type=
291291
## Development
292292

293293
```bash
294-
make install-dev # Install with dev deps + pre-commit
294+
make install-dev # Install with dev deps + pre-commit (includes diff-cover)
295295
make test # Run tests with coverage (85%+ required)
296+
make test-diff-coverage # After git fetch origin: 100% coverage on git diff vs origin/main (PR CI gate)
296297
make lint # Black, flake8, pylint, mypy
297298
make format # Format with Black
298299
make check # Lint + test
299300
```
300301

301-
Before committing: `pre-commit run --all-files` (run twice after fixes). See [CONTRIBUTING.md](CONTRIBUTING.md).
302+
Before committing: `pre-commit run --all-files` (run twice after fixes). Before a PR: `git fetch origin` and `make test-diff-coverage`. See [CONTRIBUTING.md](CONTRIBUTING.md).
302303

303304
## Troubleshooting
304305

@@ -314,7 +315,7 @@ Before committing: `pre-commit run --all-files` (run twice after fixes). See [CO
314315
1. Fork the repository
315316
2. Create a feature branch
316317
3. Make changes and add tests
317-
4. Run `make test` and `pre-commit run --all-files`
318+
4. Run `make test`, `make test-diff-coverage` (after `git fetch origin`), and `pre-commit run --all-files`
318319
5. Submit a pull request
319320

320321
## License

0 commit comments

Comments
 (0)