diff --git a/.github/workflows/python_deploy_dev.yml b/.github/workflows/python_deploy_dev.yml index ad24eb9..7f4f264 100644 --- a/.github/workflows/python_deploy_dev.yml +++ b/.github/workflows/python_deploy_dev.yml @@ -19,6 +19,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/.gitignore b/.gitignore index 63e0314..d2f5ff6 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 surface_apps/_version.py +/_version.json diff --git a/pyproject.toml b/pyproject.toml index 07c3f87..66e65e9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -118,21 +118,23 @@ style = "pep440" vcs = "git" [tool.poetry-dynamic-versioning.substitution] -files = ["surface_apps/_version.py", "recipe.yaml"] +files = ["surface_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."surface_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.conda-lock] platforms = ['win-64', 'linux-64'] diff --git a/recipe.yaml b/recipe.yaml index 2210a57..e2fd9cb 100644 --- a/recipe.yaml +++ b/recipe.yaml @@ -2,8 +2,9 @@ schema_version: 1 context: name: "surface-apps" - version: "0.0.0.dev0" # This will be replaced by the actual version in the build process - python_min: "3.10" + # Extract version from auto-generated _version.json + version: ${{ load_from_file("_version.json").version | trim }} + python_min: '3.10' package: name: ${{ name|lower }} diff --git a/tests/version_test.py b/tests/version_test.py index b4ef96c..3903b31 100644 --- a/tests/version_test.py +++ b/tests/version_test.py @@ -10,36 +10,32 @@ from __future__ import annotations import importlib +import json +import re from pathlib import Path import pytest import yaml -from jinja2 import Template -from packaging.version import InvalidVersion, Version +from packaging.version import Version import surface_apps -def get_conda_recipe_version(): - path = Path(__file__).resolve().parents[1] / "recipe.yaml" +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"] - with open(str(path), encoding="utf-8") as file: - content = file.read() - template = Template(content) - rendered_yaml = template.render() - - recipe = yaml.safe_load(rendered_yaml) +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: + recipe = yaml.safe_load(file) return recipe["context"]["version"] -def test_version_is_consistent(): - project_version = Version(surface_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("surface_apps._version") @@ -48,6 +44,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="surface_apps._version can be found: package is built", @@ -65,28 +71,7 @@ def test_fallback_version_is_zero(): not _version_module_exists(), reason="surface_apps._version cannot be found: uses a fallback version", ) -def test_conda_version_is_consistent(): +def test_version_json_is_consistent(): project_version = Version(surface_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(surface_apps.__version__) is not None + json_version = Version(_get_json_version()) + assert project_version == json_version