diff --git a/openhands-sdk/openhands/sdk/git/utils.py b/openhands-sdk/openhands/sdk/git/utils.py index e16d4a2605..2056015c62 100644 --- a/openhands-sdk/openhands/sdk/git/utils.py +++ b/openhands-sdk/openhands/sdk/git/utils.py @@ -309,6 +309,8 @@ def is_git_url(source: str) -> bool: True >>> is_git_url("git@github.com:owner/repo.git") True + >>> is_git_url("ssh://git@github.com/owner/repo.git") + True >>> is_git_url("/local/path") False """ @@ -316,6 +318,10 @@ def is_git_url(source: str) -> bool: if source.startswith(("https://", "http://")): return True + # SSH URL with explicit scheme: ssh://git@host[:port]/path + if source.startswith("ssh://"): + return True + # SSH format: git@host:path or user@host:path if re.match(r"^[\w.-]+@[\w.-]+:", source): return True diff --git a/tests/sdk/extensions/test_fetch.py b/tests/sdk/extensions/test_fetch.py index dcf2b41994..70e11f168e 100644 --- a/tests/sdk/extensions/test_fetch.py +++ b/tests/sdk/extensions/test_fetch.py @@ -128,6 +128,19 @@ def test_parse_ssh_with_custom_user(): assert url == ssh_url +def test_parse_ssh_scheme_url(): + """`ssh://` scheme URLs (incl. an explicit port) are recognized as git URLs. + + Regression test: previously `is_git_url()` did not recognize the `ssh://` + scheme, so these dropped through to "Unable to parse extension source" + instead of being treated as a git source. + """ + ssh_url = "ssh://git@bitbucket.example.com:7999/team/repo.git" + source_type, url = parse_extension_source(ssh_url) + assert source_type == SourceType.GIT + assert url == ssh_url + + def test_parse_relative_path_with_slash(): source_type, url = parse_extension_source("extensions/my-ext") assert source_type == SourceType.LOCAL