Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Integration][ADO] Fix missing team context for non default teams while ingesting boards #1127

8 changes: 8 additions & 0 deletions integrations/azure-devops/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

<!-- towncrier release notes start -->

## 0.1.79 (2024-11-07)


### Bug Fixes

- Fixed the API endpoint used in the boards kind to iterate through all project teams, ensuring non-default team boards and columns are ingested


## 0.1.78 (2024-11-06)


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,24 +286,27 @@ async def get_columns(self) -> AsyncGenerator[list[dict[str, Any]], None]:
]

async def _enrich_boards(
self, boards: list[dict[str, Any]], project_id: str
self, boards: list[dict[str, Any]], project_id: str, team_id: str
) -> list[dict[str, Any]]:
for board in boards:
response = await self.send_request(
"GET",
f"{self._organization_base_url}/{project_id}/{API_URL_PREFIX}/work/boards/{board['id']}",
f"{self._organization_base_url}/{project_id}/{team_id}/{API_URL_PREFIX}/work/boards/{board['id']}",
)
board.update(response.json())
return boards

async def _get_boards(self, project_id: str) -> list[dict[str, Any]]:
get_boards_url = (
f"{self._organization_base_url}/{project_id}/{API_URL_PREFIX}/work/boards"
)
response = await self.send_request("GET", get_boards_url)
board_data = response.json().get("value", [])
logger.info(f"Found {len(board_data)} boards for project {project_id}")
return await self._enrich_boards(board_data, project_id)
async def _get_boards(
self, project_id: str
) -> AsyncGenerator[list[dict[str, Any]], None]:
teams_url = f"{self._organization_base_url}/{API_URL_PREFIX}/projects/{project_id}/teams"
async for teams_in_project in self._get_paginated_by_top_and_skip(teams_url):
Comment on lines +302 to +303
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have a generate_teams() method already. why don't you use that one?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generate teams gets the teams outside of the project context and it might not be suitable for this purpose

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see

for team in teams_in_project:
get_boards_url = f"{self._organization_base_url}/{project_id}/{team['id']}/{API_URL_PREFIX}/work/boards"
response = await self.send_request("GET", get_boards_url)
board_data = response.json().get("value", [])
logger.info(f"Found {len(board_data)} boards for project {project_id}")
yield await self._enrich_boards(board_data, project_id, team["id"])

@cache_iterator_result()
async def get_boards_in_organization(
Expand All @@ -313,7 +316,8 @@ async def get_boards_in_organization(
yield [
{**board, "__project": project}
for project in projects
for board in await self._get_boards(project["id"])
async for boards in self._get_boards(project["id"])
for board in boards
]

async def generate_subscriptions_webhook_events(self) -> list[WebhookEvent]:
Expand Down
2 changes: 1 addition & 1 deletion integrations/azure-devops/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "azure-devops"
version = "0.1.78"
version = "0.1.79"
description = "An Azure Devops Ocean integration"
authors = ["Matan Geva <[email protected]>"]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -572,8 +572,10 @@ async def test_get_boards_in_organization(mock_event_context: MagicMock) -> None
async def mock_generate_projects() -> AsyncGenerator[List[Dict[str, Any]], None]:
yield [{"id": "proj1", "name": "Project One"}]

async def mock_get_boards(project_id: str) -> List[Dict[str, Any]]:
return [
async def mock_get_boards(
project_id: str,
) -> AsyncGenerator[List[Dict[str, Any]], None]:
yield [
{"id": "board1", "name": "Board One"},
{"id": "board2", "name": "Board Two"},
]
Expand Down