Skip to content

Commit 2dc6ef7

Browse files
committed
fix: reject prerelease binary versions
1 parent 0be87c7 commit 2dc6ef7

File tree

2 files changed

+35
-5
lines changed

2 files changed

+35
-5
lines changed

scripts/download-binary.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,17 @@ def resolve_latest_server_tag() -> str:
120120
return best[1]
121121

122122

123+
def normalize_server_tag(version: str) -> str:
124+
"""Normalize explicit CLI input to a stable stagehand-server-v3 tag."""
125+
tag = version if version.startswith("stagehand-server-v3/v") else f"stagehand-server-v3/{version}"
126+
if _parse_server_tag(tag) is None:
127+
raise ValueError(
128+
"Invalid stagehand server version. Expected a stable tag like "
129+
"'v3.2.0' or 'stagehand-server-v3/v3.2.0'."
130+
)
131+
return tag
132+
133+
123134
def download_binary(version: str) -> None:
124135
"""Download the binary for the current platform."""
125136
plat, arch = get_platform_info()
@@ -128,7 +139,7 @@ def download_binary(version: str) -> None:
128139

129140
# GitHub release URL
130141
repo = "browserbase/stagehand"
131-
tag = version if version.startswith("stagehand-server-v3/v") else f"stagehand-server-v3/{version}"
142+
tag = normalize_server_tag(version)
132143
url = f"https://github.com/{repo}/releases/download/{tag}/{binary_filename}"
133144

134145
# Destination path

tests/test_sea_binary.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import importlib.util
44
from pathlib import Path
55

6+
import pytest
7+
68
from stagehand.lib import sea_binary
79
from stagehand._version import __version__
810

@@ -22,7 +24,7 @@ def _load_download_binary_module():
2224

2325

2426
def test_resolve_binary_path_defaults_cache_version_to_package_version(
25-
monkeypatch,
27+
monkeypatch: pytest.MonkeyPatch,
2628
tmp_path: Path,
2729
) -> None:
2830
resource_path = tmp_path / "stagehand-test"
@@ -31,7 +33,10 @@ def test_resolve_binary_path_defaults_cache_version_to_package_version(
3133
captured: dict[str, object] = {}
3234

3335
monkeypatch.delenv("STAGEHAND_VERSION", raising=False)
34-
monkeypatch.setattr(sea_binary, "_resource_binary_path", lambda _filename: resource_path)
36+
def _fake_resource_binary_path(_filename: str) -> Path:
37+
return resource_path
38+
39+
monkeypatch.setattr(sea_binary, "_resource_binary_path", _fake_resource_binary_path)
3540

3641
def _fake_copy_to_cache(*, src: Path, filename: str, version: str) -> Path:
3742
captured["src"] = src
@@ -54,13 +59,27 @@ def test_parse_server_tag_rejects_prerelease_tags() -> None:
5459
assert download_binary._parse_server_tag("stagehand-server-v3/v3.20.0+build.1") is None
5560

5661

57-
def test_resolve_latest_server_tag_ignores_dev_releases(monkeypatch) -> None:
62+
def test_normalize_server_tag_rejects_prerelease_input() -> None:
63+
try:
64+
download_binary.normalize_server_tag("v3.20.0-dev")
65+
except ValueError as exc:
66+
assert "stable tag" in str(exc)
67+
else:
68+
raise AssertionError("Expected prerelease version input to be rejected")
69+
70+
71+
def test_resolve_latest_server_tag_ignores_dev_releases(
72+
monkeypatch: pytest.MonkeyPatch,
73+
) -> None:
5874
releases = [
5975
{"tag_name": "stagehand-server-v3/v3.20.0-dev"},
6076
{"tag_name": "stagehand-server-v3/v3.19.1"},
6177
{"tag_name": "stagehand-server-v3/v3.19.0"},
6278
]
6379

64-
monkeypatch.setattr(download_binary, "_http_get_json", lambda _url: releases)
80+
def _fake_http_get_json(_url: str) -> list[dict[str, str]]:
81+
return releases
82+
83+
monkeypatch.setattr(download_binary, "_http_get_json", _fake_http_get_json)
6584

6685
assert download_binary.resolve_latest_server_tag() == "stagehand-server-v3/v3.19.1"

0 commit comments

Comments
 (0)