Skip to content

Derive package version from git tag via setuptools-scm (stop hand-maintaining j1939/version.py) #79

Description

@RaulSMS

Problem

Right now the release tag (e.g. 1.2.3) and j1939/version.py's __version__ string are two independently-maintained sources of truth. Nothing enforces they match, so it's easy to push a release tag and forget to bump version.py first (happened while working on #70/#78) — the published sdist/wheel then reports the wrong __version__.

Proposal

Use setuptools-scm to derive the version directly from the git tag at build time, eliminating the possibility of drift.

Changes needed

  1. pyproject.toml

    • Add setuptools-scm to [build-system].requires.
    • Replace dynamic = ["version"] + [tool.setuptools.dynamic] version = { attr = ... } with [tool.setuptools_scm] config (writes a generated _version.py, typically via write_to = "j1939/_version.py").
    • Decide on a local_scheme/version_scheme (e.g. suppress the +g<hash> local part for clean tagged releases, since the PyPI-published artifact is always built from an exact tag).
  2. j1939/version.py

    • Remove the hardcoded __version__ = "..." string; either delete the file or have it re-export from the generated _version.py.
  3. j1939/__init__.py

    • Update from .version import __version__ if the import path changes (e.g. point at _version.py or keep version.py as a thin re-export shim so the public API — j1939.__version__ — is unaffected).
  4. .gitignore

    • Ignore the generated j1939/_version.py (it must not be committed, since it's derived at build/install time).
  5. CI (.github/workflows/CI.yml, publish.yml)

    • Ensure actions/checkout uses fetch-depth: 0 (or fetch-tags: true) in any job that builds the package — setuptools-scm needs full tag history to compute the version, and the default shallow checkout won't have it.
    • No other workflow changes expected; python -m build / pip install -e . already pick up the new backend automatically.
  6. Editable/dev installs

    • Verify pip install -e . still resolves a sane version for local/dev checkouts (untagged commits get something like 0.1.3.dev4+g<hash> — confirm that's acceptable, e.g. doesn't break the Development Status classifier expectations or any code that parses __version__).
  7. Docs

    • Update CONTRIBUTING.md's "Maintainer Deployment Sequence" — step 1 ("Update the version string inside j1939/version.py") goes away entirely; pushing the tag becomes the only step besides the tag itself.

Why this approach (vs. an automated semver-bump bot)

Discussed alongside #70/#78: this repo's release cadence and dependency surface are small enough that a full conventional-commits/release-please style bot would be more machinery than the actual problem warrants. setuptools-scm fixes the specific failure mode (forgetting to sync a file) with no new workflow, no commit-message conventions, and no bot — the tag simply becomes the single source of truth.

Test plan

  • pip install -e . in a fresh checkout reports a sane dev version
  • Tagging a commit (e.g. 0.1.3) and building (python -m build) produces a wheel/sdist with exactly __version__ == "0.1.3"
  • python -m twine check dist/* still passes
  • CI build_check job still passes with the checkout depth change

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions