From d52077c944a505f02db2b06972456cb087984726 Mon Sep 17 00:00:00 2001 From: Pete Crocker Date: Sun, 5 Apr 2026 17:08:46 +0100 Subject: [PATCH 1/2] add auto-generated compatibility matrix documentation Add a new reference page documenting SDK-to-Infrahub version compatibility. The page is auto-generated from structured data in docs/docs_generation/compatibility.py via a Jinja2 template, following the same pattern as the existing config and templating reference pages. --- docs/_templates/sdk_compatibility.j2 | 62 +++++++++ docs/docs/python-sdk/introduction.mdx | 1 + .../python-sdk/reference/compatibility.mdx | 91 +++++++++++++ docs/docs_generation/compatibility.py | 127 ++++++++++++++++++ docs/sidebars/sidebars-python-sdk.ts | 1 + tasks.py | 32 +++++ 6 files changed, 314 insertions(+) create mode 100644 docs/_templates/sdk_compatibility.j2 create mode 100644 docs/docs/python-sdk/reference/compatibility.mdx create mode 100644 docs/docs_generation/compatibility.py diff --git a/docs/_templates/sdk_compatibility.j2 b/docs/_templates/sdk_compatibility.j2 new file mode 100644 index 00000000..360d08b6 --- /dev/null +++ b/docs/_templates/sdk_compatibility.j2 @@ -0,0 +1,62 @@ +--- +title: Compatibility matrix +--- +# Compatibility matrix + +This page documents which versions of the Infrahub Python SDK are compatible with each version of Infrahub. + +## Version mapping + +Each Infrahub release pins a specific SDK version. Using the matching SDK version ensures full compatibility. Newer patch releases of the SDK within the same minor version are generally safe to use. + + +| Infrahub | Required SDK | Release date | +| --- | --- | --- | +{% for v in version_ranges %} +| {{ v.infrahub }} | >= {{ v.min_sdk }} | {{ v.date }} | +{% endfor %} + + +## Detailed release mapping + +The table below shows the exact SDK version pinned to each Infrahub release. + + +| Infrahub | SDK version | Infrahub release date | +| --- | --- | --- | +{% for r in release_mappings %} +| {{ r.infrahub }} | {{ r.sdk }} | {{ r.date }} | +{% endfor %} + + +## Python version support + + +| SDK version | Python versions | +| --- | --- | +{% for p in python_support %} +| {{ p.sdk_range }} | {{ p.python_versions }} | +{% endfor %} + + +:::note +The Infrahub server requires Python 3.12 or later. The SDK supports older Python versions so it can be used from environments that do not run the server itself. +::: + +## Feature-specific requirements + +Some SDK features require a minimum Infrahub version: + + +| Feature | Minimum SDK | Minimum Infrahub | +| --- | --- | --- | +{% for f in feature_requirements %} +| {{ f.feature }} | {{ f.min_sdk }} | {{ f.min_infrahub }} | +{% endfor %} + + +## General guidance + +- **Use the SDK version that matches your Infrahub release.** The version mapping table above shows which SDK version was tested and shipped with each Infrahub release. +- **Patch upgrades within a minor SDK version are safe.** For example, if your Infrahub version pins SDK 1.18.0, upgrading to 1.18.1 is safe. +- **Upgrading to a newer minor SDK version may work** but is not guaranteed. New SDK features may depend on server-side changes that are not present in older Infrahub versions. diff --git a/docs/docs/python-sdk/introduction.mdx b/docs/docs/python-sdk/introduction.mdx index 26f945ce..3dcef0f0 100644 --- a/docs/docs/python-sdk/introduction.mdx +++ b/docs/docs/python-sdk/introduction.mdx @@ -33,4 +33,5 @@ The Infrahub Python SDK greatly simplifies how you can interact with Infrahub pr ## Reference - [Client configuration](./reference/config.mdx) +- [Compatibility matrix](./reference/compatibility.mdx) - [Python SDK Release Notes](https://github.com/opsmill/infrahub-sdk-python/releases) diff --git a/docs/docs/python-sdk/reference/compatibility.mdx b/docs/docs/python-sdk/reference/compatibility.mdx new file mode 100644 index 00000000..8d67a4bc --- /dev/null +++ b/docs/docs/python-sdk/reference/compatibility.mdx @@ -0,0 +1,91 @@ +--- +title: Compatibility matrix +--- +# Compatibility matrix + +This page documents which versions of the Infrahub Python SDK are compatible with each version of Infrahub. + +## Version mapping + +Each Infrahub release pins a specific SDK version. Using the matching SDK version ensures full compatibility. Newer patch releases of the SDK within the same minor version are generally safe to use. + + +| Infrahub | Required SDK | Release date | +| --- | --- | --- | +| 1.8.x | >= 1.19.0 | March 2026 | +| 1.7.x | >= 1.18.0 | January 2026 | +| 1.6.x | >= 1.16.0 | December 2025 | +| 1.5.x | >= 1.15.0 | November 2025 | +| 1.4.x | >= 1.13.5 | August 2025 | +| 1.3.x | >= 1.13.0 | June 2025 | + + +## Detailed release mapping + +The table below shows the exact SDK version pinned to each Infrahub release. + + +| Infrahub | SDK version | Infrahub release date | +| --- | --- | --- | +| 1.8.4 | 1.19.0 | 2026-04-02 | +| 1.8.3 | 1.19.0 | 2026-03-31 | +| 1.8.2 | 1.19.0 | 2026-03-25 | +| 1.8.1 | 1.19.0 | 2026-03-19 | +| 1.8.0 | 1.19.0 | 2026-03-16 | +| 1.7.7 | 1.18.1 | 2026-03-12 | +| 1.7.6 | 1.18.1 | 2026-02-25 | +| 1.7.5 | 1.18.1 | 2026-02-24 | +| 1.7.4 | 1.18.1 | 2026-02-03 | +| 1.7.3 | 1.18.1 | 2026-01-28 | +| 1.7.2 | 1.18.1 | 2026-01-27 | +| 1.7.1 | 1.18.1 | 2026-01-12 | +| 1.7.0 | 1.18.1 | 2026-01-09 | +| 1.6.3 | 1.17.0 | 2026-01-07 | +| 1.6.2 | 1.17.0 | 2025-12-22 | +| 1.6.1 | 1.17.0 | 2025-12-11 | +| 1.6.0 | 1.16.0 | 2025-12-01 | +| 1.5.5 | 1.15.1 | 2025-12-22 | +| 1.5.4 | 1.15.1 | 2025-12-16 | +| 1.5.3 | 1.15.1 | 2025-11-24 | +| 1.5.2 | 1.15.1 | 2025-11-18 | +| 1.5.1 | 1.15.1 | 2025-11-13 | +| 1.5.0 | 1.15.0 | 2025-11-10 | +| 1.4.1 | 1.13.5 | 2025-08-27 | +| 1.4.0 | 1.13.5 | 2025-08-26 | +| 1.3.3 | 1.13.3 | 2025-07-15 | +| 1.3.2 | 1.13.3 | 2025-06-30 | +| 1.3.1 | 1.13.2 | 2025-06-27 | +| 1.3.0 | 1.13.0 | 2025-06-12 | + + +## Python version support + + +| SDK version | Python versions | +| --- | --- | +| >= 1.17.0 | 3.10, 3.11, 3.12, 3.13, 3.14 | +| 1.16.0 | 3.10, 3.11, 3.12, 3.13 | +| 1.13.0 - 1.15.x | 3.9, 3.10, 3.11, 3.12, 3.13 | + + +:::note +The Infrahub server requires Python 3.12 or later. The SDK supports older Python versions so it can be used from environments that do not run the server itself. +::: + +## Feature-specific requirements + +Some SDK features require a minimum Infrahub version: + + +| Feature | Minimum SDK | Minimum Infrahub | +| --- | --- | --- | +| infrahubctl branch report | 1.19.0 | 1.7 | +| FileObject support | 1.19.0 | 1.8 | +| NumberPool support | 1.13.0 | 1.3 | + + +## General guidance + +- **Use the SDK version that matches your Infrahub release.** The version mapping table above shows which SDK version was tested and shipped with each Infrahub release. +- **Patch upgrades within a minor SDK version are safe.** For example, if your Infrahub version pins SDK 1.18.0, upgrading to 1.18.1 is safe. +- **Upgrading to a newer minor SDK version may work** but is not guaranteed. New SDK features may depend on server-side changes that are not present in older Infrahub versions. \ No newline at end of file diff --git a/docs/docs_generation/compatibility.py b/docs/docs_generation/compatibility.py new file mode 100644 index 00000000..e27fa326 --- /dev/null +++ b/docs/docs_generation/compatibility.py @@ -0,0 +1,127 @@ +"""Compatibility data between the Infrahub Python SDK and Infrahub server. + +This module provides structured data for auto-generating the compatibility +matrix documentation page. Update the lists below when new releases are made. +""" + +from __future__ import annotations + +from dataclasses import dataclass + + +@dataclass +class ReleaseMapping: + """Maps an Infrahub server release to its pinned SDK version. + + Args: + infrahub: Infrahub server version (e.g. "1.8.4"). + sdk: SDK version pinned to this release (e.g. "1.19.0"). + date: Infrahub release date in YYYY-MM-DD format. + """ + + infrahub: str + sdk: str + date: str + + +@dataclass +class VersionRange: + """Maps an Infrahub minor version series to its minimum required SDK version. + + Args: + infrahub: Infrahub minor version pattern (e.g. "1.8.x"). + min_sdk: Minimum required SDK version (e.g. "1.19.0"). + date: Approximate release month (e.g. "March 2026"). + """ + + infrahub: str + min_sdk: str + date: str + + +@dataclass +class PythonSupport: + """Maps an SDK version range to supported Python versions. + + Args: + sdk_range: SDK version range description (e.g. ">= 1.17.0"). + python_versions: Comma-separated Python versions (e.g. "3.10, 3.11, 3.12, 3.13, 3.14"). + """ + + sdk_range: str + python_versions: str + + +@dataclass +class FeatureRequirement: + """Documents a feature that requires specific minimum versions. + + Args: + feature: Feature name or description. + min_sdk: Minimum SDK version required. + min_infrahub: Minimum Infrahub version required. + """ + + feature: str + min_sdk: str + min_infrahub: str + + +# Mapping of Infrahub minor version series to minimum SDK versions. +# Update this list when a new Infrahub minor version is released. +VERSION_RANGES: list[VersionRange] = [ + VersionRange(infrahub="1.8.x", min_sdk="1.19.0", date="March 2026"), + VersionRange(infrahub="1.7.x", min_sdk="1.18.0", date="January 2026"), + VersionRange(infrahub="1.6.x", min_sdk="1.16.0", date="December 2025"), + VersionRange(infrahub="1.5.x", min_sdk="1.15.0", date="November 2025"), + VersionRange(infrahub="1.4.x", min_sdk="1.13.5", date="August 2025"), + VersionRange(infrahub="1.3.x", min_sdk="1.13.0", date="June 2025"), +] + +# Detailed mapping of every Infrahub release to its pinned SDK version. +# Update this list when a new Infrahub patch release is made. +RELEASE_MAPPINGS: list[ReleaseMapping] = [ + ReleaseMapping(infrahub="1.8.4", sdk="1.19.0", date="2026-04-02"), + ReleaseMapping(infrahub="1.8.3", sdk="1.19.0", date="2026-03-31"), + ReleaseMapping(infrahub="1.8.2", sdk="1.19.0", date="2026-03-25"), + ReleaseMapping(infrahub="1.8.1", sdk="1.19.0", date="2026-03-19"), + ReleaseMapping(infrahub="1.8.0", sdk="1.19.0", date="2026-03-16"), + ReleaseMapping(infrahub="1.7.7", sdk="1.18.1", date="2026-03-12"), + ReleaseMapping(infrahub="1.7.6", sdk="1.18.1", date="2026-02-25"), + ReleaseMapping(infrahub="1.7.5", sdk="1.18.1", date="2026-02-24"), + ReleaseMapping(infrahub="1.7.4", sdk="1.18.1", date="2026-02-03"), + ReleaseMapping(infrahub="1.7.3", sdk="1.18.1", date="2026-01-28"), + ReleaseMapping(infrahub="1.7.2", sdk="1.18.1", date="2026-01-27"), + ReleaseMapping(infrahub="1.7.1", sdk="1.18.1", date="2026-01-12"), + ReleaseMapping(infrahub="1.7.0", sdk="1.18.1", date="2026-01-09"), + ReleaseMapping(infrahub="1.6.3", sdk="1.17.0", date="2026-01-07"), + ReleaseMapping(infrahub="1.6.2", sdk="1.17.0", date="2025-12-22"), + ReleaseMapping(infrahub="1.6.1", sdk="1.17.0", date="2025-12-11"), + ReleaseMapping(infrahub="1.6.0", sdk="1.16.0", date="2025-12-01"), + ReleaseMapping(infrahub="1.5.5", sdk="1.15.1", date="2025-12-22"), + ReleaseMapping(infrahub="1.5.4", sdk="1.15.1", date="2025-12-16"), + ReleaseMapping(infrahub="1.5.3", sdk="1.15.1", date="2025-11-24"), + ReleaseMapping(infrahub="1.5.2", sdk="1.15.1", date="2025-11-18"), + ReleaseMapping(infrahub="1.5.1", sdk="1.15.1", date="2025-11-13"), + ReleaseMapping(infrahub="1.5.0", sdk="1.15.0", date="2025-11-10"), + ReleaseMapping(infrahub="1.4.1", sdk="1.13.5", date="2025-08-27"), + ReleaseMapping(infrahub="1.4.0", sdk="1.13.5", date="2025-08-26"), + ReleaseMapping(infrahub="1.3.3", sdk="1.13.3", date="2025-07-15"), + ReleaseMapping(infrahub="1.3.2", sdk="1.13.3", date="2025-06-30"), + ReleaseMapping(infrahub="1.3.1", sdk="1.13.2", date="2025-06-27"), + ReleaseMapping(infrahub="1.3.0", sdk="1.13.0", date="2025-06-12"), +] + +# Python version support by SDK version range. +PYTHON_SUPPORT: list[PythonSupport] = [ + PythonSupport(sdk_range=">= 1.17.0", python_versions="3.10, 3.11, 3.12, 3.13, 3.14"), + PythonSupport(sdk_range="1.16.0", python_versions="3.10, 3.11, 3.12, 3.13"), + PythonSupport(sdk_range="1.13.0 - 1.15.x", python_versions="3.9, 3.10, 3.11, 3.12, 3.13"), +] + +# Features that require specific minimum versions of both SDK and Infrahub. +FEATURE_REQUIREMENTS: list[FeatureRequirement] = [ + FeatureRequirement(feature="infrahubctl branch report", min_sdk="1.19.0", min_infrahub="1.7"), + FeatureRequirement(feature="FileObject support", min_sdk="1.19.0", min_infrahub="1.8"), + FeatureRequirement(feature="NumberPool support", min_sdk="1.13.0", min_infrahub="1.3"), +] diff --git a/docs/sidebars/sidebars-python-sdk.ts b/docs/sidebars/sidebars-python-sdk.ts index 9f32420b..ea68b6ca 100644 --- a/docs/sidebars/sidebars-python-sdk.ts +++ b/docs/sidebars/sidebars-python-sdk.ts @@ -37,6 +37,7 @@ const referenceItems = getItemsWithOrder( [ 'reference/config', 'reference/templating', + 'reference/compatibility', ], 'reference', ); diff --git a/tasks.py b/tasks.py index 32b13ae6..fe1a0808 100644 --- a/tasks.py +++ b/tasks.py @@ -109,6 +109,37 @@ def _generate_infrahub_sdk_configuration_documentation() -> None: MDXDocPage(page=page, output_path=output_path).to_mdx() +def _generate_infrahub_sdk_compatibility_documentation() -> None: + """Generate documentation for the Infrahub SDK compatibility matrix.""" + from docs.docs_generation.compatibility import ( + FEATURE_REQUIREMENTS, + PYTHON_SUPPORT, + RELEASE_MAPPINGS, + VERSION_RANGES, + ) + from docs.docs_generation.content_gen_methods import Jinja2DocContentGenMethod + from docs.docs_generation.pages import DocPage, MDXDocPage + from infrahub_sdk.template import Jinja2Template + + print(" - Generate Infrahub SDK compatibility documentation") + page = DocPage( + content_gen_method=Jinja2DocContentGenMethod( + template=Jinja2Template( + template=Path("sdk_compatibility.j2"), + template_directory=DOCUMENTATION_DIRECTORY / "_templates", + ), + template_variables={ + "version_ranges": VERSION_RANGES, + "release_mappings": RELEASE_MAPPINGS, + "python_support": PYTHON_SUPPORT, + "feature_requirements": FEATURE_REQUIREMENTS, + }, + ), + ) + output_path = DOCUMENTATION_DIRECTORY / "docs" / "python-sdk" / "reference" / "compatibility.mdx" + MDXDocPage(page=page, output_path=output_path).to_mdx() + + def _generate_infrahub_sdk_template_documentation() -> None: """Generate documentation for the Infrahub SDK template reference.""" from docs.docs_generation.content_gen_methods import Jinja2DocContentGenMethod @@ -360,6 +391,7 @@ def generate_python_sdk(context: Context) -> None: """Generate documentation for the Python SDK.""" _generate_infrahub_sdk_configuration_documentation() _generate_infrahub_sdk_template_documentation() + _generate_infrahub_sdk_compatibility_documentation() _generate_sdk_api_docs(context) From 14175cb6530b53f13b57c3eb9b154c917bb2f935 Mon Sep 17 00:00:00 2001 From: Pete Crocker Date: Sun, 5 Apr 2026 17:36:41 +0100 Subject: [PATCH 2/2] add update script and expanded compatibility data Add update_compatibility.py to fetch version mappings from GitHub API and rewrite compatibility.py automatically. Includes expanded data from running the script (covers all releases back to 0.16.x). --- .../python-sdk/reference/compatibility.mdx | 62 +++- docs/docs_generation/compatibility.py | 66 +++- docs/docs_generation/update_compatibility.py | 341 ++++++++++++++++++ 3 files changed, 465 insertions(+), 4 deletions(-) create mode 100755 docs/docs_generation/update_compatibility.py diff --git a/docs/docs/python-sdk/reference/compatibility.mdx b/docs/docs/python-sdk/reference/compatibility.mdx index 8d67a4bc..0d3842f7 100644 --- a/docs/docs/python-sdk/reference/compatibility.mdx +++ b/docs/docs/python-sdk/reference/compatibility.mdx @@ -13,11 +13,15 @@ Each Infrahub release pins a specific SDK version. Using the matching SDK versio | Infrahub | Required SDK | Release date | | --- | --- | --- | | 1.8.x | >= 1.19.0 | March 2026 | -| 1.7.x | >= 1.18.0 | January 2026 | +| 1.7.x | >= 1.18.1 | January 2026 | | 1.6.x | >= 1.16.0 | December 2025 | | 1.5.x | >= 1.15.0 | November 2025 | | 1.4.x | >= 1.13.5 | August 2025 | | 1.3.x | >= 1.13.0 | June 2025 | +| 1.2.x | >= 1.8.0 | March 2025 | +| 1.1.x | >= 1.3.0 | December 2024 | +| 1.0.x | >= 1.0.0 | October 2024 | +| 0.16.x | >= 0.13.1 | September 2024 | ## Detailed release mapping @@ -50,12 +54,68 @@ The table below shows the exact SDK version pinned to each Infrahub release. | 1.5.2 | 1.15.1 | 2025-11-18 | | 1.5.1 | 1.15.1 | 2025-11-13 | | 1.5.0 | 1.15.0 | 2025-11-10 | +| 1.4.13 | 1.13.5 | 2025-11-06 | +| 1.4.12 | 1.13.5 | 2025-10-23 | +| 1.4.11 | 1.13.5 | 2025-10-17 | +| 1.4.10 | 1.13.5 | 2025-10-01 | +| 1.4.9 | 1.13.5 | 2025-09-26 | +| 1.4.8 | 1.13.5 | 2025-09-23 | +| 1.4.7 | 1.13.5 | 2025-09-16 | +| 1.4.6 | 1.13.5 | 2025-09-10 | +| 1.4.5 | 1.14.0 | 2025-09-08 | +| 1.4.4 | 1.13.5 | 2025-09-03 | +| 1.4.3 | 1.13.5 | 2025-08-29 | +| 1.4.2 | 1.13.5 | 2025-08-28 | | 1.4.1 | 1.13.5 | 2025-08-27 | | 1.4.0 | 1.13.5 | 2025-08-26 | +| 1.3.9 | 1.13.5 | 2025-09-08 | +| 1.3.8 | 1.13.5 | 2025-08-26 | +| 1.3.7 | 1.13.5 | 2025-08-14 | +| 1.3.6 | 1.13.5 | 2025-08-11 | +| 1.3.5 | 1.13.5 | 2025-08-05 | +| 1.3.4 | 1.13.5 | 2025-07-24 | | 1.3.3 | 1.13.3 | 2025-07-15 | | 1.3.2 | 1.13.3 | 2025-06-30 | | 1.3.1 | 1.13.2 | 2025-06-27 | | 1.3.0 | 1.13.0 | 2025-06-12 | +| 1.2.12 | 1.12.1 | 2025-06-03 | +| 1.2.11 | 1.12.1 | 2025-05-23 | +| 1.2.10 | 1.12.1 | 2025-05-14 | +| 1.2.9 | 1.12.0 | 2025-05-07 | +| 1.2.8 | 1.12.0 | 2025-05-01 | +| 1.2.7 | 1.11.1 | 2025-04-28 | +| 1.2.6 | 1.10.2 | 2025-04-18 | +| 1.2.5 | 1.10.2 | 2025-04-12 | +| 1.2.4 | 1.10.1 | 2025-04-04 | +| 1.2.3 | 1.10.0 | 2025-04-01 | +| 1.2.2 | 1.9.2 | 2025-03-28 | +| 1.2.1 | 1.9.1 | 2025-03-26 | +| 1.2.0 | 1.8.0 | 2025-03-21 | +| 1.1.10 | 1.7.2 | 2025-04-01 | +| 1.1.9 | 1.7.2 | 2025-03-17 | +| 1.1.8 | 1.7.2 | 2025-03-08 | +| 1.1.7 | 1.7.0 | 2025-02-18 | +| 1.1.6 | 1.7.1 | 2025-01-31 | +| 1.1.5 | 1.7.0 | 2025-01-24 | +| 1.1.4 | 1.6.1 | 2025-01-17 | +| 1.1.3 | 1.6.0 | 2025-01-16 | +| 1.1.2 | 1.5.0 | 2025-01-09 | +| 1.1.1 | 1.4.0 | 2025-01-06 | +| 1.1.0 | 1.3.0 | 2024-12-30 | +| 1.0.10 | 1.1.0 | 2024-12-20 | +| 1.0.9 | 1.1.0 | 2024-12-13 | +| 1.0.8 | 1.1.0 | 2024-12-03 | +| 1.0.7 | 1.0.1 | 2024-11-20 | +| 1.0.6 | 1.0.1 | 2024-11-18 | +| 1.0.5 | 1.0.1 | 2024-11-15 | +| 1.0.4 | 1.0.1 | 2024-11-13 | +| 1.0.3 | 1.0.0 | 2024-11-08 | +| 1.0.2 | 1.0.0 | 2024-11-06 | +| 1.0.1 | 1.0.0 | 2024-10-31 | +| 0.16.4 | 0.14.0 | 2024-10-17 | +| 0.16.3 | 0.14.0 | 2024-10-10 | +| 0.16.2 | 0.13.1 | 2024-10-01 | +| 0.16.1 | 0.13.1 | 2024-09-25 | ## Python version support diff --git a/docs/docs_generation/compatibility.py b/docs/docs_generation/compatibility.py index e27fa326..2a17ff55 100644 --- a/docs/docs_generation/compatibility.py +++ b/docs/docs_generation/compatibility.py @@ -68,18 +68,22 @@ class FeatureRequirement: # Mapping of Infrahub minor version series to minimum SDK versions. -# Update this list when a new Infrahub minor version is released. +# Auto-updated by update_compatibility.py. VERSION_RANGES: list[VersionRange] = [ VersionRange(infrahub="1.8.x", min_sdk="1.19.0", date="March 2026"), - VersionRange(infrahub="1.7.x", min_sdk="1.18.0", date="January 2026"), + VersionRange(infrahub="1.7.x", min_sdk="1.18.1", date="January 2026"), VersionRange(infrahub="1.6.x", min_sdk="1.16.0", date="December 2025"), VersionRange(infrahub="1.5.x", min_sdk="1.15.0", date="November 2025"), VersionRange(infrahub="1.4.x", min_sdk="1.13.5", date="August 2025"), VersionRange(infrahub="1.3.x", min_sdk="1.13.0", date="June 2025"), + VersionRange(infrahub="1.2.x", min_sdk="1.8.0", date="March 2025"), + VersionRange(infrahub="1.1.x", min_sdk="1.3.0", date="December 2024"), + VersionRange(infrahub="1.0.x", min_sdk="1.0.0", date="October 2024"), + VersionRange(infrahub="0.16.x", min_sdk="0.13.1", date="September 2024"), ] # Detailed mapping of every Infrahub release to its pinned SDK version. -# Update this list when a new Infrahub patch release is made. +# Auto-updated by update_compatibility.py. RELEASE_MAPPINGS: list[ReleaseMapping] = [ ReleaseMapping(infrahub="1.8.4", sdk="1.19.0", date="2026-04-02"), ReleaseMapping(infrahub="1.8.3", sdk="1.19.0", date="2026-03-31"), @@ -104,12 +108,68 @@ class FeatureRequirement: ReleaseMapping(infrahub="1.5.2", sdk="1.15.1", date="2025-11-18"), ReleaseMapping(infrahub="1.5.1", sdk="1.15.1", date="2025-11-13"), ReleaseMapping(infrahub="1.5.0", sdk="1.15.0", date="2025-11-10"), + ReleaseMapping(infrahub="1.4.13", sdk="1.13.5", date="2025-11-06"), + ReleaseMapping(infrahub="1.4.12", sdk="1.13.5", date="2025-10-23"), + ReleaseMapping(infrahub="1.4.11", sdk="1.13.5", date="2025-10-17"), + ReleaseMapping(infrahub="1.4.10", sdk="1.13.5", date="2025-10-01"), + ReleaseMapping(infrahub="1.4.9", sdk="1.13.5", date="2025-09-26"), + ReleaseMapping(infrahub="1.4.8", sdk="1.13.5", date="2025-09-23"), + ReleaseMapping(infrahub="1.4.7", sdk="1.13.5", date="2025-09-16"), + ReleaseMapping(infrahub="1.4.6", sdk="1.13.5", date="2025-09-10"), + ReleaseMapping(infrahub="1.4.5", sdk="1.14.0", date="2025-09-08"), + ReleaseMapping(infrahub="1.4.4", sdk="1.13.5", date="2025-09-03"), + ReleaseMapping(infrahub="1.4.3", sdk="1.13.5", date="2025-08-29"), + ReleaseMapping(infrahub="1.4.2", sdk="1.13.5", date="2025-08-28"), ReleaseMapping(infrahub="1.4.1", sdk="1.13.5", date="2025-08-27"), ReleaseMapping(infrahub="1.4.0", sdk="1.13.5", date="2025-08-26"), + ReleaseMapping(infrahub="1.3.9", sdk="1.13.5", date="2025-09-08"), + ReleaseMapping(infrahub="1.3.8", sdk="1.13.5", date="2025-08-26"), + ReleaseMapping(infrahub="1.3.7", sdk="1.13.5", date="2025-08-14"), + ReleaseMapping(infrahub="1.3.6", sdk="1.13.5", date="2025-08-11"), + ReleaseMapping(infrahub="1.3.5", sdk="1.13.5", date="2025-08-05"), + ReleaseMapping(infrahub="1.3.4", sdk="1.13.5", date="2025-07-24"), ReleaseMapping(infrahub="1.3.3", sdk="1.13.3", date="2025-07-15"), ReleaseMapping(infrahub="1.3.2", sdk="1.13.3", date="2025-06-30"), ReleaseMapping(infrahub="1.3.1", sdk="1.13.2", date="2025-06-27"), ReleaseMapping(infrahub="1.3.0", sdk="1.13.0", date="2025-06-12"), + ReleaseMapping(infrahub="1.2.12", sdk="1.12.1", date="2025-06-03"), + ReleaseMapping(infrahub="1.2.11", sdk="1.12.1", date="2025-05-23"), + ReleaseMapping(infrahub="1.2.10", sdk="1.12.1", date="2025-05-14"), + ReleaseMapping(infrahub="1.2.9", sdk="1.12.0", date="2025-05-07"), + ReleaseMapping(infrahub="1.2.8", sdk="1.12.0", date="2025-05-01"), + ReleaseMapping(infrahub="1.2.7", sdk="1.11.1", date="2025-04-28"), + ReleaseMapping(infrahub="1.2.6", sdk="1.10.2", date="2025-04-18"), + ReleaseMapping(infrahub="1.2.5", sdk="1.10.2", date="2025-04-12"), + ReleaseMapping(infrahub="1.2.4", sdk="1.10.1", date="2025-04-04"), + ReleaseMapping(infrahub="1.2.3", sdk="1.10.0", date="2025-04-01"), + ReleaseMapping(infrahub="1.2.2", sdk="1.9.2", date="2025-03-28"), + ReleaseMapping(infrahub="1.2.1", sdk="1.9.1", date="2025-03-26"), + ReleaseMapping(infrahub="1.2.0", sdk="1.8.0", date="2025-03-21"), + ReleaseMapping(infrahub="1.1.10", sdk="1.7.2", date="2025-04-01"), + ReleaseMapping(infrahub="1.1.9", sdk="1.7.2", date="2025-03-17"), + ReleaseMapping(infrahub="1.1.8", sdk="1.7.2", date="2025-03-08"), + ReleaseMapping(infrahub="1.1.7", sdk="1.7.0", date="2025-02-18"), + ReleaseMapping(infrahub="1.1.6", sdk="1.7.1", date="2025-01-31"), + ReleaseMapping(infrahub="1.1.5", sdk="1.7.0", date="2025-01-24"), + ReleaseMapping(infrahub="1.1.4", sdk="1.6.1", date="2025-01-17"), + ReleaseMapping(infrahub="1.1.3", sdk="1.6.0", date="2025-01-16"), + ReleaseMapping(infrahub="1.1.2", sdk="1.5.0", date="2025-01-09"), + ReleaseMapping(infrahub="1.1.1", sdk="1.4.0", date="2025-01-06"), + ReleaseMapping(infrahub="1.1.0", sdk="1.3.0", date="2024-12-30"), + ReleaseMapping(infrahub="1.0.10", sdk="1.1.0", date="2024-12-20"), + ReleaseMapping(infrahub="1.0.9", sdk="1.1.0", date="2024-12-13"), + ReleaseMapping(infrahub="1.0.8", sdk="1.1.0", date="2024-12-03"), + ReleaseMapping(infrahub="1.0.7", sdk="1.0.1", date="2024-11-20"), + ReleaseMapping(infrahub="1.0.6", sdk="1.0.1", date="2024-11-18"), + ReleaseMapping(infrahub="1.0.5", sdk="1.0.1", date="2024-11-15"), + ReleaseMapping(infrahub="1.0.4", sdk="1.0.1", date="2024-11-13"), + ReleaseMapping(infrahub="1.0.3", sdk="1.0.0", date="2024-11-08"), + ReleaseMapping(infrahub="1.0.2", sdk="1.0.0", date="2024-11-06"), + ReleaseMapping(infrahub="1.0.1", sdk="1.0.0", date="2024-10-31"), + ReleaseMapping(infrahub="0.16.4", sdk="0.14.0", date="2024-10-17"), + ReleaseMapping(infrahub="0.16.3", sdk="0.14.0", date="2024-10-10"), + ReleaseMapping(infrahub="0.16.2", sdk="0.13.1", date="2024-10-01"), + ReleaseMapping(infrahub="0.16.1", sdk="0.13.1", date="2024-09-25"), ] # Python version support by SDK version range. diff --git a/docs/docs_generation/update_compatibility.py b/docs/docs_generation/update_compatibility.py new file mode 100755 index 00000000..d2b7e0d7 --- /dev/null +++ b/docs/docs_generation/update_compatibility.py @@ -0,0 +1,341 @@ +#!/usr/bin/env python3 +"""Fetch Infrahub/SDK version mappings from GitHub and update compatibility.py. + +Queries the GitHub API to discover Infrahub release tags, resolve the SDK +version pinned via the python_sdk submodule for each release, and rewrite +the RELEASE_MAPPINGS and VERSION_RANGES lists in compatibility.py. + +Usage: + uv run python docs/docs_generation/update_compatibility.py + +Set GITHUB_TOKEN in the environment to avoid rate limiting (unauthenticated +requests are limited to 60/hour). +""" + +from __future__ import annotations + +import operator +import os +import re +import sys +from calendar import month_name +from collections import defaultdict +from datetime import datetime, timezone +from pathlib import Path + +import httpx + +INFRAHUB_REPO = "opsmill/infrahub" +SDK_REPO = "opsmill/infrahub-sdk-python" +API_BASE = "https://api.github.com" +TAG_PATTERN = re.compile(r"^infrahub-v(\d+\.\d+\.\d+)$") +SDK_TAG_PATTERN = re.compile(r"^v(\d+\.\d+\.\d+)$") + +COMPATIBILITY_FILE = Path(__file__).parent / "compatibility.py" + + +def _github_headers() -> dict[str, str]: + """Build HTTP headers, including auth token if available.""" + headers = {"Accept": "application/vnd.github+json", "X-GitHub-Api-Version": "2022-11-28"} + token = os.environ.get("GITHUB_TOKEN") + if token: + headers["Authorization"] = f"Bearer {token}" + return headers + + +def _paginated_get(client: httpx.Client, url: str) -> list[dict]: + """Fetch all pages from a paginated GitHub API endpoint. + + Args: + client: httpx client with auth headers configured. + url: Initial API URL to fetch. + + Returns: + Combined list of JSON objects from all pages. + """ + results: list[dict] = [] + while url: + resp = client.get(url) + resp.raise_for_status() + results.extend(resp.json()) + url = resp.headers.get("link", "") + next_match = re.search(r'<([^>]+)>;\s*rel="next"', url) + url = next_match.group(1) if next_match else "" + return results + + +def _fetch_infrahub_tags(client: httpx.Client) -> dict[str, str]: + """Fetch all infrahub-v* tags and return {version: commit_sha}. + + Args: + client: httpx client with auth headers configured. + + Returns: + Dict mapping version strings (e.g. "1.8.4") to commit SHAs. + """ + tags = _paginated_get(client, f"{API_BASE}/repos/{INFRAHUB_REPO}/tags?per_page=100") + result = {} + for tag in tags: + match = TAG_PATTERN.match(tag["name"]) + if match: + result[match.group(1)] = tag["commit"]["sha"] + return result + + +def _fetch_sdk_tags(client: httpx.Client) -> dict[str, str]: + """Fetch all SDK v* tags and return {commit_sha: version}. + + Args: + client: httpx client with auth headers configured. + + Returns: + Dict mapping commit SHAs to version strings (e.g. "1.19.0"). + """ + tags = _paginated_get(client, f"{API_BASE}/repos/{SDK_REPO}/tags?per_page=100") + result = {} + for tag in tags: + match = SDK_TAG_PATTERN.match(tag["name"]) + if match: + result[tag["commit"]["sha"]] = match.group(1) + return result + + +def _get_submodule_sha(client: httpx.Client, commit_sha: str) -> str | None: + """Get the python_sdk submodule commit SHA for an Infrahub commit. + + Args: + client: httpx client with auth headers configured. + commit_sha: The Infrahub commit SHA to inspect. + + Returns: + The submodule commit SHA, or None if not found. + """ + resp = client.get(f"{API_BASE}/repos/{INFRAHUB_REPO}/git/trees/{commit_sha}") + resp.raise_for_status() + for entry in resp.json().get("tree", []): + if entry["path"] == "python_sdk" and entry["mode"] == "160000": + return entry["sha"] + return None + + +def _get_commit_date(client: httpx.Client, repo: str, sha: str) -> str: + """Get the commit date for a SHA. + + Args: + client: httpx client with auth headers configured. + repo: GitHub repo in "owner/repo" format. + sha: Commit SHA. + + Returns: + Date string in YYYY-MM-DD format. + """ + resp = client.get(f"{API_BASE}/repos/{repo}/git/commits/{sha}") + resp.raise_for_status() + date_str = resp.json()["committer"]["date"] + dt = datetime.fromisoformat(date_str.replace("Z", "+00:00")) + return dt.strftime("%Y-%m-%d") + + +def _find_nearest_sdk_version( + client: httpx.Client, + submodule_sha: str, + sdk_tag_map: dict[str, str], +) -> str | None: + """Find the SDK version for a submodule commit. + + Checks if the commit is directly tagged. If not, walks backwards through + ancestors to find the nearest tagged version. + + Args: + client: httpx client with auth headers configured. + submodule_sha: The SDK commit SHA from the submodule. + sdk_tag_map: Mapping of commit SHAs to SDK version strings. + + Returns: + SDK version string, or None if no version could be resolved. + """ + if submodule_sha in sdk_tag_map: + return sdk_tag_map[submodule_sha] + + # Walk up to 50 ancestors to find a tagged commit + current = submodule_sha + for _ in range(50): + resp = client.get(f"{API_BASE}/repos/{SDK_REPO}/git/commits/{current}") + if resp.status_code != 200: + break + parents = resp.json().get("parents", []) + if not parents: + break + current = parents[0]["sha"] + if current in sdk_tag_map: + return sdk_tag_map[current] + + return None + + +def _version_sort_key(version: str) -> tuple[int, ...]: + """Parse a version string into a tuple for sorting. + + Args: + version: Dot-separated version string (e.g. "1.8.4"). + + Returns: + Tuple of integers for comparison. + """ + return tuple(int(x) for x in version.split(".")) + + +def _derive_version_ranges( + release_mappings: list[tuple[str, str, str]], +) -> list[tuple[str, str, str]]: + """Derive VERSION_RANGES from RELEASE_MAPPINGS. + + Groups releases by minor version and finds the minimum SDK version + and earliest release date for each group. + + Args: + release_mappings: List of (infrahub_version, sdk_version, date) tuples. + + Returns: + List of (infrahub_pattern, min_sdk, month_year) tuples, sorted by + version descending. + """ + groups: dict[str, list[tuple[str, str]]] = defaultdict(list) + for infrahub_ver, sdk_ver, date in release_mappings: + parts = infrahub_ver.split(".") + minor_key = f"{parts[0]}.{parts[1]}" + groups[minor_key].append((sdk_ver, date)) + + ranges = [] + for minor_key, entries in groups.items(): + # Find the minimum SDK version (lowest version number) + min_sdk = min(entries, key=lambda e: _version_sort_key(e[0]))[0] + # Find the earliest date for the month label + earliest_date = min(entries, key=operator.itemgetter(1))[1] + dt = datetime.strptime(earliest_date, "%Y-%m-%d").replace(tzinfo=timezone.utc) + month_year = f"{month_name[dt.month]} {dt.year}" + ranges.append((f"{minor_key}.x", min_sdk, month_year)) + + ranges.sort(key=lambda r: _version_sort_key(r[0].replace(".x", ".0")), reverse=True) + return ranges + + +def _format_release_mappings(mappings: list[tuple[str, str, str]]) -> str: + """Format RELEASE_MAPPINGS list as Python source code. + + Args: + mappings: List of (infrahub_version, sdk_version, date) tuples. + + Returns: + Python source for the RELEASE_MAPPINGS list assignment. + """ + lines = [ + "# Detailed mapping of every Infrahub release to its pinned SDK version.", + "# Auto-updated by update_compatibility.py.", + "RELEASE_MAPPINGS: list[ReleaseMapping] = [", + ] + for infrahub_ver, sdk_ver, date in mappings: + lines.append(f' ReleaseMapping(infrahub="{infrahub_ver}", sdk="{sdk_ver}", date="{date}"),') + lines.append("]") + return "\n".join(lines) + + +def _format_version_ranges(ranges: list[tuple[str, str, str]]) -> str: + """Format VERSION_RANGES list as Python source code. + + Args: + ranges: List of (infrahub_pattern, min_sdk, month_year) tuples. + + Returns: + Python source for the VERSION_RANGES list assignment. + """ + lines = [ + "# Mapping of Infrahub minor version series to minimum SDK versions.", + "# Auto-updated by update_compatibility.py.", + "VERSION_RANGES: list[VersionRange] = [", + ] + for pattern, min_sdk, month_year in ranges: + lines.append(f' VersionRange(infrahub="{pattern}", min_sdk="{min_sdk}", date="{month_year}"),') + lines.append("]") + return "\n".join(lines) + + +def _update_file(release_mappings: list[tuple[str, str, str]]) -> None: + """Rewrite the VERSION_RANGES and RELEASE_MAPPINGS in compatibility.py. + + Args: + release_mappings: List of (infrahub_version, sdk_version, date) tuples, + sorted by version descending. + """ + content = COMPATIBILITY_FILE.read_text() + + version_ranges = _derive_version_ranges(release_mappings) + + # Replace VERSION_RANGES block + content = re.sub( + r"# Mapping of Infrahub minor version series.*?^]", + _format_version_ranges(version_ranges), + content, + flags=re.DOTALL | re.MULTILINE, + ) + + # Replace RELEASE_MAPPINGS block + content = re.sub( + r"# Detailed mapping of every Infrahub release.*?^]", + _format_release_mappings(release_mappings), + content, + flags=re.DOTALL | re.MULTILINE, + ) + + COMPATIBILITY_FILE.write_text(content) + + +def main() -> None: + """Fetch version data from GitHub and update compatibility.py.""" + headers = _github_headers() + if "Authorization" not in headers: + print("Warning: GITHUB_TOKEN not set. API rate limit is 60 requests/hour.", file=sys.stderr) + + with httpx.Client(headers=headers, timeout=30) as client: + print("Fetching Infrahub release tags...") + infrahub_tags = _fetch_infrahub_tags(client) + print(f" Found {len(infrahub_tags)} releases") + + print("Fetching SDK version tags...") + sdk_tag_map = _fetch_sdk_tags(client) + print(f" Found {len(sdk_tag_map)} SDK versions") + + release_mappings: list[tuple[str, str, str]] = [] + + sorted_versions = sorted(infrahub_tags.keys(), key=_version_sort_key, reverse=True) + for version in sorted_versions: + commit_sha = infrahub_tags[version] + print(f" Resolving Infrahub {version}...", end=" ", flush=True) + + submodule_sha = _get_submodule_sha(client, commit_sha) + if not submodule_sha: + print("no python_sdk submodule found, skipping") + continue + + sdk_version = _find_nearest_sdk_version(client, submodule_sha, sdk_tag_map) + if not sdk_version: + print("could not resolve SDK version, skipping") + continue + + date = _get_commit_date(client, INFRAHUB_REPO, commit_sha) + release_mappings.append((version, sdk_version, date)) + print(f"SDK {sdk_version} ({date})") + + if not release_mappings: + print("No release mappings found. Check your network or GITHUB_TOKEN.", file=sys.stderr) + sys.exit(1) + + release_mappings.sort(key=lambda r: _version_sort_key(r[0]), reverse=True) + + print(f"\nUpdating {COMPATIBILITY_FILE}...") + _update_file(release_mappings) + print("Done. Run 'uv run invoke docs-generate' to regenerate the docs page.") + + +if __name__ == "__main__": + main()