Skip to content

Commit 8985d40

Browse files
authored
Use 4th release segment 9.6.2.N for fvtk versioning (#102)
1 parent cd59d04 commit 8985d40

3 files changed

Lines changed: 114 additions & 12 deletions

File tree

ci/cibw/fvtk_backend.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,12 @@
7474

7575

7676
def _version_suffix() -> str:
77-
"""Tag-driven ``VTK_VERSION_SUFFIX`` via setuptools_scm (start at post0).
77+
"""Tag-driven ``VTK_VERSION_SUFFIX`` via setuptools_scm (start at 9.6.2.0).
7878
79-
The PyPI version is driven by git tags: tag ``9.6.2.post0`` -> wheel
80-
``9.6.2.post0``; commits past a tag get ``9.6.2.post1.devN`` (never published,
81-
publish only runs on a release tag). setuptools_scm derives the full PEP 440
79+
The PyPI version is driven by git tags: tag ``9.6.2.0`` -> wheel ``9.6.2.0``;
80+
commits past a tag get ``9.6.2.1.devN`` (never published, publish only runs on
81+
a release tag). The 4th segment is a normal PEP 440 release component (NOT a
82+
.post; see docs/versioning.md). setuptools_scm derives the full PEP 440
8283
version from the repo's tags (honouring ``SETUPTOOLS_SCM_PRETEND_VERSION_FOR_FVTK``
8384
if set); VTK's setup.py.in composes ``{VTK_BASE_VERSION}.{VTK_VERSION_SUFFIX}``,
8485
so we hand it only the suffix (everything past the base + dot).
@@ -95,7 +96,7 @@ def _version_suffix() -> str:
9596
dist_name="fvtk", # so SETUPTOOLS_SCM_PRETEND_VERSION_FOR_FVTK is honoured
9697
version_scheme="guess-next-dev",
9798
local_scheme="no-local-version", # keep dev versions PyPI-upload-clean
98-
fallback_version=f"{VTK_BASE_VERSION}.post0.dev0",
99+
fallback_version=f"{VTK_BASE_VERSION}.0.dev0",
99100
)
100101
except Exception as exc: # noqa: BLE001 - any scm/git failure -> safe default
101102
print(
@@ -111,8 +112,8 @@ def _version_suffix() -> str:
111112
if not version.startswith(prefix):
112113
raise RuntimeError(
113114
f"fvtk_backend: scm version {version!r} does not start with the VTK "
114-
f"base {VTK_BASE_VERSION!r}; tag releases as {VTK_BASE_VERSION}.postN "
115-
f"(e.g. {VTK_BASE_VERSION}.post0)."
115+
f"base {VTK_BASE_VERSION!r}; tag releases as {VTK_BASE_VERSION}.N "
116+
f"(e.g. {VTK_BASE_VERSION}.0)."
116117
)
117118
suffix = version[len(prefix):]
118119
print(f"fvtk_backend: scm version {version} -> VTK_VERSION_SUFFIX={suffix}", flush=True)

docs/versioning.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
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`.

pyproject.toml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,20 @@ requires = ["setuptools<81", "wheel", "setuptools_scm>=8"]
1919
build-backend = "fvtk_backend"
2020
backend-path = ["ci/cibw"]
2121

22-
# Tag-driven PyPI versioning (start at post0). The base is pinned to the VTK
23-
# version this fork is a drop-in for (9.6.2); git tags add the post segment, so a
24-
# release tagged `9.6.2.post0` publishes `fvtk 9.6.2.post0`, `9.6.2.post1`, etc.
22+
# Tag-driven PyPI versioning (start at 9.6.2.0). The base is pinned to the VTK
23+
# version this fork is a drop-in for (9.6.2); git tags add a 4th release segment
24+
# (the fvtk iteration), so a release tagged `9.6.2.0` publishes `fvtk 9.6.2.0`,
25+
# `9.6.2.1`, etc. The 4th segment is a normal PEP 440 release component (NOT a
26+
# .post — fvtk ships code changes, and a real release segment also unlocks
27+
# publishable RCs like `9.6.2.1rc1`). See docs/versioning.md for the full scheme.
2528
# fvtk_backend reads this via setuptools_scm.get_version() and feeds the suffix
2629
# (everything past `9.6.2.`) to VTK's setup.py.in as VTK_VERSION_SUFFIX. Commits
27-
# between tags get `9.6.2.postN.devM` (never published — publish runs only on a
30+
# between tags get `9.6.2.N.devM` (never published — publish runs only on a
2831
# release tag). local_scheme = no-local-version keeps dev versions PyPI-clean.
2932
[tool.setuptools_scm]
3033
version_scheme = "guess-next-dev"
3134
local_scheme = "no-local-version"
32-
fallback_version = "9.6.2.post0.dev0"
35+
fallback_version = "9.6.2.0.dev0"
3336

3437
[project]
3538
name = "fvtk"

0 commit comments

Comments
 (0)