Skip to content

Commit c92de96

Browse files
authored
Merge pull request #1370 from cloudfoundry/github-org-automation
WG repo org validation
2 parents 0ea2d1c + 88093b7 commit c92de96

File tree

4 files changed

+34
-7
lines changed

4 files changed

+34
-7
lines changed

orgs/org_management/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
generator = OrgGenerator()
1515
generator.load_from_project()
1616
if not generator.validate_repo_ownership():
17-
print("ERROR: Repository ownership is invalid. Refer to RFC-0007.")
17+
print("ERROR: Repository ownership is invalid. Refer to RFC-0007 and RFC-0036.")
1818
exit(1)
1919
generator.generate_org_members()
2020
generator.generate_teams()

orgs/org_management/org_management.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,20 +120,35 @@ def load_from_project(self):
120120
raise ValueError(f"Invalid org {org} in WG {wg['name']}, expected one of {OrgGenerator._MANAGED_ORGS}")
121121
self.working_groups[org].append(wg)
122122

123-
# rfc-0007-repository-ownership: a repo can't be owned by multiple WGs, scope is github org
124123
def validate_repo_ownership(self) -> bool:
125124
valid = True
125+
126+
# rfc-0007-repository-ownership: a repo can't be owned by multiple WGs, scope is github org
126127
for org in OrgGenerator._MANAGED_ORGS:
127128
repo_owners = {}
128129
for wg in self.working_groups[org]:
129130
wg_name = wg["name"]
130131
wg_repos = set(r for a in wg["areas"] for r in a["repositories"])
131132
for repo in wg_repos:
132133
if repo in repo_owners:
133-
print(f"ERROR: Repository {repo} is owned by multiple WGs: {repo_owners[repo]}, {wg_name}")
134+
print(f"ERROR: Repository '{repo}' is owned by multiple WGs: {repo_owners[repo]}, {wg_name}")
134135
valid = False
135136
else:
136137
repo_owners[repo] = wg_name
138+
139+
# rfc-0036-multiple-github-orgs: Working Groups MUST only contain repos from one CFF Github Org (but repos from unmanaged orgs are allowed as temporary exception)
140+
for org in self.working_groups.keys():
141+
for wg in self.working_groups[org]:
142+
wg_name = wg["name"]
143+
wg_repos = set(r for a in wg["areas"] for r in a["repositories"])
144+
for repo in wg_repos:
145+
repo_org = repo.split("/")[0]
146+
if repo_org != org and repo_org in OrgGenerator._MANAGED_ORGS:
147+
print(
148+
f"ERROR: Working Group '{wg_name}' assigned to Github org '{org}' contains repository '{repo}' from a different managed org."
149+
)
150+
valid = False
151+
137152
return valid
138153

139154
def get_contributors(self, org: str) -> set[str]:

orgs/org_management/test_org_management.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@
208208
repositories:
209209
- cloudfoundry2/repo3
210210
- cloudfoundry2/repo4
211-
- cloudfoundry/repo5
211+
- cloudfoundry2/repo5
212212
"""
213213

214214
toc = """
@@ -474,6 +474,18 @@ def test_validate_repo_ownership(self):
474474
o = OrgGenerator(static_org_cfg=org_cfg, toc=toc, working_groups=[wg1, wg2, wg3])
475475
self.assertFalse(o.validate_repo_ownership())
476476

477+
def test_validate_repo_ownership_multiple_orgs(self):
478+
OrgGenerator._MANAGED_ORGS = ["cloudfoundry", "cloudfoundry2"]
479+
o = OrgGenerator(static_org_cfg=org_cfg_multiple, toc=toc, working_groups=[wg1, wg4_other_org])
480+
self.assertTrue(o.validate_repo_ownership())
481+
# includes non-managed orgs
482+
o = OrgGenerator(static_org_cfg=org_cfg_multiple, toc=toc, working_groups=[wg1, wg2, wg4_other_org])
483+
self.assertTrue(o.validate_repo_ownership())
484+
# wg can only have repos of one org
485+
bad_wg4_other_org = wg4_other_org.replace("cloudfoundry2/repo5", "cloudfoundry/repo5")
486+
o = OrgGenerator(static_org_cfg=org_cfg_multiple, toc=toc, working_groups=[wg1, bad_wg4_other_org])
487+
self.assertFalse(o.validate_repo_ownership())
488+
477489
def test_generate_wg_teams(self):
478490
_wg1 = OrgGenerator._yaml_load(wg1)
479491
OrgGenerator._validate_wg(_wg1)
@@ -559,7 +571,7 @@ def test_generate_wg_teams_multiple_orgs(self):
559571
self.assertDictEqual({"repo1": "write", "repo2": "write"}, team["repos"])
560572

561573
team = wg_team["teams"]["wg-wg4-name-area-2-approvers"]
562-
self.assertDictEqual({"repo3": "write", "repo4": "write"}, team["repos"])
574+
self.assertDictEqual({"repo3": "write", "repo4": "write", "repo5": "write"}, team["repos"])
563575

564576
def test_generate_toc_team(self):
565577
_toc = OrgGenerator._yaml_load(toc)
@@ -758,7 +770,7 @@ def test_generate_branch_protection_multiple_orgs(self):
758770

759771
bp_repos = o.branch_protection["branch-protection"]["orgs"]["cloudfoundry2"]["repos"]
760772
# wg4 opted in, repo5 is ignored because of wrong org
761-
self.assertSetEqual({f"repo{i}" for i in range(1, 5)}, set(bp_repos.keys()))
773+
self.assertSetEqual({f"repo{i}" for i in range(1, 6)}, set(bp_repos.keys()))
762774
# repo1 has static config that wins over generated branch protection rules
763775
self.assertTrue(bp_repos["repo1"]["protect"])
764776
self.assertNotIn("required_pull_request_reviews", bp_repos["repo1"])

orgs/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ version = "0.1.0"
44
description = "Automation for GitHub orgs managed by the Cloud Foundry Foundation"
55
readme = "readme.md"
66
requires-python = ">=3.14"
7-
license-files = ["LICENSE"]
7+
license = "Apache-2.0"
88
classifiers = ["Private :: Do Not Upload"]
99
dependencies = [
1010
"pyyaml",

0 commit comments

Comments
 (0)