mirror of
https://github.com/All-Hands-AI/OpenHands.git
synced 2026-01-08 22:38:05 -05:00
feat: add Azure DevOps integration support (#11243)
Co-authored-by: Graham Neubig <neubig@gmail.com>
This commit is contained in:
@@ -147,9 +147,11 @@ def runtime(temp_dir):
|
||||
return runtime
|
||||
|
||||
|
||||
def mock_repo_and_patch(monkeypatch, provider=ProviderType.GITHUB, is_public=True):
|
||||
def mock_repo_and_patch(
|
||||
monkeypatch, provider=ProviderType.GITHUB, is_public=True, full_name='owner/repo'
|
||||
):
|
||||
repo = Repository(
|
||||
id='123', full_name='owner/repo', git_provider=provider, is_public=is_public
|
||||
id='123', full_name=full_name, git_provider=provider, is_public=is_public
|
||||
)
|
||||
|
||||
async def mock_verify_repo_provider(*_args, **_kwargs):
|
||||
@@ -216,11 +218,14 @@ async def test_export_latest_git_provider_tokens_success(runtime):
|
||||
async def test_export_latest_git_provider_tokens_multiple_refs(temp_dir):
|
||||
"""Test token export with multiple token references"""
|
||||
config = OpenHandsConfig()
|
||||
# Initialize with both GitHub and GitLab tokens
|
||||
# Initialize with GitHub, GitLab, and Azure DevOps tokens
|
||||
git_provider_tokens = MappingProxyType(
|
||||
{
|
||||
ProviderType.GITHUB: ProviderToken(token=SecretStr('github_token')),
|
||||
ProviderType.GITLAB: ProviderToken(token=SecretStr('gitlab_token')),
|
||||
ProviderType.AZURE_DEVOPS: ProviderToken(
|
||||
token=SecretStr('azure_devops_token')
|
||||
),
|
||||
}
|
||||
)
|
||||
file_store = get_file_store('local', temp_dir)
|
||||
@@ -234,15 +239,18 @@ async def test_export_latest_git_provider_tokens_multiple_refs(temp_dir):
|
||||
)
|
||||
|
||||
# Create a command that references multiple tokens
|
||||
cmd = CmdRunAction(command='echo $GITHUB_TOKEN && echo $GITLAB_TOKEN')
|
||||
cmd = CmdRunAction(
|
||||
command='echo $GITHUB_TOKEN && echo $GITLAB_TOKEN && echo $AZURE_DEVOPS_TOKEN'
|
||||
)
|
||||
|
||||
# Export the tokens
|
||||
await runtime._export_latest_git_provider_tokens(cmd)
|
||||
|
||||
# Verify that both tokens were exported
|
||||
# Verify that all tokens were exported
|
||||
assert event_stream.secrets == {
|
||||
'github_token': 'github_token',
|
||||
'gitlab_token': 'gitlab_token',
|
||||
'azure_devops_token': 'azure_devops_token',
|
||||
}
|
||||
|
||||
|
||||
@@ -478,6 +486,57 @@ async def test_clone_or_init_repo_gitlab_with_token(temp_dir, monkeypatch):
|
||||
assert result == 'repo'
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_clone_or_init_repo_azure_devops_with_token(temp_dir, monkeypatch):
|
||||
"""Test cloning Azure DevOps repository with token"""
|
||||
config = OpenHandsConfig()
|
||||
|
||||
# Set up Azure DevOps token
|
||||
azure_devops_token = 'azure_devops_test_token'
|
||||
git_provider_tokens = MappingProxyType(
|
||||
{ProviderType.AZURE_DEVOPS: ProviderToken(token=SecretStr(azure_devops_token))}
|
||||
)
|
||||
|
||||
file_store = get_file_store('local', temp_dir)
|
||||
event_stream = EventStream('abc', file_store)
|
||||
runtime = MockRuntime(
|
||||
config=config,
|
||||
event_stream=event_stream,
|
||||
user_id='test_user',
|
||||
git_provider_tokens=git_provider_tokens,
|
||||
)
|
||||
|
||||
# Mock the repository to be Azure DevOps with 3-part format: org/project/repo
|
||||
azure_repo_name = 'testorg/testproject/testrepo'
|
||||
mock_repo_and_patch(
|
||||
monkeypatch, provider=ProviderType.AZURE_DEVOPS, full_name=azure_repo_name
|
||||
)
|
||||
|
||||
# Call the method with Azure DevOps 3-part format: org/project/repo
|
||||
result = await runtime.clone_or_init_repo(
|
||||
git_provider_tokens=git_provider_tokens,
|
||||
selected_repository=azure_repo_name,
|
||||
selected_branch=None,
|
||||
)
|
||||
|
||||
# Check that the first command is the git clone with the correct URL format with token
|
||||
# Azure DevOps uses Basic auth format: https://org:token@dev.azure.com/org/project/_git/repo
|
||||
clone_cmd = runtime.run_action_calls[0].command
|
||||
expected_repo_path = str(runtime.workspace_root / 'testrepo')
|
||||
assert (
|
||||
f'https://testorg:{azure_devops_token}@dev.azure.com/testorg/testproject/_git/testrepo'
|
||||
in clone_cmd
|
||||
)
|
||||
assert expected_repo_path in clone_cmd
|
||||
|
||||
# Check that the second command is the checkout
|
||||
checkout_cmd = runtime.run_action_calls[1].command
|
||||
assert f'cd {expected_repo_path}' in checkout_cmd
|
||||
assert 'git checkout -b openhands-workspace-' in checkout_cmd
|
||||
|
||||
assert result == 'testrepo'
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_clone_or_init_repo_with_branch(temp_dir, monkeypatch):
|
||||
"""Test cloning a repository with a specified branch"""
|
||||
|
||||
Reference in New Issue
Block a user