diff --git a/backend_api_python/app/_version.py b/backend_api_python/app/_version.py index 76ecdf9..5e71a74 100644 --- a/backend_api_python/app/_version.py +++ b/backend_api_python/app/_version.py @@ -14,6 +14,7 @@ from pathlib import Path FALLBACK_VERSION = "0.0.0-dev" TAG_REF_PREFIX = "refs/tags/" +BRANCH_REF_PREFIX = "refs/heads/" def normalize_version(value: object) -> str: @@ -23,6 +24,8 @@ def normalize_version(value: object) -> str: return "" if text.startswith(TAG_REF_PREFIX): text = text[len(TAG_REF_PREFIX) :] + elif text.startswith(BRANCH_REF_PREFIX): + text = text[len(BRANCH_REF_PREFIX) :] if text.startswith("v") and len(text) > 1 and text[1].isdigit(): text = text[1:] return text diff --git a/backend_api_python/scripts/export_openapi.py b/backend_api_python/scripts/export_openapi.py index 562acdd..6dbd76a 100644 --- a/backend_api_python/scripts/export_openapi.py +++ b/backend_api_python/scripts/export_openapi.py @@ -46,6 +46,13 @@ def export_spec(output: Path, fmt: str) -> None: from app.openapi.register import enrich_spec spec_dict = enrich_spec(spec_dict) + # Runtime build/version metadata is intentionally excluded from the + # committed spec. CI exports from branch refs while release images export + # from tags, so keeping this field would make openapi.yaml drift even when + # the API surface has not changed. + info = spec_dict.get("info") + if isinstance(info, dict): + info.pop("x-api-app-version", None) output.parent.mkdir(parents=True, exist_ok=True) diff --git a/backend_api_python/tests/test_app_version.py b/backend_api_python/tests/test_app_version.py index 8b95c17..13439cc 100644 --- a/backend_api_python/tests/test_app_version.py +++ b/backend_api_python/tests/test_app_version.py @@ -25,6 +25,7 @@ def local_temp_dir() -> Iterator[Path]: def test_normalize_version_accepts_common_tag_formats(): assert normalize_version("v3.0.23") == "3.0.23" assert normalize_version("refs/tags/v3.0.23") == "3.0.23" + assert normalize_version("refs/heads/main") == "main" assert normalize_version("3.0.23") == "3.0.23" @@ -73,6 +74,16 @@ def test_floating_tag_falls_back_to_version_file(): ) +def test_branch_ref_falls_back_to_version_file(): + with local_temp_dir() as tmp_path: + (tmp_path / "VERSION").write_text("3.0.22\n", encoding="utf-8") + + assert ( + resolve_app_version({"GITHUB_REF": "refs/heads/main"}, repo_root=tmp_path, app_root=tmp_path, use_git=False) + == "3.0.22" + ) + + def test_missing_sources_return_dev_fallback(): with local_temp_dir() as tmp_path: assert resolve_app_version({}, repo_root=tmp_path, app_root=tmp_path, use_git=False) == FALLBACK_VERSION diff --git a/backend_api_python/tests/test_openapi.py b/backend_api_python/tests/test_openapi.py index 4f17ad1..c73ce63 100644 --- a/backend_api_python/tests/test_openapi.py +++ b/backend_api_python/tests/test_openapi.py @@ -70,4 +70,5 @@ def test_export_script_writes_yaml(tmp_path): ) loaded = yaml.safe_load(out.read_text(encoding="utf-8")) assert loaded["openapi"].startswith("3.") + assert "x-api-app-version" not in loaded.get("info", {}) assert "/health" in loaded["paths"] diff --git a/docs/api/openapi.yaml b/docs/api/openapi.yaml index d955457..16bd95a 100644 --- a/docs/api/openapi.yaml +++ b/docs/api/openapi.yaml @@ -6,7 +6,6 @@ info: url: https://github.com/brokermr810/quantdinger license: name: See repository LICENSE - x-api-app-version: 3.0.22 title: QuantDinger Web API version: 1.0.0 components: