test_release_version.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. """Tests for repository-owned Python release versions."""
  2. from __future__ import annotations
  3. import json
  4. import runpy
  5. from pathlib import Path
  6. from types import SimpleNamespace
  7. import pytest
  8. ROOT = Path(__file__).resolve().parents[3]
  9. SCRIPT = ROOT / "scripts" / "build-python-release.py"
  10. build_python_release = SimpleNamespace(**runpy.run_path(str(SCRIPT)))
  11. def test_repository_version_matches_root_package_json() -> None:
  12. expected = json.loads((ROOT / "package.json").read_text())["version"]
  13. assert build_python_release.repository_version() == expected
  14. def test_release_tag_is_optional_for_non_release_builds() -> None:
  15. build_python_release.validate_release_tag(None, "1.2.3")
  16. def test_release_tag_must_match_repository_version() -> None:
  17. build_python_release.validate_release_tag("python-v1.2.3", "1.2.3")
  18. with pytest.raises(ValueError, match="expected 'python-v1.2.3'"):
  19. build_python_release.validate_release_tag("python-v1.2.4", "1.2.3")
  20. def test_repository_version_accepts_a_prerelease(tmp_path: Path) -> None:
  21. (tmp_path / "package.json").write_text('{"version":"1.2.3-rc.1"}\n')
  22. assert build_python_release.repository_version(tmp_path) == "1.2.3-rc.1"
  23. def test_repository_version_rejects_malformed_versions(tmp_path: Path) -> None:
  24. (tmp_path / "package.json").write_text('{"version":"v1.2"}\n')
  25. with pytest.raises(ValueError, match="must be X.Y.Z"):
  26. build_python_release.repository_version(tmp_path)
  27. def test_pep440_version_spells_a_prerelease_the_python_way() -> None:
  28. # Build backends normalize to this spelling, so the wheel filename and
  29. # metadata checks compare against it rather than the repository version.
  30. assert build_python_release.pep440_version("1.2.3") == "1.2.3"
  31. assert build_python_release.pep440_version("1.2.3-rc.1") == "1.2.3rc1"
  32. assert build_python_release.pep440_version("1.2.3-alpha.2") == "1.2.3a2"
  33. assert build_python_release.pep440_version("1.2.3-beta.10") == "1.2.3b10"
  34. with pytest.raises(ValueError, match="no PEP 440 spelling"):
  35. build_python_release.pep440_version("1.2.3-nightly")
  36. def test_macos_wheel_tag_does_not_claim_unsupported_node_platforms() -> None:
  37. assert build_python_release.PLATFORMS["macos-arm64"][0] == "macosx_14_0_arm64"
  38. assert build_python_release.PLATFORMS["macos-arm64"][1] == "deepseek-harness-sdk-runtime-macos-arm64"
  39. assert build_python_release.PLATFORMS["macos-x64"][0] == "macosx_14_0_x86_64"
  40. assert build_python_release.PLATFORMS["macos-x64"][1] == "deepseek-harness-sdk-runtime-macos-x64"
  41. def test_windows_wheel_tag_and_payload_are_x64_only() -> None:
  42. assert build_python_release.PLATFORMS["win-x64"] == (
  43. "win_amd64",
  44. "deepseek-harness-sdk-runtime-win-x64.exe",
  45. )
  46. assert not any(name.startswith("win-") and name != "win-x64" for name in build_python_release.PLATFORMS)
  47. def test_platform_manifest_rejects_incomplete_entries(tmp_path: Path) -> None:
  48. manifest = tmp_path / "platforms.json"
  49. manifest.write_text('{"macos-arm64":{"tag":"macosx_14_0_arm64"}}\n')
  50. with pytest.raises(ValueError, match="tag and executable fields"):
  51. build_python_release.load_platforms(manifest)
  52. def test_stage_sdk_keeps_distribution_module_and_runtime_pin_distinct(tmp_path: Path) -> None:
  53. destination = tmp_path / "staging"
  54. build_python_release.stage_sdk(destination, "1.2.3")
  55. pyproject = (destination / "pyproject.toml").read_text()
  56. assert 'name = "deepseek-harness-sdk"' in pyproject
  57. assert 'version = "1.2.3"' in pyproject
  58. assert 'license = "MIT"' in pyproject
  59. assert '"deepseek-harness-runtime-bin==1.2.3"' in pyproject
  60. assert 'license-files = ["LICENSE"]' in pyproject
  61. assert (destination / "LICENSE").read_bytes() == (ROOT / "LICENSE").read_bytes()
  62. assert (destination / "src" / "deepseek_harness" / "__init__.py").is_file()
  63. @pytest.mark.parametrize(
  64. ("target", "with_helper"),
  65. [("linux-x64", False), ("macos-arm64", True), ("macos-x64", True), ("win-x64.exe", False)],
  66. )
  67. def test_stage_runtime_copies_platform_payload(
  68. tmp_path: Path, target: str, with_helper: bool
  69. ) -> None:
  70. executable = tmp_path / f"deepseek-harness-sdk-runtime-{target}"
  71. executable.write_bytes(b"runtime")
  72. executable.chmod(0o755)
  73. expected = {executable.name: b"runtime"}
  74. ripgrep = (
  75. executable.with_name(f"{executable.stem}-rg.exe")
  76. if executable.suffix == ".exe"
  77. else Path(f"{executable}-rg")
  78. )
  79. ripgrep.write_bytes(b"ripgrep")
  80. ripgrep.chmod(0o755)
  81. expected[ripgrep.name] = b"ripgrep"
  82. if with_helper:
  83. spawn_helper = Path(f"{executable}-spawn-helper")
  84. spawn_helper.write_bytes(b"helper")
  85. spawn_helper.chmod(0o755)
  86. expected[spawn_helper.name] = b"helper"
  87. destination = tmp_path / "staging"
  88. build_python_release.stage_runtime(destination, "1.2.3", executable, executable.name)
  89. runtime_dir = destination / "src" / "deepseek_harness_runtime" / "runtime"
  90. assert {
  91. path.name: path.read_bytes()
  92. for path in runtime_dir.glob("deepseek-harness-sdk-runtime-*")
  93. } == expected
  94. pyproject = (destination / "pyproject.toml").read_text()
  95. assert 'license = "MIT"' in pyproject
  96. assert 'license-files = ["LICENSE", "THIRD_PARTY_NOTICES.md"]' in pyproject
  97. assert 'dsh = "deepseek_harness_runtime:main"' in pyproject
  98. assert (destination / "platforms.json").read_bytes() == (
  99. ROOT / "python" / "sdk-runtime" / "platforms.json"
  100. ).read_bytes()
  101. assert (destination / "LICENSE").read_bytes() == (ROOT / "LICENSE").read_bytes()
  102. assert (destination / "THIRD_PARTY_NOTICES.md").read_bytes() == (
  103. ROOT / "THIRD_PARTY_NOTICES.md"
  104. ).read_bytes()
  105. def test_stage_runtime_rejects_a_noncanonical_executable_name(tmp_path: Path) -> None:
  106. executable = tmp_path / "renamed.exe"
  107. executable.write_bytes(b"runtime")
  108. with pytest.raises(ValueError, match="must be named deepseek-harness-sdk-runtime-win-x64.exe"):
  109. build_python_release.stage_runtime(
  110. tmp_path / "staging",
  111. "1.2.3",
  112. executable,
  113. "deepseek-harness-sdk-runtime-win-x64.exe",
  114. )