diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8d30a7e..b6a4ec9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,6 +10,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 # hatch-vcs derives the version from git tags - uses: actions/setup-python@v5 with: @@ -30,11 +32,14 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 # hatch-vcs derives the version from git tags - name: Smoke test on glibc 2.34 run: | docker run --rm -v "$PWD":/w -w /w \ quay.io/pypa/manylinux_2_34_x86_64 bash -c ' PY=/opt/python/cp311-cp311/bin/python + git config --global --add safe.directory /w && "$PY" -m pip install -e . pytest && "$PY" scripts/vendor_binaries.py --only gomc-rest-linux-amd64 && "$PY" -m pytest -v diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8c6a5d9..1507cbb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -35,20 +35,14 @@ jobs: plat: manylinux2014_aarch64 steps: - uses: actions/checkout@v4 + with: + # hatch-vcs derives the version from git tags + fetch-depth: 0 - uses: actions/setup-python@v5 with: python-version: "3.11" - - name: Check tag matches project version - if: github.ref_type == 'tag' - shell: bash - run: | - tag="${GITHUB_REF_NAME#v}" - proj=$(python -c "import tomllib,pathlib; print(tomllib.loads(pathlib.Path('pyproject.toml').read_bytes().decode())['project']['version'])") - echo "tag=$tag project.version=$proj" - test "$tag" = "$proj" || { echo "::error::tag $GITHUB_REF_NAME does not match project.version $proj"; exit 1; } - - name: Install build tooling run: python -m pip install --upgrade build wheel @@ -72,19 +66,13 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + fetch-depth: 0 - uses: actions/setup-python@v5 with: python-version: "3.11" - - name: Check tag matches project version - if: github.ref_type == 'tag' - shell: bash - run: | - tag="${GITHUB_REF_NAME#v}" - proj=$(python -c "import tomllib,pathlib; print(tomllib.loads(pathlib.Path('pyproject.toml').read_bytes().decode())['project']['version'])") - test "$tag" = "$proj" || { echo "::error::tag $GITHUB_REF_NAME does not match project.version $proj"; exit 1; } - - name: Build sdist (no binary bundled) run: | python -m pip install --upgrade build diff --git a/RELEASING.md b/RELEASING.md index 2073510..1fe7753 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -6,8 +6,8 @@ Maintainer notes. Users don't need anything here — see [README.md](README.md). Pushing a `v*` tag runs `.github/workflows/release.yml`: -1. **Guard** — the tag must equal `project.version` in `pyproject.toml`, - or every job fails immediately. +1. **Version** — derived from the tag itself by hatch-vcs + (`dynamic = ["version"]`); there is no version string to keep in sync. 2. **Build wheels** (one per platform, each bundling only its matching server binary, downloaded and SHA-256-verified at build time): - `win_amd64` — `gomc-rest.exe` @@ -25,15 +25,17 @@ Pushing a `v*` tag runs `.github/workflows/release.yml`: ## Cutting a release -1. Bump the package version in **both** places (they must match the tag): - - `pyproject.toml` → `project.version` - - `src/gomc_rest/__init__.py` → `__version__` -2. Merge to `main`, then tag that exact version: +Tag `main` and push — that's all. The version comes from the tag +(hatch-vcs), and `__version__` reads the installed package metadata, so +there is nothing to bump anywhere. - ```bash - git tag v0.2.0 - git push origin v0.2.0 - ``` +```bash +git tag v0.2.0 +git push origin v0.2.0 +``` + +Untagged builds get a dev version like `0.1.3.dev2+g1234abc` — handy for +telling local builds apart from releases. If publish fails transiently, re-run the failed jobs for that tag's run from the GitHub Actions UI — PyPI skips files it already has, and the diff --git a/pyproject.toml b/pyproject.toml index 874e531..d82fc7f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,10 +1,12 @@ [build-system] -requires = ["hatchling"] +requires = ["hatchling", "hatch-vcs"] build-backend = "hatchling.build" [project] name = "gomc-rest" -version = "0.1.2" +# The version comes from the git tag (hatch-vcs); releasing is just pushing +# a v* tag — no manual bump anywhere. +dynamic = ["version"] description = "Talk to Mitsubishi PLCs from Python over the MC protocol via a bundled, auto-launched gomc-rest server — with optional REST API exposure." readme = "README.md" requires-python = ">=3.10" @@ -26,6 +28,9 @@ Homepage = "https://github.com/Moge800/gomc_rest_python" "Upstream server" = "https://github.com/Moge800/gomc-rest" "HTTP client" = "https://github.com/Moge800/gomc_rest_client" +[tool.hatch.version] +source = "vcs" + [tool.hatch.build.targets.wheel] packages = ["src/gomc_rest"] # The platform-specific server binaries under gomc_rest/binaries/ are vendored diff --git a/src/gomc_rest/__init__.py b/src/gomc_rest/__init__.py index 1d52e24..8d8141d 100644 --- a/src/gomc_rest/__init__.py +++ b/src/gomc_rest/__init__.py @@ -29,9 +29,14 @@ PLCClient, ) +from importlib.metadata import PackageNotFoundError, version as _pkg_version + from ._server import Server -__version__ = "0.1.2" +try: + __version__ = _pkg_version("gomc-rest") +except PackageNotFoundError: # running from a source tree without install + __version__ = "0.0.0.dev0" def launch(