Skip to content
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
41 changes: 41 additions & 0 deletions .github/workflows/real-test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# SPDX-FileCopyrightText: 2025 DB Systel GmbH
#
# SPDX-License-Identifier: Apache-2.0

name: Test with real GitHub org

on:
pull_request:
workflow_dispatch:

jobs:
selftest:
runs-on: ubuntu-24.04
env:
GITHUB_APP_ID: ${{ secrets.TEST_GITHUB_APP_ID }}
GITHUB_APP_PRIVATE_KEY: ${{ secrets.TEST_GITHUB_APP_PRIVATE_KEY }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- uses: ./.github/actions/poetrybuild
- name: Replace data in config files
run: |
sed -i "s/TEST_GITHUB_ORG/${{ secrets.TEST_GITHUB_ORG }}/g" tests/data/config/org_files/*.yaml
sed -i "s/TEST_USER/${{ secrets.TEST_USER }}/g" tests/data/config/org_files/*.yaml
sed -i "s/TEST_USER/${{ secrets.TEST_USER }}/g" tests/data/config/teams_files/*.yaml
- name: Prepare for first run
run: |
mkdir -p tests/data/config/teams
cp tests/data/config/teams_files/teams_changes.yaml tests/data/config/teams/teams.yaml
cp tests/data/config/org_files/org_changes.yaml tests/data/config/org.yaml
- name: Run 1 (changes) - dry run
run: poetry run gh-org-mgr sync -c tests/data/config/ --dry -vv
- name: Run 1 (changes) - prod run
run: poetry run gh-org-mgr sync -c tests/data/config/ -vv
- name: Prepare for second run, reverting to original state
run: |
cp tests/data/config/teams_files/teams_orig.yaml tests/data/config/teams/teams.yaml
cp tests/data/config/org_files/org_orig.yaml tests/data/config/org.yaml
- name: Run 2 (revert) - dry run
run: poetry run gh-org-mgr sync -c tests/data/config/ --dry -vv
- name: Run 2 (revert) - prod run
run: poetry run gh-org-mgr sync -c tests/data/config/ -vv
47 changes: 32 additions & 15 deletions gh_org_mgr/_gh_org.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,12 @@
import sys
from dataclasses import asdict, dataclass, field

from github import (
Auth,
Github,
from github import Auth, Github, GithubIntegration
from github.GithubException import (
BadCredentialsException,
GithubException,
GithubIntegration,
UnknownObjectException,
)
from github.GithubException import BadCredentialsException
from github.NamedUser import NamedUser
from github.Organization import Organization
from github.Repository import Repository
Expand Down Expand Up @@ -54,6 +52,7 @@ class GHorg: # pylint: disable=too-many-instance-attributes, too-many-lines
current_repos_collaborators: dict[Repository, dict[str, str]] = field(default_factory=dict)
configured_repos_collaborators: dict[str, dict[str, str]] = field(default_factory=dict)
archived_repos: list[Repository] = field(default_factory=list)
unconfigured_teams: list[Team] = field(default_factory=list)
unconfigured_team_repo_permissions: dict[str, dict[str, str]] = field(default_factory=dict)
stats: OrgChanges = field(default_factory=OrgChanges)

Expand Down Expand Up @@ -296,7 +295,18 @@ def create_missing_teams(self, dry: bool = False):
for team, attributes in self.configured_teams.items():
if team not in existent_team_names:
if parent := attributes.get("parent"): # type: ignore
parent_id = self.org.get_team_by_slug(sluggify_teamname(parent)).id
try:
parent_id = self.org.get_team_by_slug(sluggify_teamname(parent)).id
except UnknownObjectException:
if dry:
logging.debug(
"For team %s, the configured parent team's ('%s') ID wasn't found, "
"probably because it should be created but it's a dry-run. "
"We set a default ID of 424242",
team,
parent,
)
parent_id = 424242

logging.info("Creating team '%s' with parent ID '%s'", team, parent_id)
self.stats.create_team(team)
Expand Down Expand Up @@ -594,31 +604,38 @@ def sync_teams_members(self, dry: bool = False) -> None: # pylint: disable=too-
team.name,
)

def get_unconfigured_teams(
def get_and_delete_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)
self.unconfigured_teams.append(team)

if unconfigured_teams:
if self.unconfigured_teams:
if delete_unconfigured_teams:
for team in unconfigured_teams:
for team in self.unconfigured_teams:
logging.info("Deleting team '%s' as it is not configured locally", team.name)
self.stats.delete_team(team=team.name, deleted=True)
if not dry:
team.delete()
try:
team.delete()
except UnknownObjectException as e:
logging.info(
"Team '%s' could not be deleted, probably because it was already "
"deleted as part of a parent team. "
"Error: %s",
team.name,
e,
)
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),
", ".join([team.name for team in self.unconfigured_teams]),
)
for team in unconfigured_teams:
for team in self.unconfigured_teams:
self.stats.delete_team(team=team.name, deleted=False)

def get_members_without_team(
Expand Down
2 changes: 1 addition & 1 deletion gh_org_mgr/manage.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ def main():
org.sync_teams_members(dry=args.dry)
# Report and act on teams that are not configured locally
log_progress("Checking for unconfigured teams...")
org.get_unconfigured_teams(
org.get_and_delete_unconfigured_teams(
dry=args.dry,
delete_unconfigured_teams=cfg_app.get("delete_unconfigured_teams", False),
)
Expand Down
5 changes: 5 additions & 0 deletions tests/data/config/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# SPDX-FileCopyrightText: 2025 DB Systel GmbH
# SPDX-License-Identifier: CC0-1.0

org.yaml
teams/teams.yaml
19 changes: 19 additions & 0 deletions tests/data/config/app.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# SPDX-FileCopyrightText: 2024 DB Systel GmbH
# SPDX-License-Identifier: CC0-1.0

# ------------------------------------------------------------------------------
# General configuration for this program
# ------------------------------------------------------------------------------

# github_token: ghp_test
# github_app_id: 12345
# github_app_private_key: |
# ------BEGIN RSA PRIVATE KEY-----
# ...
# ------END RSA PRIVATE KEY-----

# Delete teams that are not configured
delete_unconfigured_teams: true

# Remove members that are not configured
remove_members_without_team: true
24 changes: 24 additions & 0 deletions tests/data/config/org_files/org_changes.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# SPDX-FileCopyrightText: 2025 DB Systel GmbH
# SPDX-License-Identifier: CC0-1.0

# ------------------------------------------------------------------------------
# General configuration for the GitHub organisation
# ------------------------------------------------------------------------------

# Name of the GitHub organisation
org_name: TEST_GITHUB_ORG
org_owners:
- TEST_USER

# Default settings. Will be overridden if set in a team.
# If neither defaults nor team settings are present:
# - when creating a new team, will take GitHub's defaults.
# - when syncing settting of a team, will not touch the current status.
defaults:
team:
# Description of a team
# description: ""
# Level of privacy of a team. Can be "secret" or "closed"
privacy: "secret"
# Notification setting of a team. Can be "notifications_enabled" or "notifications_disabled"
notification_setting: "notifications_enabled"
24 changes: 24 additions & 0 deletions tests/data/config/org_files/org_orig.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# SPDX-FileCopyrightText: 2025 DB Systel GmbH
# SPDX-License-Identifier: CC0-1.0

# ------------------------------------------------------------------------------
# General configuration for the GitHub organisation
# ------------------------------------------------------------------------------

# Name of the GitHub organisation
org_name: TEST_GITHUB_ORG
org_owners:
- TEST_USER

# Default settings. Will be overridden if set in a team.
# If neither defaults nor team settings are present:
# - when creating a new team, will take GitHub's defaults.
# - when syncing settting of a team, will not touch the current status.
defaults:
team:
# Description of a team
# description: ""
# Level of privacy of a team. Can be "secret" or "closed"
privacy: "closed"
# Notification setting of a team. Can be "notifications_enabled" or "notifications_disabled"
notification_setting: "notifications_enabled"
29 changes: 29 additions & 0 deletions tests/data/config/teams_files/teams_changes.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# SPDX-FileCopyrightText: 2025 DB Systel GmbH
# SPDX-License-Identifier: CC0-1.0

Test1:
description: First test team with a new description
privacy: closed
member:
- TEST_USER

Test2:
parent: Test1
privacy: closed
description: Second test team
maintainer:
- TEST_USER

Test3:
notification_setting: notifications_disabled
privacy: closed

Test3-child:
parent: Test3
description: Child of Test3
privacy: closed
member:
- TEST_USER

Test4:
member:
11 changes: 11 additions & 0 deletions tests/data/config/teams_files/teams_orig.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# SPDX-FileCopyrightText: 2025 DB Systel GmbH
# SPDX-License-Identifier: CC0-1.0

Test1:
description: First test team
member:

Test2:
privacy: secret
description: Second test team
member:
Loading