From c436634f2c192d677a72f0a5f12bd106b783185b Mon Sep 17 00:00:00 2001 From: RomainFloreani Date: Wed, 27 May 2026 09:15:29 -0400 Subject: [PATCH 1/4] Logic for auto-versioning in local conda recipes --- .github/workflows/python_deploy_dev.yml | 1 + pyproject.toml | 14 ++++++++------ recipe.yaml | 5 +++-- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/.github/workflows/python_deploy_dev.yml b/.github/workflows/python_deploy_dev.yml index 62d0205..cbc753a 100644 --- a/.github/workflows/python_deploy_dev.yml +++ b/.github/workflows/python_deploy_dev.yml @@ -24,6 +24,7 @@ jobs: source-repo-names: '["public-noremote-conda-dev"]' conda-channels: '["conda-forge"]' publish-repo-names: '["public-noremote-conda-dev"]' + build-experimental: true secrets: JFROG_ARTIFACTORY_URL: ${{ secrets.JFROG_ARTIFACTORY_URL }} JFROG_ARTIFACTORY_TOKEN: ${{ secrets.JFROG_ARTIFACTORY_TOKEN }} diff --git a/pyproject.toml b/pyproject.toml index 866a397..112d085 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -122,21 +122,23 @@ style = "pep440" vcs = "git" [tool.poetry-dynamic-versioning.substitution] -files = ["grid_apps/_version.py", "recipe.yaml"] +files = ["grid_apps/_version.py", "_version.json"] patterns = [ - { value = '''(^__version__\s*(?::.*?)?=\s*['"])[^'"]*(['"])''', mode = "str" }, - { value = '''(^\s*version\s*(?::.*?)?:\s*['"])[^'"]*(['"])''', mode = "str" }, + '''(^__version__\s*(?::.*?)?=\s*['"])[^'"]*(['"])''', + '''(^{\s*"version"\s*:\s*")[^"]*("\s*})''', ] [tool.poetry-dynamic-versioning.files."grid_apps/_version.py"] persistent-substitution = true initial-content = """ - # Version placeholder that will be replaced during substitution - __version__ = "0.0.0" + __version__ = "0.0.0.dev0" """ -[tool.poetry-dynamic-versioning.files."recipe.yaml"] +[tool.poetry-dynamic-versioning.files."_version.json"] persistent-substitution = true +initial-content = """ +{ "version": "0.0.0.dev0" } +""" [tool.ruff] target-version = "py312" diff --git a/recipe.yaml b/recipe.yaml index f052b8b..9e2773d 100644 --- a/recipe.yaml +++ b/recipe.yaml @@ -2,8 +2,9 @@ schema_version: 1 context: name: "grid-apps" - version: "0.0.0.dev0" # This will be replaced by the actual version in the build process - python_min: "3.12" + # Extract version from auto-generated _version.json + version: ${{ load_from_file("_version.json").version | trim }} + python_min: '3.12' module_name: ${{ name|lower|replace("-", "_") }} package: From 15b7f21fd7ea25ca5ffa1bf09f41bd950e1adbc0 Mon Sep 17 00:00:00 2001 From: RomainFloreani Date: Wed, 27 May 2026 09:54:18 -0400 Subject: [PATCH 2/4] Logic for auto-versioning in local conda recipes --- .gitignore | 3 ++- tests/version_test.py | 60 ++++++++++++++++++------------------------- 2 files changed, 27 insertions(+), 36 deletions(-) diff --git a/.gitignore b/.gitignore index e601eee..a10f99a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -# Byte-compiled / optimized / DLL files +# Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class @@ -148,3 +148,4 @@ pyproject-sha.toml #version ignore grid_apps/_version.py +/_version.json diff --git a/tests/version_test.py b/tests/version_test.py index c5a31df..94c76a2 100644 --- a/tests/version_test.py +++ b/tests/version_test.py @@ -1,4 +1,4 @@ -# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' # Copyright (c) 2022-2026 Mira Geoscience Ltd. ' # ' # This file is part of grid-apps package. ' @@ -6,21 +6,28 @@ # grid-apps is distributed under the terms and conditions of the MIT License ' # (see LICENSE file at the root of this source code package). ' # ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' - - from __future__ import annotations import importlib +import json +import re from pathlib import Path import pytest import yaml -from packaging.version import InvalidVersion, Version +from packaging.version import Version import grid_apps -def get_conda_recipe_version(): +def _get_json_version() -> str: + version_json_path = Path(__file__).resolve().parents[1] / "_version.json" + with version_json_path.open(encoding="utf-8") as file: + version_json = json.load(file) + return version_json["version"] + + +def _get_conda_recipe_version_def() -> str: recipe_path = Path(__file__).resolve().parents[1] / "recipe.yaml" with recipe_path.open(encoding="utf-8") as file: @@ -28,12 +35,6 @@ def get_conda_recipe_version(): return recipe["context"]["version"] -def test_version_is_consistent(): - project_version = Version(grid_apps.__version__) - conda_version = Version(get_conda_recipe_version()) - assert conda_version.base_version == project_version.base_version - - def _version_module_exists(): try: importlib.import_module("grid_apps._version") @@ -42,6 +43,16 @@ def _version_module_exists(): return False +def test_conda_recipe_version_loads_json(): + conda_version_def = _get_conda_recipe_version_def() + regex = ( + r"\$\{\{\s*load_from_file\(\s*['\"](_version\.json)['\"]\s*\)" + r"\s*\.version\b.*\}\}" + ) + regex_match = re.match(regex, conda_version_def) + assert regex_match is not None + + @pytest.mark.skipif( _version_module_exists(), reason="grid_apps._version can be found: package is built", @@ -59,28 +70,7 @@ def test_fallback_version_is_zero(): not _version_module_exists(), reason="grid_apps._version cannot be found: uses a fallback version", ) -def test_conda_version_is_consistent(): +def test_version_json_is_consistent(): project_version = Version(grid_apps.__version__) - conda_version = Version(get_conda_recipe_version()) - - assert conda_version.is_devrelease == project_version.is_devrelease - assert conda_version.is_prerelease == project_version.is_prerelease - assert conda_version.is_postrelease == project_version.is_postrelease - assert conda_version == project_version - - -def test_conda_version_is_pep440(): - version = Version(get_conda_recipe_version()) - assert version is not None - - -def validate_version(version_str): - try: - version = Version(version_str) - return (version.major, version.minor, version.micro, version.pre, version.post) - except InvalidVersion: - return None - - -def test_version_is_valid(): - assert validate_version(grid_apps.__version__) is not None + json_version = Version(_get_json_version()) + assert project_version == json_version \ No newline at end of file From e6e982efe024e963d47268ce29f5cf59c3e6097b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 27 May 2026 13:55:08 +0000 Subject: [PATCH 3/4] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- tests/version_test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/version_test.py b/tests/version_test.py index 94c76a2..42cd95a 100644 --- a/tests/version_test.py +++ b/tests/version_test.py @@ -1,4 +1,4 @@ -# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' +# ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' # Copyright (c) 2022-2026 Mira Geoscience Ltd. ' # ' # This file is part of grid-apps package. ' @@ -73,4 +73,4 @@ def test_fallback_version_is_zero(): def test_version_json_is_consistent(): project_version = Version(grid_apps.__version__) json_version = Version(_get_json_version()) - assert project_version == json_version \ No newline at end of file + assert project_version == json_version From c32983d859693333c840d349b33b9156d3f7b4c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Hensgen?= <24550538+sebhmg@users.noreply.github.com> Date: Wed, 27 May 2026 22:13:00 -0400 Subject: [PATCH 4/4] Apply suggestion from @sebhmg --- tests/version_test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/version_test.py b/tests/version_test.py index 42cd95a..507f0eb 100644 --- a/tests/version_test.py +++ b/tests/version_test.py @@ -6,6 +6,7 @@ # grid-apps is distributed under the terms and conditions of the MIT License ' # (see LICENSE file at the root of this source code package). ' # ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + from __future__ import annotations import importlib