From 2e7787ee5a27ed52aa232c2eee9ea174429fe680 Mon Sep 17 00:00:00 2001 From: "Hans J. Johnson" Date: Mon, 20 Jul 2026 18:31:10 -0500 Subject: [PATCH 1/2] ENH: Add YYYYMMDD tweak version for between-tag downstream gating Set the fourth (tweak) version component to the UTC date of the most recent migration-inducing change and export ITK_VERSION_TWEAK and ITK_VERSION_FULL through ITKConfig.cmake. Downstream projects building against untagged commits (e.g. during git bisect) can gate at configure time with ITK_VERSION_FULL VERSION_GREATER_EQUAL M.m.p.YYYYMMDD; version ordering expires the value at each release tag with no extra checklist steps. Policy, recorded in AGENTS.md and the migration-guide index: a change requiring a migration-guide entry or altering public API must bump ITK_VERSION_TWEAK; other key changes may. EXACT find_package matches on the three-component version are preserved. --- AGENTS.md | 8 ++- CMake/ITKConfig.cmake.in | 7 +++ CMake/ITKConfigVersion.cmake.in | 11 +++- CMake/itkVersion.cmake | 4 ++ CMakeLists.txt | 3 +- Documentation/AI/git-commits.md | 9 ++++ Documentation/docs/migration_guides/index.md | 29 +++++++++++ Utilities/Maintenance/BumpVersionTweak.py | 55 ++++++++++++++++++++ 8 files changed, 122 insertions(+), 4 deletions(-) create mode 100755 Utilities/Maintenance/BumpVersionTweak.py diff --git a/AGENTS.md b/AGENTS.md index 175a595bc6d..40fe1454dcf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -35,7 +35,13 @@ the minimum set for the task at hand. 4. **`Update()` is required** — filters don't execute until called; parameter changes after `Update()` need another call. 5. **Link errors → check `itk-module.cmake`** — missing `DEPENDS` or `PRIVATE_DEPENDS` is the usual cause. 6. **Licensing** — verify AI output does not reproduce third-party code in conflict with Apache 2.0. -7. **Verbose committed text is a review-blocking defect** — not a stylistic preference. Reviewers reject PRs whose commit messages, in-source comments, or PR bodies exceed the budgets in [prose-budget.md](./Documentation/AI/prose-budget.md). Cut prose, not code. +7. **Migration or API changes MUST bump `ITK_VERSION_TWEAK`** — any change + that requires a migration-guide entry or alters public API must also set + `ITK_VERSION_TWEAK` in `CMake/itkVersion.cmake` to the landing date + (`YYYYMMDD`, UTC); other key changes may bump it. The tweak component + gives downstream projects fine-grained version gating between release + tags (see `Documentation/docs/migration_guides/index.md`). +8. **Verbose committed text is a review-blocking defect** — not a stylistic preference. Reviewers reject PRs whose commit messages, in-source comments, or PR bodies exceed the budgets in [prose-budget.md](./Documentation/AI/prose-budget.md). Cut prose, not code. ## Resources diff --git a/CMake/ITKConfig.cmake.in b/CMake/ITKConfig.cmake.in index 367b1b096ae..e9557b05fb7 100644 --- a/CMake/ITKConfig.cmake.in +++ b/CMake/ITKConfig.cmake.in @@ -25,6 +25,13 @@ set(ITK_REQUIRED_LINK_FLAGS "@ITK_REQUIRED_LINK_FLAGS@") set(ITK_VERSION_MAJOR "@ITK_VERSION_MAJOR@") set(ITK_VERSION_MINOR "@ITK_VERSION_MINOR@") set(ITK_VERSION_PATCH "@ITK_VERSION_PATCH@") +# Tweak is the YYYYMMDD date of the newest migration/API change; enables +# fine-grained downstream gating between release tags via ITK_VERSION_FULL. +set(ITK_VERSION_TWEAK "@ITK_VERSION_TWEAK@") +set( + ITK_VERSION_FULL + "@ITK_VERSION_MAJOR@.@ITK_VERSION_MINOR@.@ITK_VERSION_PATCH@.@ITK_VERSION_TWEAK@" +) # Remove all legacy code completely. set(ITK_LEGACY_REMOVE "@ITK_LEGACY_REMOVE@") diff --git a/CMake/ITKConfigVersion.cmake.in b/CMake/ITKConfigVersion.cmake.in index 5ce84d5cbcb..5b869e32cb2 100644 --- a/CMake/ITKConfigVersion.cmake.in +++ b/CMake/ITKConfigVersion.cmake.in @@ -1,7 +1,14 @@ -set(PACKAGE_VERSION "@ITK_VERSION_MAJOR@.@ITK_VERSION_MINOR@.@ITK_VERSION_PATCH@") +set( + PACKAGE_VERSION + "@ITK_VERSION_MAJOR@.@ITK_VERSION_MINOR@.@ITK_VERSION_PATCH@.@ITK_VERSION_TWEAK@" +) if(NOT "${PACKAGE_FIND_VERSION}" VERSION_GREATER "${PACKAGE_VERSION}") set(PACKAGE_VERSION_COMPATIBLE 1) # compatible with older - if("${PACKAGE_FIND_VERSION}" VERSION_EQUAL "${PACKAGE_VERSION}") + if( + "${PACKAGE_FIND_VERSION}" VERSION_EQUAL "${PACKAGE_VERSION}" + OR "${PACKAGE_FIND_VERSION}" VERSION_EQUAL + "@ITK_VERSION_MAJOR@.@ITK_VERSION_MINOR@.@ITK_VERSION_PATCH@" + ) set(PACKAGE_VERSION_EXACT 1) # exact match for this version endif() endif() diff --git a/CMake/itkVersion.cmake b/CMake/itkVersion.cmake index e9509ab406a..78358e75de3 100644 --- a/CMake/itkVersion.cmake +++ b/CMake/itkVersion.cmake @@ -2,3 +2,7 @@ set(ITK_VERSION_MAJOR "6") set(ITK_VERSION_MINOR "0") set(ITK_VERSION_PATCH "0") +# Fine-grained ordering between release tags: YYYYMMDD (UTC) of the most +# recent migration-guide or public-API change; bump allowed for other key +# changes. Never reset; must not reach itkConfigure.h (ccache). +set(ITK_VERSION_TWEAK "20260715") diff --git a/CMakeLists.txt b/CMakeLists.txt index d34521cf0bd..2bb691f4e08 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -56,9 +56,10 @@ set( ITK_VERSION "${ITK_VERSION_MAJOR}.${ITK_VERSION_MINOR}.${ITK_VERSION_PATCH}" ) +set(ITK_VERSION_FULL "${ITK_VERSION}.${ITK_VERSION_TWEAK}") project( ITK - VERSION ${ITK_VERSION} + VERSION ${ITK_VERSION_FULL} DESCRIPTION "The Insight Toolkit (ITK) is an open-source, cross-platform toolkit for N-dimensional scientific image processing, segmentation, and registration." HOMEPAGE_URL "https://itk.org" diff --git a/Documentation/AI/git-commits.md b/Documentation/AI/git-commits.md index bca987589b4..442ecd85480 100644 --- a/Documentation/AI/git-commits.md +++ b/Documentation/AI/git-commits.md @@ -51,6 +51,15 @@ authoring any commit body. > work-in-progress, add `[WIP]` to the **PR title** — the GitHub "WIP" app > gates merging on that string; remove it when the PR is ready. +## Migration / API changes: tweak version bump required + +A commit that adds a migration-guide entry or changes public API MUST also +update `ITK_VERSION_TWEAK` in `CMake/itkVersion.cmake` to the landing date +(`YYYYMMDD`, UTC) — run `Utilities/Maintenance/BumpVersionTweak.py`. +Other key changes MAY bump it. The tweak enables +fine-grained downstream version gating between release tags; it is never +reset (see `Documentation/docs/migration_guides/index.md`). + ## Commit Message Length Keep commit messages concise. A 1-line subject plus a short body diff --git a/Documentation/docs/migration_guides/index.md b/Documentation/docs/migration_guides/index.md index 7af7696e24d..05982addebe 100644 --- a/Documentation/docs/migration_guides/index.md +++ b/Documentation/docs/migration_guides/index.md @@ -2,6 +2,35 @@ These migration guides explain how to update major versions of ITK, whic may contain breaking changes to the API. +## Fine-grained versioning between release tags + +ITK's fourth (tweak) version component is the `YYYYMMDD` (UTC) date of the +most recent migration-inducing change on `main`. It exists so downstream +projects building against untagged ITK commits — for example during a +`git bisect` — can make configure-time decisions at day granularity between +release tags: + +```cmake +find_package(ITK REQUIRED) +if(ITK_VERSION_FULL VERSION_GREATER_EQUAL 6.0.0.20260715) + set(BASELINE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Baseline/post-change) +else() + set(BASELINE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Baseline/legacy) +endif() +``` + +`ITK_VERSION_FULL` and `ITK_VERSION_TWEAK` are exported through +`ITKConfig.cmake`. Against an older ITK that predates the tweak component, +`ITK_VERSION_FULL` is unset and the comparison is false, so the legacy +branch is taken. + +Policy: any change that requires a migration-guide entry or alters public +API **must** update `ITK_VERSION_TWEAK` in `CMake/itkVersion.cmake` to the +date the change lands (`Utilities/Maintenance/BumpVersionTweak.py` does +this); other significant changes **may** bump it. The value +is never reset — release tags supersede it, and version ordering makes it +expire naturally. + ```{toctree} :hidden: :maxdepth: 3 diff --git a/Utilities/Maintenance/BumpVersionTweak.py b/Utilities/Maintenance/BumpVersionTweak.py new file mode 100755 index 00000000000..906f458c0e7 --- /dev/null +++ b/Utilities/Maintenance/BumpVersionTweak.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 +"""Set ITK_VERSION_TWEAK in CMake/itkVersion.cmake to a YYYYMMDD date. + +Usage: + BumpVersionTweak.py # bump to today's UTC date + BumpVersionTweak.py 20260801 # bump to an explicit date +""" + +import argparse +import datetime +import re +import sys +from pathlib import Path + +VERSION_FILE = Path(__file__).resolve().parents[2] / "CMake" / "itkVersion.cmake" +PATTERN = re.compile(r'(set\(ITK_VERSION_TWEAK ")(\d{8})("\))') + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument( + "date", + nargs="?", + default=datetime.datetime.now(datetime.UTC).strftime("%Y%m%d"), + help="YYYYMMDD value (default: today, UTC)", + ) + args = parser.parse_args() + + try: + datetime.datetime.strptime(args.date, "%Y%m%d") + except ValueError: + parser.error(f"'{args.date}' is not a valid YYYYMMDD date") + + content = VERSION_FILE.read_text() + match = PATTERN.search(content) + if match is None: + print(f"ERROR: ITK_VERSION_TWEAK not found in {VERSION_FILE}", file=sys.stderr) + return 1 + if args.date < match.group(2): + print( + f"ERROR: {args.date} is older than current tweak {match.group(2)}", + file=sys.stderr, + ) + return 1 + if args.date == match.group(2): + print(f"ITK_VERSION_TWEAK already {args.date}") + return 0 + + VERSION_FILE.write_text(PATTERN.sub(rf"\g<1>{args.date}\g<3>", content)) + print(f"ITK_VERSION_TWEAK: {match.group(2)} -> {args.date}") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) From 3350e61274ab49381dab59ab7f8b577da3d42dd8 Mon Sep 17 00:00:00 2001 From: Hans Johnson Date: Tue, 21 Jul 2026 09:15:27 -0500 Subject: [PATCH 2/2] DOC: Document ITK 6 minimum wrapped Python is 3.11 --- .../docs/migration_guides/itk_6_migration_guide.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/docs/migration_guides/itk_6_migration_guide.md b/Documentation/docs/migration_guides/itk_6_migration_guide.md index 0205b343109..feebaac7a6e 100644 --- a/Documentation/docs/migration_guides/itk_6_migration_guide.md +++ b/Documentation/docs/migration_guides/itk_6_migration_guide.md @@ -640,6 +640,14 @@ target_link_libraries(MyExample ITK::MyModuleModule) For backward compatibility, non-namespaced aliases are created with deprecation warnings. However, new code should use the namespaced `ITK::` targets exclusively. +## Minimum wrapped Python raised to 3.11 + +ITK 6 requires Python 3.11 or newer for Python wrapping; the previous floor was 3.10. Configuring the wrapping against an older interpreter now fails early. + +### What you need to do + +Use Python 3.11+ when building or installing the ITK Python wrapping. The prebuilt `itk` wheels already target 3.11 and newer. + ## NumPy bridge: `image_from_array(arr.T)` is no longer transpose-equivalent to `image_from_array(arr)` ### Rationale