Skip to content

Commit 6b7e74c

Browse files
Copilotmbarbero
andauthored
Skip fork PR approval API calls for private repos instead of catching exceptions
Agent-Logs-Url: https://github.com/eclipse-csi/otterdog/sessions/7a7e39a1-6243-4958-8653-fa287e9c1984 Co-authored-by: mbarbero <452625+mbarbero@users.noreply.github.com>
1 parent 98aa7a8 commit 6b7e74c

5 files changed

Lines changed: 45 additions & 10 deletions

File tree

otterdog/models/github_organization.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -681,7 +681,8 @@ async def _process_single_repo(
681681
github_repo_data = await rest_api.repo.get_repo_data(github_id, repo_name)
682682
repo = Repository.from_provider_data(github_id, github_repo_data)
683683

684-
github_repo_workflow_data = await rest_api.repo.get_workflow_settings(github_id, repo_name)
684+
is_private = github_repo_data.get("private", False)
685+
github_repo_workflow_data = await rest_api.repo.get_workflow_settings(github_id, repo_name, is_private=is_private)
685686
repo.workflows = RepositoryWorkflowSettings.from_provider_data(github_id, github_repo_workflow_data)
686687
if repo_permissions is not None:
687688
repo_permission = repo_permissions.get(repo_name, [])

otterdog/models/repository.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1478,6 +1478,7 @@ async def apply_live_patch(
14781478
org_id,
14791479
expected_object.name,
14801480
await expected_object.workflows.dict_to_provider_data(org_id, workflow_data, provider),
1481+
is_private=expected_object.private is True,
14811482
)
14821483

14831484
# Team permissions are defined on the repository but originate from the team side.
@@ -1511,7 +1512,12 @@ async def apply_live_patch(
15111512
data = unwrap(patch.expected_object).workflows.to_model_dict(for_diff=True)
15121513
github_data = await RepositoryWorkflowSettings.dict_to_provider_data(org_id, data, provider)
15131514

1514-
await provider.update_repo_workflow_settings(org_id, expected_object.name, github_data)
1515+
await provider.update_repo_workflow_settings(
1516+
org_id,
1517+
expected_object.name,
1518+
github_data,
1519+
is_private=expected_object.private is True,
1520+
)
15151521

15161522
# Team permissions sit at the intersection of repositories and teams.
15171523
# A change in `team_permissions` can represent three different operations:

otterdog/providers/github/__init__.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -360,13 +360,15 @@ async def add_repo_environment(self, org_id: str, repo_name: str, env_name: str,
360360
async def delete_repo_environment(self, org_id: str, repo_name: str, env_name: str) -> None:
361361
await self.rest_api.repo.delete_environment(org_id, repo_name, env_name)
362362

363-
async def get_repo_workflow_settings(self, org_id: str, repo_name: str) -> dict[str, Any]:
364-
return await self.rest_api.repo.get_workflow_settings(org_id, repo_name)
363+
async def get_repo_workflow_settings(
364+
self, org_id: str, repo_name: str, is_private: bool = False
365+
) -> dict[str, Any]:
366+
return await self.rest_api.repo.get_workflow_settings(org_id, repo_name, is_private=is_private)
365367

366368
async def update_repo_workflow_settings(
367-
self, org_id: str, repo_name: str, workflow_settings: dict[str, Any]
369+
self, org_id: str, repo_name: str, workflow_settings: dict[str, Any], is_private: bool = False
368370
) -> None:
369-
await self.rest_api.repo.update_workflow_settings(org_id, repo_name, workflow_settings)
371+
await self.rest_api.repo.update_workflow_settings(org_id, repo_name, workflow_settings, is_private=is_private)
370372

371373
async def get_org_secrets(self, org_id: str) -> list[dict[str, Any]]:
372374
return await self.rest_api.org.get_secrets(org_id)

otterdog/providers/github/rest/repo_client.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -971,7 +971,9 @@ async def delete_variable(self, org_id: str, repo_name: str, variable_name: str)
971971

972972
_logger.debug("removed repo variable '%s'", variable_name)
973973

974-
async def get_workflow_settings(self, org_id: str, repo_name: str) -> dict[str, Any]:
974+
async def get_workflow_settings(
975+
self, org_id: str, repo_name: str, is_private: bool = False
976+
) -> dict[str, Any]:
975977
_logger.debug("retrieving workflow settings for repo '%s/%s'", org_id, repo_name)
976978

977979
workflow_settings: dict[str, Any] = {}
@@ -989,11 +991,14 @@ async def get_workflow_settings(self, org_id: str, repo_name: str) -> dict[str,
989991
if permissions.get("enabled", False) is not False:
990992
workflow_settings.update(await self._get_default_workflow_permissions(org_id, repo_name))
991993

992-
workflow_settings.update(await self._get_fork_pr_approval_policy(org_id, repo_name))
994+
if not is_private:
995+
workflow_settings.update(await self._get_fork_pr_approval_policy(org_id, repo_name))
993996

994997
return workflow_settings
995998

996-
async def update_workflow_settings(self, org_id: str, repo_name: str, data: dict[str, Any]) -> None:
999+
async def update_workflow_settings(
1000+
self, org_id: str, repo_name: str, data: dict[str, Any], is_private: bool = False
1001+
) -> None:
9971002
_logger.debug("updating workflow settings for repo '%s/%s'", org_id, repo_name)
9981003

9991004
permission_data = {k: data[k] for k in ["enabled", "allowed_actions"] if k in data}
@@ -1023,7 +1028,7 @@ async def update_workflow_settings(self, org_id: str, repo_name: str, data: dict
10231028
if len(default_permission_data) > 0:
10241029
await self._update_default_workflow_permissions(org_id, repo_name, default_permission_data)
10251030

1026-
if "approval_policy" in data:
1031+
if not is_private and "approval_policy" in data:
10271032
await self._update_fork_pr_approval_policy(org_id, repo_name, {"approval_policy": data["approval_policy"]})
10281033

10291034
_logger.debug("updated %d workflow setting(s)", len(data))

tests/providers/github/rest/test_repo_client.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,3 +248,24 @@ async def mock_get(org, repo):
248248

249249
# Assert result includes the approval policy
250250
assert set(policy.items()).issubset(result.items())
251+
252+
async def test_get_workflow_settings_skips_fork_pr_approval_policy_for_private_repo(self):
253+
called = []
254+
255+
async def mock_request(method, url):
256+
return {}
257+
258+
async def mock_get(org, repo):
259+
called.append(True)
260+
return {"approval_policy": "all_external_contributors"}
261+
262+
mock_requester = pretend.stub(request_json=mock_request)
263+
mock_restapi = pretend.stub(requester=mock_requester)
264+
repo_client = RepoClient(mock_restapi)
265+
repo_client._get_fork_pr_approval_policy = mock_get
266+
267+
result = await repo_client.get_workflow_settings("org", "repo", is_private=True)
268+
269+
# Assert the fork PR approval policy was NOT fetched
270+
assert not called
271+
assert "approval_policy" not in result

0 commit comments

Comments
 (0)