Skip to content

Release pipeline: no version sync between release drafter and pyproject.toml #5

@tnware

Description

@tnware

Problem Statement

The release pipeline has a version sync gap. Release Drafter computes a semver version from PR labels and tags the GitHub release (e.g., v0.2.0), but the publish workflow builds from pyproject.toml which has its own hardcoded version. Nothing connects these two values — no step bumps pyproject.toml to match the tag, and no step gates the publish if they diverge.

Technical Context

The current flow:

  1. Release Drafter (.github/release-drafter.yml) auto-drafts a GitHub release with a version resolved from PR labels via version-resolver (major/minor/patch). Creates a tag like v0.2.0.
  2. Publish to PyPI (.github/workflows/publish_to_pypi.yml) triggers on release: published. It runs python -m build, which reads version = "0.1.0" from pyproject.toml.
  3. The two versions are completely independent. The tag could say v0.2.0 while PyPI receives 0.1.0.

Failure Scenario

  1. PRs labeled feature are merged → release drafter bumps draft to v0.2.0
  2. Maintainer publishes the GitHub release
  3. python -m build reads version = "0.1.0" from pyproject.toml
  4. twine upload either publishes 0.1.0 (wrong version) or fails if 0.1.0 already exists on PyPI
  5. Git tag says v0.2.0, PyPI says 0.1.0 — or the publish fails entirely

Affected Code Areas

  • pyproject.toml — hardcoded version = "0.1.0"
  • .github/workflows/publish_to_pypi.yml — build and publish step
  • .github/release-drafter.yml — version resolution config

Options

A) Dynamic versioning from git tags (recommended)

Use hatch-vcs to derive the version from the git tag at build time. Remove the hardcoded version from pyproject.toml. The release drafter tag becomes the single source of truth.

Changes:

  • Add hatch-vcs to [build-system] requires in pyproject.toml
  • Replace version = "0.1.0" with dynamic = ["version"]
  • Add [tool.hatch.version] config pointing to VCS
  • No workflow changes needed — python -m build picks up the tag automatically

B) Version gate in publish workflow

Add a step that extracts the version from the release tag, compares it to pyproject.toml, and fails the workflow if they don't match. Forces a manual version bump PR before publishing.

Changes:

  • Add a validation step to publish_to_pypi.yml before the build step
  • Script extracts tag from ${{ github.event.release.tag_name }}, strips v prefix, compares to pyproject.toml

C) Auto-bump in publish workflow

Add a step that writes the tag version into pyproject.toml before building. The tag overrides at publish time.

Changes:

  • Add a sed or Python script step to publish_to_pypi.yml that patches pyproject.toml before build

Acceptance Criteria

  • The version published to PyPI always matches the GitHub release tag
  • It is impossible to publish a mismatched version without an explicit failure
  • The solution works with the existing release-drafter version resolution
  • development.rst is updated to reflect the new version source (see also tracker item Add early validation for fk_field configuration #3)

Non-Goals

  • Changing the release-drafter label/category configuration
  • Migrating away from release-drafter
  • Changing the PyPI publish trigger (remains release: published)

Constraints

  • Must work with hatchling build backend (already in use)
  • Must not break local development (pip install -e .)
  • Must be compatible with the existing CI matrix (testing.yml)

Risk Considerations

Medium. This changes the version source of truth for the package. Option A (hatch-vcs) is well-established and used by many Python packages, but requires testing that pip install -e . still works in development and that the CI build step picks up the tag correctly.

Testing Expectations

  • Verify local pip install -e . works after the change
  • Verify python -m build produces the correct version from a git tag
  • Verify the publish workflow succeeds on a test release (or verify via dry-run)

Metadata

Metadata

Assignees

No one assigned

    Labels

    ciCI/CD and release pipelinesemver:patchPatch version bump

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions