From 6f49624a7205179529d25e0c49bb84f776dd28d4 Mon Sep 17 00:00:00 2001 From: openhands Date: Sun, 15 Mar 2026 20:58:42 +0000 Subject: [PATCH 1/3] chore(agent-server): bump version for REST API breakage checks Bump openhands-agent-server from 1.14.0 to 1.15.0 so the REST API breakage workflow reflects the current breaking API surface already present on main. This is intentionally separate from PR #2455, whose failing REST API check is unrelated to the browser timeout fix. Co-authored-by: openhands --- openhands-agent-server/pyproject.toml | 2 +- uv.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/openhands-agent-server/pyproject.toml b/openhands-agent-server/pyproject.toml index c7573f4b6f..5d5b2ea6c0 100644 --- a/openhands-agent-server/pyproject.toml +++ b/openhands-agent-server/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "openhands-agent-server" -version = "1.14.0" +version = "1.15.0" description = "OpenHands Agent Server - REST/WebSocket interface for OpenHands AI Agent" requires-python = ">=3.12" diff --git a/uv.lock b/uv.lock index 6fce0cbd5e..c25bb3c1e0 100644 --- a/uv.lock +++ b/uv.lock @@ -2341,7 +2341,7 @@ wheels = [ [[package]] name = "openhands-agent-server" -version = "1.14.0" +version = "1.15.0" source = { editable = "openhands-agent-server" } dependencies = [ { name = "aiosqlite" }, From 2368c7f7e03abe7973a4323fdb6d3d8508c2949e Mon Sep 17 00:00:00 2001 From: enyst Date: Sun, 15 Mar 2026 21:16:49 +0000 Subject: [PATCH 2/3] ci: guard package version bumps outside release PRs Co-authored-by: openhands --- .github/scripts/check_version_bumps.py | 196 +++++++++++++++++++ .github/workflows/version-bump-guard.yml | 25 +++ openhands-agent-server/pyproject.toml | 2 +- tests/ci_scripts/test_check_version_bumps.py | 137 +++++++++++++ uv.lock | 2 +- 5 files changed, 360 insertions(+), 2 deletions(-) create mode 100644 .github/scripts/check_version_bumps.py create mode 100644 .github/workflows/version-bump-guard.yml create mode 100644 tests/ci_scripts/test_check_version_bumps.py diff --git a/.github/scripts/check_version_bumps.py b/.github/scripts/check_version_bumps.py new file mode 100644 index 0000000000..033f1e35de --- /dev/null +++ b/.github/scripts/check_version_bumps.py @@ -0,0 +1,196 @@ +"""Guard package version changes so they only happen in release PRs.""" + +from __future__ import annotations + +import os +import re +import subprocess +import sys +import tomllib +from dataclasses import dataclass +from pathlib import Path + + +PACKAGE_PYPROJECTS: dict[str, Path] = { + "openhands-sdk": Path("openhands-sdk/pyproject.toml"), + "openhands-tools": Path("openhands-tools/pyproject.toml"), + "openhands-workspace": Path("openhands-workspace/pyproject.toml"), + "openhands-agent-server": Path("openhands-agent-server/pyproject.toml"), +} + +_VERSION_PATTERN = r"\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.]+)?" +_RELEASE_TITLE_RE = re.compile(rf"^Release v(?P{_VERSION_PATTERN})$") +_RELEASE_BRANCH_RE = re.compile(rf"^rel-(?P{_VERSION_PATTERN})$") + + +@dataclass(frozen=True) +class VersionChange: + package: str + path: Path + previous_version: str + current_version: str + + +def _read_version_from_pyproject_text(text: str, source: str) -> str: + data = tomllib.loads(text) + version = data.get("project", {}).get("version") + if not isinstance(version, str): + raise SystemExit(f"Unable to determine project.version from {source}") + return version + + +def _read_current_version(repo_root: Path, pyproject: Path) -> str: + return _read_version_from_pyproject_text( + (repo_root / pyproject).read_text(), + str(pyproject), + ) + + +def _read_version_from_git_ref(repo_root: Path, git_ref: str, pyproject: Path) -> str: + result = subprocess.run( + ["git", "show", f"{git_ref}:{pyproject.as_posix()}"], + cwd=repo_root, + check=False, + capture_output=True, + text=True, + ) + if result.returncode != 0: + message = result.stderr.strip() or result.stdout.strip() or "unknown git error" + raise SystemExit( + f"Unable to read {pyproject} from git ref {git_ref}: {message}" + ) + return _read_version_from_pyproject_text(result.stdout, f"{git_ref}:{pyproject}") + + +def _base_ref_candidates(base_ref: str) -> list[str]: + if base_ref.startswith("origin/"): + return [base_ref, base_ref.removeprefix("origin/")] + return [f"origin/{base_ref}", base_ref] + + +def find_version_changes(repo_root: Path, base_ref: str) -> list[VersionChange]: + changes: list[VersionChange] = [] + candidates = _base_ref_candidates(base_ref) + + for package, pyproject in PACKAGE_PYPROJECTS.items(): + current_version = _read_current_version(repo_root, pyproject) + previous_error: SystemExit | None = None + previous_version: str | None = None + + for candidate in candidates: + try: + previous_version = _read_version_from_git_ref( + repo_root, candidate, pyproject + ) + break + except SystemExit as exc: + previous_error = exc + + if previous_version is None: + assert previous_error is not None + raise previous_error + + if previous_version != current_version: + changes.append( + VersionChange( + package=package, + path=pyproject, + previous_version=previous_version, + current_version=current_version, + ) + ) + + return changes + + +def get_release_pr_version( + pr_title: str, pr_head_ref: str +) -> tuple[str | None, list[str]]: + title_match = _RELEASE_TITLE_RE.fullmatch(pr_title.strip()) + branch_match = _RELEASE_BRANCH_RE.fullmatch(pr_head_ref.strip()) + title_version = title_match.group("version") if title_match else None + branch_version = branch_match.group("version") if branch_match else None + + if title_version and branch_version and title_version != branch_version: + return None, [ + "Release PR markers disagree: title requests " + f"v{title_version} but branch is rel-{branch_version}." + ] + + return title_version or branch_version, [] + + +def validate_version_changes( + changes: list[VersionChange], + pr_title: str, + pr_head_ref: str, +) -> list[str]: + if not changes: + return [] + + release_version, errors = get_release_pr_version(pr_title, pr_head_ref) + if errors: + return errors + + formatted_changes = ", ".join( + f"{change.package} ({change.previous_version} -> {change.current_version})" + for change in changes + ) + + if release_version is None: + return [ + "Package version changes are only allowed in release PRs. " + f"Detected changes: {formatted_changes}. " + "Use the Prepare Release workflow so the PR title is 'Release vX.Y.Z' " + "or the branch is 'rel-X.Y.Z'." + ] + + mismatched = [ + change for change in changes if change.current_version != release_version + ] + if mismatched: + mismatch_details = ", ".join( + f"{change.package} ({change.current_version})" for change in mismatched + ) + return [ + f"Release PR version v{release_version} does not match changed package " + f"versions: {mismatch_details}." + ] + + return [] + + +def main() -> int: + repo_root = Path(__file__).resolve().parents[2] + base_ref = os.environ.get("VERSION_BUMP_BASE_REF") or os.environ.get( + "GITHUB_BASE_REF" + ) + if not base_ref: + print("::warning title=Version bump guard::No base ref found; skipping check.") + return 0 + + pr_title = os.environ.get("PR_TITLE", "") + pr_head_ref = os.environ.get("PR_HEAD_REF", "") + + changes = find_version_changes(repo_root, base_ref) + errors = validate_version_changes(changes, pr_title, pr_head_ref) + + if errors: + for error in errors: + print(f"::error title=Version bump guard::{error}") + return 1 + + if changes: + changed_packages = ", ".join(change.package for change in changes) + print( + "::notice title=Version bump guard::" + f"Release PR version changes validated for {changed_packages}." + ) + else: + print("::notice title=Version bump guard::No package version changes detected.") + + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/.github/workflows/version-bump-guard.yml b/.github/workflows/version-bump-guard.yml new file mode 100644 index 0000000000..099ae1fb85 --- /dev/null +++ b/.github/workflows/version-bump-guard.yml @@ -0,0 +1,25 @@ +--- +name: Version bump guard + +on: + pull_request: + branches: [main] + +jobs: + version-bump-guard: + name: Check package versions + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Validate package version changes + env: + VERSION_BUMP_BASE_REF: ${{ github.base_ref }} + PR_TITLE: ${{ github.event.pull_request.title }} + PR_HEAD_REF: ${{ github.event.pull_request.head.ref }} + run: python3 .github/scripts/check_version_bumps.py diff --git a/openhands-agent-server/pyproject.toml b/openhands-agent-server/pyproject.toml index 5d5b2ea6c0..c7573f4b6f 100644 --- a/openhands-agent-server/pyproject.toml +++ b/openhands-agent-server/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "openhands-agent-server" -version = "1.15.0" +version = "1.14.0" description = "OpenHands Agent Server - REST/WebSocket interface for OpenHands AI Agent" requires-python = ">=3.12" diff --git a/tests/ci_scripts/test_check_version_bumps.py b/tests/ci_scripts/test_check_version_bumps.py new file mode 100644 index 0000000000..bbb5531422 --- /dev/null +++ b/tests/ci_scripts/test_check_version_bumps.py @@ -0,0 +1,137 @@ +"""Tests for the version bump guard script.""" + +from __future__ import annotations + +import importlib.util +import subprocess +import sys +from pathlib import Path + + +def _load_prod_module(): + repo_root = Path(__file__).resolve().parents[2] + script_path = repo_root / ".github" / "scripts" / "check_version_bumps.py" + name = "check_version_bumps" + spec = importlib.util.spec_from_file_location(name, script_path) + assert spec and spec.loader + mod = importlib.util.module_from_spec(spec) + sys.modules[name] = mod + spec.loader.exec_module(mod) + return mod + + +_prod = _load_prod_module() +VersionChange = _prod.VersionChange +find_version_changes = _prod.find_version_changes +get_release_pr_version = _prod.get_release_pr_version +validate_version_changes = _prod.validate_version_changes + + +def _write_version(pyproject: Path, version: str) -> None: + pyproject.write_text( + f'[project]\nname = "{pyproject.parent.name}"\nversion = "{version}"\n' + ) + + +def _init_repo_with_versions(tmp_path: Path, version: str) -> Path: + repo_root = tmp_path / "repo" + repo_root.mkdir() + + for package_dir in ( + "openhands-sdk", + "openhands-tools", + "openhands-workspace", + "openhands-agent-server", + ): + package_path = repo_root / package_dir + package_path.mkdir() + _write_version(package_path / "pyproject.toml", version) + + subprocess.run(["git", "init", "-b", "main"], cwd=repo_root, check=True) + subprocess.run(["git", "config", "user.name", "test"], cwd=repo_root, check=True) + subprocess.run( + ["git", "config", "user.email", "test@example.com"], + cwd=repo_root, + check=True, + ) + subprocess.run(["git", "add", "."], cwd=repo_root, check=True) + subprocess.run(["git", "commit", "-m", "base"], cwd=repo_root, check=True) + subprocess.run(["git", "branch", "origin/main", "HEAD"], cwd=repo_root, check=True) + return repo_root + + +def test_get_release_pr_version_accepts_title_or_branch(): + assert get_release_pr_version("Release v1.15.0", "feature/foo") == ("1.15.0", []) + assert get_release_pr_version("chore: test", "rel-1.15.0") == ("1.15.0", []) + + +def test_get_release_pr_version_rejects_mismatched_markers(): + version, errors = get_release_pr_version("Release v1.15.0", "rel-1.16.0") + + assert version is None + assert errors == [ + "Release PR markers disagree: title requests v1.15.0 but branch is rel-1.16.0." + ] + + +def test_validate_version_changes_rejects_agent_server_bump_in_non_release_pr(): + changes = [ + VersionChange( + package="openhands-agent-server", + path=Path("openhands-agent-server/pyproject.toml"), + previous_version="1.14.0", + current_version="1.15.0", + ) + ] + + errors = validate_version_changes( + changes, + pr_title="chore(agent-server): bump version", + pr_head_ref="fix/agent-server-version-bump", + ) + + assert errors == [ + "Package version changes are only allowed in release PRs. Detected " + "changes: openhands-agent-server (1.14.0 -> 1.15.0). Use the Prepare " + "Release workflow so the PR title is 'Release vX.Y.Z' or the branch is " + "'rel-X.Y.Z'." + ] + + +def test_validate_version_changes_accepts_matching_release_version(): + changes = [ + VersionChange( + package="openhands-agent-server", + path=Path("openhands-agent-server/pyproject.toml"), + previous_version="1.14.0", + current_version="1.15.0", + ) + ] + + assert ( + validate_version_changes( + changes, + pr_title="Release v1.15.0", + pr_head_ref="rel-1.15.0", + ) + == [] + ) + + +def test_find_version_changes_detects_agent_server_package(tmp_path: Path): + repo_root = _init_repo_with_versions(tmp_path, "1.14.0") + _write_version( + repo_root / "openhands-agent-server" / "pyproject.toml", + "1.15.0", + ) + + changes = find_version_changes(repo_root, "main") + + assert changes == [ + VersionChange( + package="openhands-agent-server", + path=Path("openhands-agent-server/pyproject.toml"), + previous_version="1.14.0", + current_version="1.15.0", + ) + ] diff --git a/uv.lock b/uv.lock index c25bb3c1e0..6fce0cbd5e 100644 --- a/uv.lock +++ b/uv.lock @@ -2341,7 +2341,7 @@ wheels = [ [[package]] name = "openhands-agent-server" -version = "1.15.0" +version = "1.14.0" source = { editable = "openhands-agent-server" } dependencies = [ { name = "aiosqlite" }, From 77212f88d177c531fc38b343b19388ffc5d532bb Mon Sep 17 00:00:00 2001 From: enyst Date: Sun, 15 Mar 2026 21:21:59 +0000 Subject: [PATCH 3/3] Revert "ci: guard package version bumps outside release PRs" This reverts commit 2368c7f7e03abe7973a4323fdb6d3d8508c2949e. --- .github/scripts/check_version_bumps.py | 196 ------------------- .github/workflows/version-bump-guard.yml | 25 --- openhands-agent-server/pyproject.toml | 2 +- tests/ci_scripts/test_check_version_bumps.py | 137 ------------- uv.lock | 2 +- 5 files changed, 2 insertions(+), 360 deletions(-) delete mode 100644 .github/scripts/check_version_bumps.py delete mode 100644 .github/workflows/version-bump-guard.yml delete mode 100644 tests/ci_scripts/test_check_version_bumps.py diff --git a/.github/scripts/check_version_bumps.py b/.github/scripts/check_version_bumps.py deleted file mode 100644 index 033f1e35de..0000000000 --- a/.github/scripts/check_version_bumps.py +++ /dev/null @@ -1,196 +0,0 @@ -"""Guard package version changes so they only happen in release PRs.""" - -from __future__ import annotations - -import os -import re -import subprocess -import sys -import tomllib -from dataclasses import dataclass -from pathlib import Path - - -PACKAGE_PYPROJECTS: dict[str, Path] = { - "openhands-sdk": Path("openhands-sdk/pyproject.toml"), - "openhands-tools": Path("openhands-tools/pyproject.toml"), - "openhands-workspace": Path("openhands-workspace/pyproject.toml"), - "openhands-agent-server": Path("openhands-agent-server/pyproject.toml"), -} - -_VERSION_PATTERN = r"\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.]+)?" -_RELEASE_TITLE_RE = re.compile(rf"^Release v(?P{_VERSION_PATTERN})$") -_RELEASE_BRANCH_RE = re.compile(rf"^rel-(?P{_VERSION_PATTERN})$") - - -@dataclass(frozen=True) -class VersionChange: - package: str - path: Path - previous_version: str - current_version: str - - -def _read_version_from_pyproject_text(text: str, source: str) -> str: - data = tomllib.loads(text) - version = data.get("project", {}).get("version") - if not isinstance(version, str): - raise SystemExit(f"Unable to determine project.version from {source}") - return version - - -def _read_current_version(repo_root: Path, pyproject: Path) -> str: - return _read_version_from_pyproject_text( - (repo_root / pyproject).read_text(), - str(pyproject), - ) - - -def _read_version_from_git_ref(repo_root: Path, git_ref: str, pyproject: Path) -> str: - result = subprocess.run( - ["git", "show", f"{git_ref}:{pyproject.as_posix()}"], - cwd=repo_root, - check=False, - capture_output=True, - text=True, - ) - if result.returncode != 0: - message = result.stderr.strip() or result.stdout.strip() or "unknown git error" - raise SystemExit( - f"Unable to read {pyproject} from git ref {git_ref}: {message}" - ) - return _read_version_from_pyproject_text(result.stdout, f"{git_ref}:{pyproject}") - - -def _base_ref_candidates(base_ref: str) -> list[str]: - if base_ref.startswith("origin/"): - return [base_ref, base_ref.removeprefix("origin/")] - return [f"origin/{base_ref}", base_ref] - - -def find_version_changes(repo_root: Path, base_ref: str) -> list[VersionChange]: - changes: list[VersionChange] = [] - candidates = _base_ref_candidates(base_ref) - - for package, pyproject in PACKAGE_PYPROJECTS.items(): - current_version = _read_current_version(repo_root, pyproject) - previous_error: SystemExit | None = None - previous_version: str | None = None - - for candidate in candidates: - try: - previous_version = _read_version_from_git_ref( - repo_root, candidate, pyproject - ) - break - except SystemExit as exc: - previous_error = exc - - if previous_version is None: - assert previous_error is not None - raise previous_error - - if previous_version != current_version: - changes.append( - VersionChange( - package=package, - path=pyproject, - previous_version=previous_version, - current_version=current_version, - ) - ) - - return changes - - -def get_release_pr_version( - pr_title: str, pr_head_ref: str -) -> tuple[str | None, list[str]]: - title_match = _RELEASE_TITLE_RE.fullmatch(pr_title.strip()) - branch_match = _RELEASE_BRANCH_RE.fullmatch(pr_head_ref.strip()) - title_version = title_match.group("version") if title_match else None - branch_version = branch_match.group("version") if branch_match else None - - if title_version and branch_version and title_version != branch_version: - return None, [ - "Release PR markers disagree: title requests " - f"v{title_version} but branch is rel-{branch_version}." - ] - - return title_version or branch_version, [] - - -def validate_version_changes( - changes: list[VersionChange], - pr_title: str, - pr_head_ref: str, -) -> list[str]: - if not changes: - return [] - - release_version, errors = get_release_pr_version(pr_title, pr_head_ref) - if errors: - return errors - - formatted_changes = ", ".join( - f"{change.package} ({change.previous_version} -> {change.current_version})" - for change in changes - ) - - if release_version is None: - return [ - "Package version changes are only allowed in release PRs. " - f"Detected changes: {formatted_changes}. " - "Use the Prepare Release workflow so the PR title is 'Release vX.Y.Z' " - "or the branch is 'rel-X.Y.Z'." - ] - - mismatched = [ - change for change in changes if change.current_version != release_version - ] - if mismatched: - mismatch_details = ", ".join( - f"{change.package} ({change.current_version})" for change in mismatched - ) - return [ - f"Release PR version v{release_version} does not match changed package " - f"versions: {mismatch_details}." - ] - - return [] - - -def main() -> int: - repo_root = Path(__file__).resolve().parents[2] - base_ref = os.environ.get("VERSION_BUMP_BASE_REF") or os.environ.get( - "GITHUB_BASE_REF" - ) - if not base_ref: - print("::warning title=Version bump guard::No base ref found; skipping check.") - return 0 - - pr_title = os.environ.get("PR_TITLE", "") - pr_head_ref = os.environ.get("PR_HEAD_REF", "") - - changes = find_version_changes(repo_root, base_ref) - errors = validate_version_changes(changes, pr_title, pr_head_ref) - - if errors: - for error in errors: - print(f"::error title=Version bump guard::{error}") - return 1 - - if changes: - changed_packages = ", ".join(change.package for change in changes) - print( - "::notice title=Version bump guard::" - f"Release PR version changes validated for {changed_packages}." - ) - else: - print("::notice title=Version bump guard::No package version changes detected.") - - return 0 - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/.github/workflows/version-bump-guard.yml b/.github/workflows/version-bump-guard.yml deleted file mode 100644 index 099ae1fb85..0000000000 --- a/.github/workflows/version-bump-guard.yml +++ /dev/null @@ -1,25 +0,0 @@ ---- -name: Version bump guard - -on: - pull_request: - branches: [main] - -jobs: - version-bump-guard: - name: Check package versions - runs-on: ubuntu-latest - permissions: - contents: read - steps: - - name: Checkout - uses: actions/checkout@v5 - with: - fetch-depth: 0 - - - name: Validate package version changes - env: - VERSION_BUMP_BASE_REF: ${{ github.base_ref }} - PR_TITLE: ${{ github.event.pull_request.title }} - PR_HEAD_REF: ${{ github.event.pull_request.head.ref }} - run: python3 .github/scripts/check_version_bumps.py diff --git a/openhands-agent-server/pyproject.toml b/openhands-agent-server/pyproject.toml index c7573f4b6f..5d5b2ea6c0 100644 --- a/openhands-agent-server/pyproject.toml +++ b/openhands-agent-server/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "openhands-agent-server" -version = "1.14.0" +version = "1.15.0" description = "OpenHands Agent Server - REST/WebSocket interface for OpenHands AI Agent" requires-python = ">=3.12" diff --git a/tests/ci_scripts/test_check_version_bumps.py b/tests/ci_scripts/test_check_version_bumps.py deleted file mode 100644 index bbb5531422..0000000000 --- a/tests/ci_scripts/test_check_version_bumps.py +++ /dev/null @@ -1,137 +0,0 @@ -"""Tests for the version bump guard script.""" - -from __future__ import annotations - -import importlib.util -import subprocess -import sys -from pathlib import Path - - -def _load_prod_module(): - repo_root = Path(__file__).resolve().parents[2] - script_path = repo_root / ".github" / "scripts" / "check_version_bumps.py" - name = "check_version_bumps" - spec = importlib.util.spec_from_file_location(name, script_path) - assert spec and spec.loader - mod = importlib.util.module_from_spec(spec) - sys.modules[name] = mod - spec.loader.exec_module(mod) - return mod - - -_prod = _load_prod_module() -VersionChange = _prod.VersionChange -find_version_changes = _prod.find_version_changes -get_release_pr_version = _prod.get_release_pr_version -validate_version_changes = _prod.validate_version_changes - - -def _write_version(pyproject: Path, version: str) -> None: - pyproject.write_text( - f'[project]\nname = "{pyproject.parent.name}"\nversion = "{version}"\n' - ) - - -def _init_repo_with_versions(tmp_path: Path, version: str) -> Path: - repo_root = tmp_path / "repo" - repo_root.mkdir() - - for package_dir in ( - "openhands-sdk", - "openhands-tools", - "openhands-workspace", - "openhands-agent-server", - ): - package_path = repo_root / package_dir - package_path.mkdir() - _write_version(package_path / "pyproject.toml", version) - - subprocess.run(["git", "init", "-b", "main"], cwd=repo_root, check=True) - subprocess.run(["git", "config", "user.name", "test"], cwd=repo_root, check=True) - subprocess.run( - ["git", "config", "user.email", "test@example.com"], - cwd=repo_root, - check=True, - ) - subprocess.run(["git", "add", "."], cwd=repo_root, check=True) - subprocess.run(["git", "commit", "-m", "base"], cwd=repo_root, check=True) - subprocess.run(["git", "branch", "origin/main", "HEAD"], cwd=repo_root, check=True) - return repo_root - - -def test_get_release_pr_version_accepts_title_or_branch(): - assert get_release_pr_version("Release v1.15.0", "feature/foo") == ("1.15.0", []) - assert get_release_pr_version("chore: test", "rel-1.15.0") == ("1.15.0", []) - - -def test_get_release_pr_version_rejects_mismatched_markers(): - version, errors = get_release_pr_version("Release v1.15.0", "rel-1.16.0") - - assert version is None - assert errors == [ - "Release PR markers disagree: title requests v1.15.0 but branch is rel-1.16.0." - ] - - -def test_validate_version_changes_rejects_agent_server_bump_in_non_release_pr(): - changes = [ - VersionChange( - package="openhands-agent-server", - path=Path("openhands-agent-server/pyproject.toml"), - previous_version="1.14.0", - current_version="1.15.0", - ) - ] - - errors = validate_version_changes( - changes, - pr_title="chore(agent-server): bump version", - pr_head_ref="fix/agent-server-version-bump", - ) - - assert errors == [ - "Package version changes are only allowed in release PRs. Detected " - "changes: openhands-agent-server (1.14.0 -> 1.15.0). Use the Prepare " - "Release workflow so the PR title is 'Release vX.Y.Z' or the branch is " - "'rel-X.Y.Z'." - ] - - -def test_validate_version_changes_accepts_matching_release_version(): - changes = [ - VersionChange( - package="openhands-agent-server", - path=Path("openhands-agent-server/pyproject.toml"), - previous_version="1.14.0", - current_version="1.15.0", - ) - ] - - assert ( - validate_version_changes( - changes, - pr_title="Release v1.15.0", - pr_head_ref="rel-1.15.0", - ) - == [] - ) - - -def test_find_version_changes_detects_agent_server_package(tmp_path: Path): - repo_root = _init_repo_with_versions(tmp_path, "1.14.0") - _write_version( - repo_root / "openhands-agent-server" / "pyproject.toml", - "1.15.0", - ) - - changes = find_version_changes(repo_root, "main") - - assert changes == [ - VersionChange( - package="openhands-agent-server", - path=Path("openhands-agent-server/pyproject.toml"), - previous_version="1.14.0", - current_version="1.15.0", - ) - ] diff --git a/uv.lock b/uv.lock index 6fce0cbd5e..c25bb3c1e0 100644 --- a/uv.lock +++ b/uv.lock @@ -2341,7 +2341,7 @@ wheels = [ [[package]] name = "openhands-agent-server" -version = "1.14.0" +version = "1.15.0" source = { editable = "openhands-agent-server" } dependencies = [ { name = "aiosqlite" },