|
| 1 | +# Versioning and releases |
| 2 | + |
| 3 | +fvtk publishes two PyPI projects — **`fvtk`** (the runtime wheel) and |
| 4 | +**`fvtk-sdk`** (headers + CMake config + import libraries). They share one |
| 5 | +version, derived from a single git tag. |
| 6 | + |
| 7 | +## The scheme: `9.6.2.N` |
| 8 | + |
| 9 | +The version is the VTK base this fork is a drop-in for (**`9.6.2`**, frozen) plus |
| 10 | +a **4th release segment `N`** — the fvtk iteration: |
| 11 | + |
| 12 | +``` |
| 13 | +9.6.2.0 first fvtk release of VTK 9.6.2 |
| 14 | +9.6.2.1 next fvtk release (perf levers, opt-in filters, fixes) |
| 15 | +9.6.2.2 ... |
| 16 | +``` |
| 17 | + |
| 18 | +`N` is a normal [PEP 440](https://peps.python.org/pep-0440/) release component, |
| 19 | +incremented every time we ship. The base stays `9.6.2` for the life of the fork |
| 20 | +against VTK 9.6.2; it only changes when we rebase onto a new upstream VTK (then |
| 21 | +`9.7.0.0`, etc.). |
| 22 | + |
| 23 | +### Why a 4th segment and not `.postN` |
| 24 | + |
| 25 | +fvtk ships **real code changes** between releases (devirtualization, LTO/PGO, |
| 26 | +opt-in fast filters, threading fixes). PEP 440 reserves `.postN` for |
| 27 | +*packaging-only* corrections with **no code changes**, so `.post` would |
| 28 | +misdescribe every release as "repackaged VTK 9.6.2." A normal release segment is |
| 29 | +honest, and it also keeps the door open for **publishable pre-releases** — |
| 30 | +`9.6.2.1rc1` is valid, whereas an RC *of* a post-release is not expressible. |
| 31 | + |
| 32 | +### Special case: bare `9.6.2` |
| 33 | + |
| 34 | +A tag of exactly `9.6.2` (no 4th segment) builds with an empty |
| 35 | +`VTK_VERSION_SUFFIX` — reserved for an unmodified, byte-exact official build. |
| 36 | +Normal fork releases always carry the `.N` segment. |
| 37 | + |
| 38 | +## How a version is computed |
| 39 | + |
| 40 | +`setuptools_scm` derives the version from git tags (config in |
| 41 | +`pyproject.toml` `[tool.setuptools_scm]`; consumed by |
| 42 | +`ci/cibw/fvtk_backend.py::_version_suffix`, which feeds everything past `9.6.2.` |
| 43 | +to VTK's `setup.py.in` as `VTK_VERSION_SUFFIX`). `fvtk-sdk` calls the *same* |
| 44 | +function (`ci/build-sdk.sh`), so the two wheels always match. |
| 45 | + |
| 46 | +- **On a tag** (`9.6.2.1`) → exact version `9.6.2.1`. |
| 47 | +- **Between tags** → `9.6.2.N.devM` (next-iteration dev). These build but are |
| 48 | + **never published** — publish runs only on a release. `local_scheme = |
| 49 | + no-local-version` keeps them PyPI-upload-clean. |
| 50 | + |
| 51 | +## Cutting a release |
| 52 | + |
| 53 | +Publishing is gated on a **published GitHub Release**, not a bare tag push. |
| 54 | +A `git push --tags` alone does **not** publish. |
| 55 | + |
| 56 | +1. Pick the next segment `N` (last published `9.6.2.K` → tag `9.6.2.{K+1}`; very |
| 57 | + first release → `9.6.2.0`). |
| 58 | +2. Draft a **GitHub Release** in `pyvista/fvtk` and create the tag `9.6.2.N` from |
| 59 | + it (target the commit you want to ship). |
| 60 | +3. Publishing the Release fires: |
| 61 | + - `.github/workflows/ci.yml` → builds the shipped wheels (Linux LTO abi3 + |
| 62 | + macOS + Windows), runs the bit-exact / pixel-exact gates, then the |
| 63 | + `publish` job (environment **`pypi`**) trusted-publishes `fvtk`. |
| 64 | + - `.github/workflows/sdk.yml` → builds + `publish-sdk` (environment |
| 65 | + **`pypi-sdk`**) trusted-publishes `fvtk-sdk`. |
| 66 | +4. Both use OIDC trusted publishing (no stored tokens). PyPI trusted-publisher |
| 67 | + config: |
| 68 | + |
| 69 | + | project | workflow | environment | |
| 70 | + |------------|-----------|-------------| |
| 71 | + | `fvtk` | `ci.yml` | `pypi` | |
| 72 | + | `fvtk-sdk` | `sdk.yml` | `pypi-sdk` | |
| 73 | + |
| 74 | + For the **first** release of each project (before it exists on PyPI), register |
| 75 | + a **pending** trusted publisher on PyPI with these values. |
| 76 | + |
| 77 | +## Downstream pinning |
| 78 | + |
| 79 | +`9.6.2.N` behaves like any release version — a bare `pip install fvtk` always |
| 80 | +resolves the latest stable (pre-releases excluded by default): |
| 81 | + |
| 82 | +``` |
| 83 | +fvtk==9.6.2.1 # exact build |
| 84 | +fvtk==9.6.2.* # any fvtk built against VTK 9.6.2 |
| 85 | +fvtk~=9.6.2.0 # compatible release: >=9.6.2.0, <9.6.3 |
| 86 | +fvtk>=9.6.2.1 # floor |
| 87 | +``` |
| 88 | + |
| 89 | +Downstream libraries that need a specific fork iteration pin `==9.6.2.N`; those |
| 90 | +that only care about the VTK base pin `==9.6.2.*`. Pin `fvtk` and `fvtk-sdk` to |
| 91 | +the same version — they are released in lockstep. |
| 92 | + |
| 93 | +## Rebasing onto a new VTK |
| 94 | + |
| 95 | +When fvtk moves to a new upstream VTK (say 9.7.0), bump `VTK_BASE_VERSION` |
| 96 | +(`ci/cibw/fvtk_backend.py`) and the base in `pyproject.toml`, then restart the |
| 97 | +segment at `9.7.0.0`. PEP 440 ordering keeps the lines distinct: |
| 98 | +`9.6.2.5 < 9.7.0.0`. |
0 commit comments