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

Synchronise org owners before teams #49

Merged
merged 1 commit into from
Aug 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
212 changes: 106 additions & 106 deletions gh_org_mgr/_gh_org.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,112 @@ def consolidate_team_config(self, default_team_configs: dict[str, str]) -> None:

logging.debug("Configuration for team '%s' consolidated to: %s", team_name, team_config)

# --------------------------------------------------------------------------
# Owners
# --------------------------------------------------------------------------
def _get_current_org_owners(self) -> None:
"""Get all owners of the org"""
# Reset the user list, then build up new list
self.current_org_owners = []
for member in self.org.get_members(role="admin"):
self.current_org_owners.append(member)

def _check_configured_org_owners(self) -> bool:
"""Check configured owners and make them lower-case for better
comparison. Returns True if owners are well configured."""
# Add configured owners if they are a list
if isinstance(self.configured_org_owners, list):
# Make all configured users lower-case
self.configured_org_owners = [user.lower() for user in self.configured_org_owners]
else:
logging.warning(
"The organisation owners are not configured as a proper list. Will not handle them."
)
self.configured_org_owners = []

if not self.configured_org_owners:
logging.warning(
"No owners for your GitHub organisation configured. Will not make any "
"change regarding the ownership, and continue with the current owners: %s",
", ".join([user.login for user in self.current_org_owners]),
)
return False

return True

def _is_user_authenticated_user(self, user: NamedUser) -> bool:
"""Check if a given NamedUser is the authenticated user"""
if user.login == self.gh.get_user().login:
return True
return False

def sync_org_owners(self, dry: bool = False, force: bool = False) -> None:
"""Synchronise the organization owners"""
# Get current and configured owners
self._get_current_org_owners()

# Abort owner synchronisation if no owners are configured, or badly
if not self._check_configured_org_owners():
return

# Get differences between the current and configured owners
owners_remove, owners_ok, owners_add = self.compare_two_lists(
self.configured_org_owners, [user.login for user in self.current_org_owners]
)
# Compare configured (lower-cased) owners with lower-cased list of current owners
if not owners_remove and not owners_add:
logging.info("Organization owners are in sync, no changes")
return

logging.debug(
"Organization owners are not in sync. Config: '%s' vs. Current: '%s'",
self.configured_org_owners,
self.current_org_owners,
)
logging.debug(
"Will remove %s, will not change %s, will add %s", owners_remove, owners_ok, owners_add
)

# Add the missing owners
for user in owners_add:
if gh_user := self._resolve_gh_username(user, "<org owners>"):
logging.info("Adding user '%s' as organization owner", gh_user.login)
if not dry:
self.org.add_to_members(gh_user, "admin")

# Remove the surplus owners
for user in owners_remove:
if gh_user := self._resolve_gh_username(user, "<org owners>"):
logging.info(
"User '%s' is not configured as organization owners. "
"Will make them a normal member",
gh_user.login,
)
# Handle authenticated user being the same as the one you want to degrade
if self._is_user_authenticated_user(gh_user):
logging.warning(
"The user '%s' you want to remove from owners is the one you "
"authenticated with. This may disrupt all further operations. "
"Unless you run the program with --force, "
"this operation will not be executed.",
gh_user.login,
)
# Check if user forced this operation
if force:
logging.info(
"You called the program with --force, "
"so it will remove yourself from the owners"
)
else:
continue

# Execute the degradation of the owner
if not dry:
self.org.add_to_members(gh_user, "member")

# Update the current organisation owners
self._get_current_org_owners()

# --------------------------------------------------------------------------
# Teams
# --------------------------------------------------------------------------
Expand Down Expand Up @@ -343,112 +449,6 @@ def sync_current_teams_settings(self, dry: bool = False) -> None:
else:
logging.info("Team '%s' settings are in sync, no changes", team.name)

# --------------------------------------------------------------------------
# Owners
# --------------------------------------------------------------------------
def _get_current_org_owners(self) -> None:
"""Get all owners of the org"""
# Reset the user list, then build up new list
self.current_org_owners = []
for member in self.org.get_members(role="admin"):
self.current_org_owners.append(member)

def _check_configured_org_owners(self) -> bool:
"""Check configured owners and make them lower-case for better
comparison. Returns True if owners are well configured."""
# Add configured owners if they are a list
if isinstance(self.configured_org_owners, list):
# Make all configured users lower-case
self.configured_org_owners = [user.lower() for user in self.configured_org_owners]
else:
logging.warning(
"The organisation owners are not configured as a proper list. Will not handle them."
)
self.configured_org_owners = []

if not self.configured_org_owners:
logging.warning(
"No owners for your GitHub organisation configured. Will not make any "
"change regarding the ownership, and continue with the current owners: %s",
", ".join([user.login for user in self.current_org_owners]),
)
return False

return True

def _is_user_authenticated_user(self, user: NamedUser) -> bool:
"""Check if a given NamedUser is the authenticated user"""
if user.login == self.gh.get_user().login:
return True
return False

def sync_org_owners(self, dry: bool = False, force: bool = False) -> None:
"""Synchronise the organization owners"""
# Get current and configured owners
self._get_current_org_owners()

# Abort owner synchronisation if no owners are configured, or badly
if not self._check_configured_org_owners():
return

# Get differences between the current and configured owners
owners_remove, owners_ok, owners_add = self.compare_two_lists(
self.configured_org_owners, [user.login for user in self.current_org_owners]
)
# Compare configured (lower-cased) owners with lower-cased list of current owners
if not owners_remove and not owners_add:
logging.info("Organization owners are in sync, no changes")
return

logging.debug(
"Organization owners are not in sync. Config: '%s' vs. Current: '%s'",
self.configured_org_owners,
self.current_org_owners,
)
logging.debug(
"Will remove %s, will not change %s, will add %s", owners_remove, owners_ok, owners_add
)

# Add the missing owners
for user in owners_add:
if gh_user := self._resolve_gh_username(user, "<org owners>"):
logging.info("Adding user '%s' as organization owner", gh_user.login)
if not dry:
self.org.add_to_members(gh_user, "admin")

# Remove the surplus owners
for user in owners_remove:
if gh_user := self._resolve_gh_username(user, "<org owners>"):
logging.info(
"User '%s' is not configured as organization owners. "
"Will make them a normal member",
gh_user.login,
)
# Handle authenticated user being the same as the one you want to degrade
if self._is_user_authenticated_user(gh_user):
logging.warning(
"The user '%s' you want to remove from owners is the one you "
"authenticated with. This may disrupt all further operations. "
"Unless you run the program with --force, "
"this operation will not be executed.",
gh_user.login,
)
# Check if user forced this operation
if force:
logging.info(
"You called the program with --force, "
"so it will remove yourself from the owners"
)
else:
continue

# Execute the degradation of the owner
if not dry:
self.org.add_to_members(gh_user, "member")

# Update the current organisation owners
self._get_current_org_owners()

# --------------------------------------------------------------------------
# Members
# --------------------------------------------------------------------------
Expand Down
4 changes: 2 additions & 2 deletions gh_org_mgr/manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,12 @@ def main():
# Get current rate limit
org.ratelimit()

# Synchronise organisation owners
org.sync_org_owners(dry=args.dry, force=args.force)
# Create teams that aren't present at Github yet
org.create_missing_teams(dry=args.dry)
# Configure general settings of teams
org.sync_current_teams_settings(dry=args.dry)
# Synchronise organisation owners
org.sync_org_owners(dry=args.dry, force=args.force)
# Synchronise the team memberships
org.sync_teams_members(dry=args.dry)
# Report about organisation members that do not belong to any team
Expand Down