Skip to content

Release pipeline: enforce the version guard on dispatch, clean SBOM, least-privilege jobs (#507) - #525

Merged
kgdunn merged 7 commits into
mainfrom
claude/process-improve-library-issues-hr7xxk-release
Aug 29, 2026
Merged

Release pipeline: enforce the version guard on dispatch, clean SBOM, least-privilege jobs (#507)#525
kgdunn merged 7 commits into
mainfrom
claude/process-improve-library-issues-hr7xxk-release

Conversation

@kgdunn

@kgdunn kgdunn commented Aug 29, 2026

Copy link
Copy Markdown
Owner

Summary

Fixes #507. Closes the three paths around the ENG-21 (#303) publish gate, plus the smaller hardening items from the same issue. No library code changes; everything is in .github/workflows/publish.yml, Makefile, and the release metadata files.

  • Dispatch guard design: the version-vs-tag check now runs on both triggers. On workflow_dispatch the checked-out commit must already carry a v<version> tag matching pyproject.toml, so dispatch becomes a republish-only path (re-run a failed release, re-upload the SBOM). I chose this over a required "expected version" dispatch input because an input only proves the operator typed the same string as the file they are publishing; it does not tie the publish to a deliberate tag on a specific commit. Requiring the existing tag preserves the workflow's stated promise exactly: no tag, no release, regardless of what pyproject.toml holds on the chosen ref. The guard errors also tell the operator what to do (push the tag; dispatch against the tag itself).
  • Changelog gate: the build job asserts a matching ## [X.Y.Z] heading exists in CHANGELOG.md (mirroring the extraction regex) and fails before anything is built or published. The notes-extraction step in the publish job now errors instead of silently falling back to --generate-notes.
  • Release target commit: gh release create passes --target "$(git rev-parse HEAD)". HEAD of the checkout rather than GITHUB_SHA, because a dispatch run may check out inputs.ref, which differs from github.ref.
  • Clean SBOM: the SBOM is generated from a fresh venv containing only the built wheel and its runtime dependency closure; pip/setuptools/wheel are uninstalled from it before the scan, and cyclonedx-bom runs from a separate tooling venv, pointed at the target venv's interpreter. build, cyclonedx-bom, and their transitive deps can no longer appear as components.
  • Least-privilege permissions: workflow-level permissions: {}; the build job (which executes repo code via PEP 517 hooks) gets only contents: read; id-token: write, contents: write, and attestations: write stay on the publish job, which also creates the GitHub release (there is no separate release job). The trusted-publishing/OIDC and attestation setup is otherwise untouched, per the issue's non-goals.
  • Action pin: pypa/gh-action-pypi-publish is pinned to dc37677b2e1c63e2034f94d8a5b11f265b73ba33, resolved via git ls-remote as the current head of release/v1, which is the peeled commit of tag v1.14.2 (noted in a comment next to the pin).
  • Makefile: the release target no longer pulls, builds, or publishes. It prints the tag-gated release instructions (git tag vX.Y.Z && git push origin vX.Y.Z, or workflow_dispatch for a republish) and exits nonzero.

Housekeeping in the same PR: version 1.73.3 in pyproject.toml and CITATION.cff (date-released: 2026-08-29), plus the matching ## [1.73.3] - 2026-08-29 CHANGELOG section and link-footer updates. The version assumes the earlier queued PRs (1.73.x siblings) merge first; their CHANGELOG entries and compare links slot in above/below this one.

Test plan

Full verification needs a real release run (tag push and a dispatch republish); the workflow paths cannot be exercised from CI on this PR. Verified locally:

  • python -c "import yaml; yaml.safe_load(open('.github/workflows/publish.yml'))" parses cleanly
  • The changelog-guard regex and the extraction regex were both tested against the updated CHANGELOG.md: they match 1.73.3 and 1.71.0, and reject a missing version
  • uv run ruff check . and uv run ruff format --check . both pass
  • make release now exits nonzero with the instructions

Checklist

  • Version bumped in pyproject.toml (PATCH for fixes/docs/config, MINOR for new features)
  • Tests added or updated where relevant (not applicable: workflow/Makefile only)
  • ruff check . passes
  • CHANGELOG.md updated

Generated by Claude Code

…lish pipeline (#507)

The ENG-21 gate promised that a typo in pyproject.toml on main cannot
ship a release, but three paths around the gate remained. This closes
them:

- publish.yml: the version guard now also runs on workflow_dispatch,
  which becomes a republish-only path: the checked-out commit must
  already carry the v<version> tag for the version in pyproject.toml.
- publish.yml: the build job additionally asserts CHANGELOG.md has a
  matching "## [X.Y.Z]" heading (mirroring the extraction regex), and
  the notes-extraction step fails loudly instead of silently falling
  back to auto-generated notes.
- publish.yml: gh release create passes --target with the SHA of the
  checked-out commit (HEAD, not GITHUB_SHA, since a dispatch run may
  check out inputs.ref), so the release tag lands on the published
  commit rather than the default branch head.
- publish.yml: the SBOM is generated from a fresh venv containing only
  the built wheel and its runtime closure, with pip/setuptools/wheel
  removed; cyclonedx-bom runs from a separate tooling venv so build
  tooling no longer ships as runtime components.
- publish.yml: permissions are per-job. The build job, which executes
  repo code via PEP 517 hooks, holds only contents: read; id-token,
  contents, and attestations write scopes stay on the publish job.
- publish.yml: pypa/gh-action-pypi-publish is pinned to the commit SHA
  that release/v1 resolves to (v1.14.2) instead of the mutable branch.
- Makefile: the release target no longer builds or publishes; it prints
  the tag-gated release instructions and exits nonzero.

Version 1.73.3; CITATION.cff and CHANGELOG.md updated in step.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019C3XXbJkuSYH9fMryLqNcU
@codecov

codecov Bot commented Aug 29, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

The typecheck gate is red on main itself: the unpinned mcp extra now
resolves to mcp 2.x, where FastMCP was renamed MCPServer, so mypy fails
on mcp_server.py on every branch. This ports the migrated server and the
mcp>=2.0 floor verbatim from #528; the diff no-ops once #528 merges.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019C3XXbJkuSYH9fMryLqNcU

kgdunn commented Aug 29, 2026

Copy link
Copy Markdown
Owner Author

The typecheck failure here is not this PR's: it is red on main's own latest runs. The unpinned mcp extra now resolves to mcp 2.x, where FastMCP was renamed MCPServer, so mypy fails on src/process_improve/mcp_server.py everywhere. The fix is PR #528; its migrated mcp_server.py and mcp>=2.0 floor are ported verbatim into this branch so CI can go green in any merge order. The ported files disappear from this diff once #528 merges.


Generated by Claude Code

claude added 5 commits August 29, 2026 06:26
…e-library-issues-hr7xxk-release

# Conflicts:
#	CHANGELOG.md
#	CITATION.cff
#	pyproject.toml
…e-library-issues-hr7xxk-release

# Conflicts:
#	CHANGELOG.md
#	CITATION.cff
#	pyproject.toml
…e-library-issues-hr7xxk-release

# Conflicts:
#	CHANGELOG.md
#	CITATION.cff
#	pyproject.toml
test_budget_clamped_to_minimum_model_size fails intermittently on any
PR's CI (macOS, assert 3 >= 4) in code this PR does not touch. Root
cause and fix are in #531; ported verbatim so this PR's CI is
deterministic. No-ops once #531 merges.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019C3XXbJkuSYH9fMryLqNcU
…e-library-issues-hr7xxk-release

# Conflicts:
#	CHANGELOG.md
#	CITATION.cff
#	pyproject.toml
@kgdunn
kgdunn merged commit 5461e86 into main Aug 29, 2026
11 checks passed
@kgdunn
kgdunn deleted the claude/process-improve-library-issues-hr7xxk-release branch August 29, 2026 07:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Release pipeline: workflow_dispatch skips the version guard, the SBOM includes build tooling, and make release bypasses the gate entirely

2 participants