Skip to content

ci: pre-merge guard for the PyPI release build path (+ CHANGELOG fix)#552

Merged
igerber merged 1 commit into
mainfrom
ci/release-build-guard
Jun 26, 2026
Merged

ci: pre-merge guard for the PyPI release build path (+ CHANGELOG fix)#552
igerber merged 1 commit into
mainfrom
ci/release-build-guard

Conversation

@igerber

@igerber igerber commented Jun 26, 2026

Copy link
Copy Markdown
Owner

Summary

Adds a pre-merge guard for the PyPI release build path and fixes a misfiled CHANGELOG entry.

publish.yml only runs on release: published, so its build path — the manylinux_2_28 containers, checkout@v7 inside glibc-2.28, and the full py3.9–3.14 ABI range — is never exercised by PR CI. The three recent chores (pyo3/numpy 0.29, checkout v7, blas-src 0.14) are all merged but unreleased, so the next release is the first time publish.yml runs with them. This makes that path testable before merge.

  • New reusable build-wheels.yml (workflow_call, input linux_only): the four wheel-build jobs, lifted verbatim from publish.yml. Single source of truth so the guard can't drift from what actually publishes.
  • publish.yml → thin caller: build: uses: ./.github/workflows/build-wheels.yml (full matrix) + the unchanged PyPI-upload job (OIDC trusted publishing, environment: pypi).
  • New release-build-check.yml: calls the reusable workflow build-onlylinux_only (manylinux leg only, the gap rust-test.yml doesn't cover) on PRs, full matrix on workflow_dispatch (manual pre-release rehearsal). Gated on ready-for-ci, path-filtered, not a required check.
  • Lock-test registration: release-build-check.yml added to EXPECTED_JOBS + GUARD_COVERED_WORKFLOWS in tests/test_openai_review.py and to rust-test.yml's path filters, per the existing label-guard convention.
  • CHANGELOG fix: the pyo3/numpy 0.29 ### Security entry was filed under ## [3.5.3] but is unreleased (not in the v3.5.3 tag or its 24 PyPI wheels) — moved to ## [Unreleased]. The checkout v7 chore (chore(deps): bump actions/checkout from 6 to 7 #550) intentionally gets no entry (CI-only, not shipped).

Methodology references

  • N/A — CI infrastructure + release notes; no estimator / math changes.

Validation

  • actionlint: clean (EXIT=0) on all four touched workflows. The one finding was a pre-existing info-level SC2012 (ls | wc -l) inherited verbatim; fixed to find in the build-linux job only (which runs on this PR), so the verbatim argument for the un-executed macOS/Windows/sdist jobs is intact.
  • Lock tests: tests/test_openai_review.py — 250 passed (the guard's if: matches EXPECTED_GUARD, job set matches the tuple, types carry labeled+unlabeled).
  • Verbatim relocation: diff origin/main:publish.yml build-wheels.yml shows only the intended changes (header/workflow_call/linux_only input, three if: ${{ !inputs.linux_only }} gates, publish job moved out).
  • On this PR: because the guard's paths: include the workflow files, adding ready-for-ci runs the new Release build check (manylinux py3.9–3.14, both arches, build-only) — a built-in acceptance test of the new reusable build path.
  • Known gap (by design): the macOS/Windows/sdist legs are linux_only-skipped on PRs and a brand-new workflow_dispatch isn't dispatchable until it's on main, so they get no execution test here. Mitigated by (a) the verbatim relocation, (b) rust-test.yml already building the macOS-accelerate + Windows-default wheels on this PR via identical maturin commands, and (c) a tracked release-checklist step: run the workflow_dispatch full dry-run once before the next release.

Security / privacy

  • Confirm no secrets/PII in this PR: Yes. PyPI publish remains OIDC trusted publishing (no token).

🤖 Generated with Claude Code

Extract publish.yml's wheel-build jobs into a reusable build-wheels.yml
(workflow_call) so the PyPI release build path can be exercised before
merge. publish.yml becomes a thin caller (build via the reusable workflow
+ PyPI upload). New release-build-check.yml runs the SAME reusable workflow
build-only on PRs (manylinux leg, the gap rust-test.yml doesn't cover) and
full-matrix on workflow_dispatch (manual pre-release rehearsal).

Why: pyo3/numpy 0.29, checkout v7, and blas-src 0.14 are all merged but
unreleased, so the next release is the first time publish.yml runs with
them; its manylinux / checkout-v7 / py3.9-3.14 path was never exercised by
PR CI. A single reusable workflow means the guard can't drift from what
actually publishes.

Also:
- Register release-build-check.yml in the workflow-contract lock tests
  (EXPECTED_JOBS + GUARD_COVERED_WORKFLOWS) and add it to rust-test.yml
  path filters, per the existing convention.
- Fix CHANGELOG: the pyo3/numpy 0.29 Security entry was filed under 3.5.3
  but is unreleased (not in the v3.5.3 tag or PyPI wheels) -> moved to
  [Unreleased].

Build jobs are a verbatim relocation; the only logic change is a
shellcheck-clean wheel count in the on-PR-tested build-linux job.
actionlint clean; lock tests (tests/test_openai_review.py) pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Overall Assessment

✅ Looks good. No unmitigated P0/P1 findings.

Executive Summary

  • No estimator, math, weighting, variance/SE, assumptions, or defaults changed; affected methods: none.
  • publish.yml now delegates builds to the reusable build-wheels.yml while keeping the PyPI publish job separate and OIDC-based.
  • release-build-check.yml calls the same reusable workflow for PR manylinux builds and full manual dispatch rehearsal.
  • Guard/path-filter tests were updated for the new workflow contract.
  • I could not run pytest locally because pytest is not installed in this sandbox; changed YAML parsed cleanly.

Methodology

No findings.

Severity: N/A
Impact: No methodology surface changed. docs/methodology/REGISTRY.md does not add or require a deviation for this CI-only diff.
Concrete fix: None.

Code Quality

No findings.

Severity: N/A
Impact: The reusable workflow extraction is scoped and keeps publish-time build logic centralized in .github/workflows/build-wheels.yml:L8-L159; publish.yml remains a thin build-plus-upload caller at .github/workflows/publish.yml:L10-L32.
Concrete fix: None.

Performance

No findings.

Severity: N/A
Impact: CI cost is intentionally gated by ready-for-ci; PR mode limits the reusable build to Linux via linux_only in .github/workflows/release-build-check.yml:L27-L36.
Concrete fix: None.

Maintainability

No findings.

Severity: N/A
Impact: The new guard workflow is included in the ready-for-ci guard lock set and rust-test path filters at tests/test_openai_review.py:L2083-L2135 and .github/workflows/rust-test.yml:L20-L52.
Concrete fix: None.

Tech Debt

No findings.

Severity: N/A
Impact: No new untracked correctness debt introduced. No relevant existing TODO.md item is affected by this CI/changelog diff.
Concrete fix: None.

Security

No findings.

Severity: N/A
Impact: PR build workflow runs with contents: read only, and PyPI publishing remains isolated to the release workflow with id-token: write on the publish job at .github/workflows/publish.yml:L20-L32.
Concrete fix: None.

Documentation/Tests

P3 - Local test execution unavailable in review sandbox.

Impact: I could not execute tests/test_openai_review.py locally because pytest is not installed. Static inspection confirms the YAML parses and the changed lock-test expectations match the new workflow names.
Concrete fix: Ensure CI runs tests/test_openai_review.py, especially TestRustTestWorkflowPathFilter and TestCiWorkflowLabelEventGuard.

@igerber igerber added the ready-for-ci Triggers CI test workflows label Jun 26, 2026
@igerber igerber merged commit ea550e7 into main Jun 26, 2026
47 of 49 checks passed
@igerber igerber deleted the ci/release-build-guard branch June 26, 2026 19:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-ci Triggers CI test workflows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant