Skip to content

Commit

Permalink
Merge pull request #80 from OpenRailAssociation/remove-surplus-member…
Browse files Browse the repository at this point in the history
…s-and-teams
  • Loading branch information
mxmehl authored Feb 20, 2025
2 parents ae19bc1 + d091001 commit 4d96ee0
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 19 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Afterwards, the tool is executable with the command `gh-org-mgr`. The `--help` f

Inside [`config/example`](./config/example), you can find an example configuration that shall help you to understand the structure:

* `app.yaml`: Configuration necessary to run this tool
* `app.yaml`: Configuration necessary to run this tool and controlling some behaviour
* `org.yaml`: Organization-wide configuration
* `teams/*.yaml`: Configuration concerning the teams of your organization.

Expand Down
7 changes: 7 additions & 0 deletions config/example/app.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,10 @@ github_app_private_key: |
D9zgrlJ8D4bxPrwDrCuXHY7s/1/uCX3K+mS7CWpybOcJY4XzsNznOYcMQzw22fxl
u1ioG/s3Ahhd778VIjj5d32Xbjj8vbSFj8vJe5bBNblYbelWfETg
-----END RSA PRIVATE KEY-----
# Remove members from organisation who are not member of any team or
# organisation owners. Default: false
remove_members_without_team: false

# Delete teams that are not configured. Default: false
delete_unconfigured_teams: false
64 changes: 48 additions & 16 deletions gh_org_mgr/_gh_org.py
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,10 @@ def sync_teams_members(self, dry: bool = False) -> None: # pylint: disable=too-
open_invitations = [user.login.lower() for user in self.org.invitations()]

for team, team_attrs in self.current_teams.items():
# Ignore any team not being configured locally, will be handled later
if team.name not in self.configured_teams:
continue

# Update current team members with dict[NamedUser, str (role)]
team_attrs["members"] = self._get_current_team_members(team)

Expand All @@ -559,15 +563,6 @@ def sync_teams_members(self, dry: bool = False) -> None: # pylint: disable=too-
user.login.lower(): role for user, role in team_attrs["members"].items()
}

# Handle the team not being configured locally
if team.name not in self.configured_teams:
logging.warning(
"Team '%s' does not seem to be configured locally. "
"Taking no action about this team at all",
team.name,
)
continue

# Get configuration from current team
if team_configuration := self.configured_teams.get(team.name):
pass
Expand Down Expand Up @@ -666,8 +661,35 @@ def sync_teams_members(self, dry: bool = False) -> None: # pylint: disable=too-
team.name,
)

def get_members_without_team(self) -> None:
"""Get all organisation members without any team membership"""
def get_unconfigured_teams(
self, dry: bool = False, delete_unconfigured_teams: bool = False
) -> None:
"""Get all teams that are not configured locally and optionally remove them"""
# Get all teams that are not configured locally
unconfigured_teams: list[Team] = []
for team in self.current_teams:
if team.name not in self.configured_teams:
unconfigured_teams.append(team)

if unconfigured_teams:
if delete_unconfigured_teams:
for team in unconfigured_teams:
logging.info("Deleting team '%s' as it is not configured locally", team.name)
if not dry:
team.delete()
else:
unconfigured_teams_str = [team.name for team in unconfigured_teams]
logging.warning(
"The following teams of your GitHub organisation are not "
"configured locally: %s. Taking no action about these teams.",
", ".join(unconfigured_teams_str),
)

def get_members_without_team(
self, dry: bool = False, remove_members_without_team: bool = False
) -> None:
"""Get all organisation members without any team membership, and
optionally remove them"""
# Combine org owners and org members
all_org_members = set(self.org_members + self.current_org_owners)

Expand All @@ -685,11 +707,21 @@ def get_members_without_team(self) -> None:
members_without_team = all_org_members.difference(all_team_members)

if members_without_team:
members_without_team_str = [user.login for user in members_without_team]
logging.warning(
"The following members of your GitHub organisation are not member of any team: %s",
", ".join(members_without_team_str),
)
if remove_members_without_team:
for user in members_without_team:
logging.info(
"Removing user '%s' from organisation as they are not member of any team",
user.login,
)
if not dry:
self.org.remove_from_membership(user)
else:
members_without_team_str = [user.login for user in members_without_team]
logging.warning(
"The following members of your GitHub organisation are not "
"member of any team: %s",
", ".join(members_without_team_str),
)

# --------------------------------------------------------------------------
# Repos
Expand Down
12 changes: 10 additions & 2 deletions gh_org_mgr/manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,16 @@ def main():
org.sync_current_teams_settings(dry=args.dry)
# Synchronise the team memberships
org.sync_teams_members(dry=args.dry)
# Report about organisation members that do not belong to any team
org.get_members_without_team()
# Report and act on teams that are not configured locally
org.get_unconfigured_teams(
dry=args.dry,
delete_unconfigured_teams=cfg_app.get("delete_unconfigured_teams", False),
)
# Report and act on organisation members that do not belong to any team
org.get_members_without_team(
dry=args.dry,
remove_members_without_team=cfg_app.get("remove_members_without_team", False),
)
# Synchronise the permissions of teams for all repositories
org.sync_repo_permissions(dry=args.dry, ignore_archived=args.ignore_archived)
# Remove individual collaborator permissions if they are higher than the one
Expand Down

0 comments on commit 4d96ee0

Please sign in to comment.