github-org-manager 0.7.3__tar.gz → 0.7.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {github_org_manager-0.7.3 → github_org_manager-0.7.4}/PKG-INFO +1 -1
- {github_org_manager-0.7.3 → github_org_manager-0.7.4}/gh_org_mgr/_gh_org.py +45 -20
- {github_org_manager-0.7.3 → github_org_manager-0.7.4}/gh_org_mgr/manage.py +1 -1
- {github_org_manager-0.7.3 → github_org_manager-0.7.4}/pyproject.toml +1 -1
- {github_org_manager-0.7.3 → github_org_manager-0.7.4}/LICENSE.txt +0 -0
- {github_org_manager-0.7.3 → github_org_manager-0.7.4}/LICENSES/Apache-2.0.txt +0 -0
- {github_org_manager-0.7.3 → github_org_manager-0.7.4}/LICENSES/CC-BY-4.0.txt +0 -0
- {github_org_manager-0.7.3 → github_org_manager-0.7.4}/LICENSES/CC0-1.0.txt +0 -0
- {github_org_manager-0.7.3 → github_org_manager-0.7.4}/LICENSES/MIT.txt +0 -0
- {github_org_manager-0.7.3 → github_org_manager-0.7.4}/README.md +0 -0
- {github_org_manager-0.7.3 → github_org_manager-0.7.4}/gh_org_mgr/__init__.py +0 -0
- {github_org_manager-0.7.3 → github_org_manager-0.7.4}/gh_org_mgr/_config.py +0 -0
- {github_org_manager-0.7.3 → github_org_manager-0.7.4}/gh_org_mgr/_gh_api.py +0 -0
- {github_org_manager-0.7.3 → github_org_manager-0.7.4}/gh_org_mgr/_helpers.py +0 -0
- {github_org_manager-0.7.3 → github_org_manager-0.7.4}/gh_org_mgr/_setup_team.py +0 -0
- {github_org_manager-0.7.3 → github_org_manager-0.7.4}/gh_org_mgr/_stats.py +0 -0
|
@@ -8,14 +8,12 @@ import logging
|
|
|
8
8
|
import sys
|
|
9
9
|
from dataclasses import asdict, dataclass, field
|
|
10
10
|
|
|
11
|
-
from github import
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
from github import Auth, Github, GithubIntegration
|
|
12
|
+
from github.GithubException import (
|
|
13
|
+
BadCredentialsException,
|
|
14
14
|
GithubException,
|
|
15
|
-
GithubIntegration,
|
|
16
15
|
UnknownObjectException,
|
|
17
16
|
)
|
|
18
|
-
from github.GithubException import BadCredentialsException
|
|
19
17
|
from github.NamedUser import NamedUser
|
|
20
18
|
from github.Organization import Organization
|
|
21
19
|
from github.Repository import Repository
|
|
@@ -54,6 +52,7 @@ class GHorg: # pylint: disable=too-many-instance-attributes, too-many-lines
|
|
|
54
52
|
current_repos_collaborators: dict[Repository, dict[str, str]] = field(default_factory=dict)
|
|
55
53
|
configured_repos_collaborators: dict[str, dict[str, str]] = field(default_factory=dict)
|
|
56
54
|
archived_repos: list[Repository] = field(default_factory=list)
|
|
55
|
+
unconfigured_teams: list[Team] = field(default_factory=list)
|
|
57
56
|
unconfigured_team_repo_permissions: dict[str, dict[str, str]] = field(default_factory=dict)
|
|
58
57
|
stats: OrgChanges = field(default_factory=OrgChanges)
|
|
59
58
|
|
|
@@ -84,8 +83,9 @@ class GHorg: # pylint: disable=too-many-instance-attributes, too-many-lines
|
|
|
84
83
|
|
|
85
84
|
# Decide how to login. If app set, prefer this
|
|
86
85
|
if self.gh_app_id and self.gh_app_private_key:
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
gh_app_id_sanitized = str(self.gh_app_id).strip("'").strip('"')
|
|
87
|
+
logging.debug("Logging in via app %s", gh_app_id_sanitized)
|
|
88
|
+
auth = Auth.AppAuth(app_id=gh_app_id_sanitized, private_key=self.gh_app_private_key)
|
|
89
89
|
app = GithubIntegration(auth=auth)
|
|
90
90
|
try:
|
|
91
91
|
installation = app.get_org_installation(org=orgname)
|
|
@@ -202,9 +202,16 @@ class GHorg: # pylint: disable=too-many-instance-attributes, too-many-lines
|
|
|
202
202
|
return True
|
|
203
203
|
|
|
204
204
|
def _is_user_authenticated_user(self, user: NamedUser) -> bool:
|
|
205
|
-
"""Check if a given NamedUser is the authenticated user
|
|
206
|
-
|
|
207
|
-
|
|
205
|
+
"""Check if a given NamedUser is the authenticated user. If logging in via App, this will
|
|
206
|
+
always return False, as the authenticated user is the App itself"""
|
|
207
|
+
try:
|
|
208
|
+
if user.login == self.gh.get_user().login:
|
|
209
|
+
return True
|
|
210
|
+
except GithubException as e:
|
|
211
|
+
if e.status == 403 and "Resource not accessible by integration" in str(e):
|
|
212
|
+
logging.debug("Cannot check if user is authenticated, as this is an App login")
|
|
213
|
+
return False
|
|
214
|
+
raise
|
|
208
215
|
return False
|
|
209
216
|
|
|
210
217
|
def sync_org_owners(self, dry: bool = False, force: bool = False) -> None:
|
|
@@ -296,7 +303,18 @@ class GHorg: # pylint: disable=too-many-instance-attributes, too-many-lines
|
|
|
296
303
|
for team, attributes in self.configured_teams.items():
|
|
297
304
|
if team not in existent_team_names:
|
|
298
305
|
if parent := attributes.get("parent"): # type: ignore
|
|
299
|
-
|
|
306
|
+
try:
|
|
307
|
+
parent_id = self.org.get_team_by_slug(sluggify_teamname(parent)).id
|
|
308
|
+
except UnknownObjectException:
|
|
309
|
+
if dry:
|
|
310
|
+
logging.debug(
|
|
311
|
+
"For team %s, the configured parent team's ('%s') ID wasn't found, "
|
|
312
|
+
"probably because it should be created but it's a dry-run. "
|
|
313
|
+
"We set a default ID of 424242",
|
|
314
|
+
team,
|
|
315
|
+
parent,
|
|
316
|
+
)
|
|
317
|
+
parent_id = 424242
|
|
300
318
|
|
|
301
319
|
logging.info("Creating team '%s' with parent ID '%s'", team, parent_id)
|
|
302
320
|
self.stats.create_team(team)
|
|
@@ -594,31 +612,38 @@ class GHorg: # pylint: disable=too-many-instance-attributes, too-many-lines
|
|
|
594
612
|
team.name,
|
|
595
613
|
)
|
|
596
614
|
|
|
597
|
-
def
|
|
615
|
+
def get_and_delete_unconfigured_teams(
|
|
598
616
|
self, dry: bool = False, delete_unconfigured_teams: bool = False
|
|
599
617
|
) -> None:
|
|
600
618
|
"""Get all teams that are not configured locally and optionally remove them"""
|
|
601
619
|
# Get all teams that are not configured locally
|
|
602
|
-
unconfigured_teams: list[Team] = []
|
|
603
620
|
for team in self.current_teams:
|
|
604
621
|
if team.name not in self.configured_teams:
|
|
605
|
-
unconfigured_teams.append(team)
|
|
622
|
+
self.unconfigured_teams.append(team)
|
|
606
623
|
|
|
607
|
-
if unconfigured_teams:
|
|
624
|
+
if self.unconfigured_teams:
|
|
608
625
|
if delete_unconfigured_teams:
|
|
609
|
-
for team in unconfigured_teams:
|
|
626
|
+
for team in self.unconfigured_teams:
|
|
610
627
|
logging.info("Deleting team '%s' as it is not configured locally", team.name)
|
|
611
628
|
self.stats.delete_team(team=team.name, deleted=True)
|
|
612
629
|
if not dry:
|
|
613
|
-
|
|
630
|
+
try:
|
|
631
|
+
team.delete()
|
|
632
|
+
except UnknownObjectException as e:
|
|
633
|
+
logging.info(
|
|
634
|
+
"Team '%s' could not be deleted, probably because it was already "
|
|
635
|
+
"deleted as part of a parent team. "
|
|
636
|
+
"Error: %s",
|
|
637
|
+
team.name,
|
|
638
|
+
e,
|
|
639
|
+
)
|
|
614
640
|
else:
|
|
615
|
-
unconfigured_teams_str = [team.name for team in unconfigured_teams]
|
|
616
641
|
logging.warning(
|
|
617
642
|
"The following teams of your GitHub organisation are not "
|
|
618
643
|
"configured locally: %s. Taking no action about these teams.",
|
|
619
|
-
", ".join(
|
|
644
|
+
", ".join([team.name for team in self.unconfigured_teams]),
|
|
620
645
|
)
|
|
621
|
-
for team in unconfigured_teams:
|
|
646
|
+
for team in self.unconfigured_teams:
|
|
622
647
|
self.stats.delete_team(team=team.name, deleted=False)
|
|
623
648
|
|
|
624
649
|
def get_members_without_team(
|
|
@@ -145,7 +145,7 @@ def main():
|
|
|
145
145
|
org.sync_teams_members(dry=args.dry)
|
|
146
146
|
# Report and act on teams that are not configured locally
|
|
147
147
|
log_progress("Checking for unconfigured teams...")
|
|
148
|
-
org.
|
|
148
|
+
org.get_and_delete_unconfigured_teams(
|
|
149
149
|
dry=args.dry,
|
|
150
150
|
delete_unconfigured_teams=cfg_app.get("delete_unconfigured_teams", False),
|
|
151
151
|
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|