Skip to content

fix(azuredevops_go): skip failing service connections when listing remote repositories - #9376

Open
dmorfav wants to merge 1 commit into
apache:mainfrom
dmorfav:fix/azuredevops-remote-repos-partial
Open

dmorfav wants to merge 1 commit into
apache:mainfrom
dmorfav:fix/azuredevops-remote-repos-partial

Conversation

@dmorfav

@dmorfav dmorfav commented Nov 11, 2026

Copy link
Copy Markdown

Summary

Fixes the Azure DevOps (azuredevops_go) scope picker hiding all external (GitHub/Bitbucket) repositories of a project when a single service connection fails.

listRemoteRepos queries every supported service connection of the project in parallel through an errgroup. Each goroutine returned the error of its GetRemoteRepositories call, so as soon as one connection failed (expired or revoked credentials, missing permissions, a deleted remote...) g.Wait() made the function return nil plus the error, discarding the repositories already collected from the healthy connections. listAzuredevopsRemoteScopes then dropped that error without logging it, so the UI showed no external repositories and the logs had no trace of why.

Projects with many service connections are very likely to have at least one broken one, which makes external repositories impossible to add from the UI.

This PR:

  • logs a warning for a service connection whose repositories cannot be listed and skips it, keeping the repositories of the other connections;
  • logs the errors of listRemoteRepos and listAzuredevopsRepos that listAzuredevopsRemoteScopes used to ignore;
  • adds TestListRemoteReposSkipsFailingServiceConnection (one failing and one working service connection). It fails on main (error returned, 0 repositories) and passes with this change.

go test -race ./plugins/azuredevops_go/api/... and go vet pass locally.

Does this close any open issues?

Closes #9370

Screenshots

Not applicable (backend change).

Other Information

Kept intentionally small. While reading this code I noticed a few other things that may deserve separate follow-ups, but I have not verified them against a real organization, so they are not part of this PR:

  • slices.Contains(supportedSourceRepositories, v.Type) is case-sensitive;
  • GetRemoteRepositories does not check res.StatusCode and does not guard against a repeated continuation token;
  • GetServiceEndpoints/GetRemoteRepositories build the path as orgId/projectId even when orgId is empty (on-premises), unlike GetRepositories.

…mote repositories

listRemoteRepos queried every GitHub/Bitbucket service connection of a project in parallel and returned an error as soon as one of them failed, discarding the repositories already collected from the others. listAzuredevopsRemoteScopes then dropped that error silently, so a single broken service connection (e.g. expired credentials) hid every external repository of the project in the scope picker, with nothing in the logs.

Log and skip a failing service connection instead, and log the errors that listAzuredevopsRemoteScopes used to ignore.

Closes apache#9370
@dmorfav

dmorfav commented Nov 11, 2026

Copy link
Copy Markdown
Author

Hi! A bit of context on this PR and #9371: we are rolling out Apache DevLake for the first time (v1.0.3-beta19) to track DORA metrics for one of our teams, using Jira, Bitbucket Cloud and Azure DevOps Pipelines, and these are the two issues we ran into along the way.

We kept both fixes as small as possible. If you would prefer a different approach (for example, showing the failing service connections in the UI instead of just logging them), we are happy to adapt. We also can't add the pr-type/bug-fix label ourselves.

Thanks for the project, it has been very useful so far.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug][azuredevops_go] External (Bitbucket/GitHub) repositories not listed if any service endpoint fails

1 participant