aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Joe Banks <[email protected]>2025-07-10 13:38:48 +0100
committerGravatar Joe Banks <[email protected]>2025-07-10 13:45:55 +0100
commitb169dc300f738c59e717d444445dfe0c8e6da98a (patch)
tree001737a929998b6798143ad65278e366ae1476c3
parentBetter handling of locking/unlocking users (diff)
Remove GitHub-Grafana team sync cog
-rw-r--r--arthur/apis/github/teams.py25
-rw-r--r--arthur/exts/grafana/github_team_sync.py172
2 files changed, 0 insertions, 197 deletions
diff --git a/arthur/apis/github/teams.py b/arthur/apis/github/teams.py
index 4cf18d4..a8775a3 100644
--- a/arthur/apis/github/teams.py
+++ b/arthur/apis/github/teams.py
@@ -1,32 +1,7 @@
-import aiohttp
-
from arthur.config import CONFIG
-from arthur.log import logger
HEADERS = {
"Accept": "application/vnd.github+json",
"X-GitHub-Api-Version": "2022-11-28",
"Authorization": f"Bearer {CONFIG.github_token.get_secret_value()}",
}
-BASE_URL = "https://api.github.com"
-MEMBERS_PER_PAGE = 100
-
-
-class GithubTeamNotFoundError(aiohttp.ClientResponseError):
- """Raised when a github team could not be found."""
-
-
-async def list_team_members(team_slug: str, session: aiohttp.ClientSession) -> list[dict[str, str]]:
- """List all Github teams."""
- endpoint = f"{BASE_URL}/orgs/{CONFIG.github_org}/teams/{team_slug}/members"
- params = {"per_page": MEMBERS_PER_PAGE}
- async with session.get(endpoint, headers=HEADERS, params=params) as response:
- response.raise_for_status()
- teams_resp = await response.json()
- if len(teams_resp) == MEMBERS_PER_PAGE:
- logger.warning(
- "Max number (%d) of members returned when fetching members of %s. Some members may have been missed.",
- MEMBERS_PER_PAGE,
- team_slug,
- )
- return teams_resp
diff --git a/arthur/exts/grafana/github_team_sync.py b/arthur/exts/grafana/github_team_sync.py
deleted file mode 100644
index cfc1e77..0000000
--- a/arthur/exts/grafana/github_team_sync.py
+++ /dev/null
@@ -1,172 +0,0 @@
-import aiohttp
-import discord
-from discord.ext import commands, tasks
-
-from arthur.apis import github, grafana
-from arthur.bot import KingArthur
-from arthur.config import CONFIG
-from arthur.log import logger
-
-from . import MissingMembers, SyncFigures
-
-
-class GrafanaGitHubTeamSync(commands.Cog):
- """
- Update Grafana team membership to match Github team membership.
-
- Grafana team name must match Github team slug exactly.
- Use `gh api orgs/{org-name}/teams` to get a list of teams in an org
- """
-
- def __init__(self, bot: KingArthur) -> None:
- self.bot = bot
- self.sync_github_grafana_teams.start()
-
- async def _add_missing_members(
- self,
- grafana_team_id: int,
- github_team_members: set[str],
- grafana_team_members: set[str],
- all_grafana_users: list[dict],
- ) -> MissingMembers:
- """
- Adds members to the Grafana team if they're in the Github team and not already present.
-
- Returns the number of missing members, and the number of members it could actually add.
- """
- missing_members = github_team_members - grafana_team_members
- added_members = 0
- for grafana_user in all_grafana_users:
- if grafana_user["login"] not in missing_members:
- continue
- if "GitHub" not in grafana_user.get("authLabels", []):
- continue
-
- await grafana.add_user_to_team(
- grafana_user["userId"],
- grafana_team_id,
- self.bot.http_session,
- )
- added_members += 1
- return MissingMembers(count=len(missing_members), successfully_added=added_members)
-
- async def _remove_extra_members(
- self,
- grafana_team_id: int,
- github_team_members: set[str],
- grafana_team_members: set[str],
- all_grafana_users: list[dict],
- ) -> int:
- """
- Removes Grafana users from a team if they are not present in the Github team.
-
- Return how many were removed.
- """
- extra_members = grafana_team_members - github_team_members
- removed_members = 0
- for grafana_user in all_grafana_users:
- if grafana_user["login"] not in extra_members:
- continue
- await grafana.remove_user_from_team(
- grafana_user["userId"],
- grafana_team_id,
- self.bot.http_session,
- )
- removed_members += 1
- return removed_members
-
- async def _sync_teams(self, team: dict[str, str]) -> SyncFigures:
- """
- Ensure members in Github are present in Grafana teams.
-
- Return the number of members missing from the Grafana team, and the number of members added.
- """
- github_team_members = {
- member["login"]
- for member in await github.list_team_members(team["name"], self.bot.http_session)
- }
- grafana_team_members = {
- member["login"]
- for member in await grafana.list_team_members(team["id"], self.bot.http_session)
- if member.get("auth_module") == "oauth_github"
- }
-
- all_grafana_users = await grafana.get_all_users(self.bot.http_session)
- added_members = await self._add_missing_members(
- team["id"],
- github_team_members,
- grafana_team_members,
- all_grafana_users,
- )
- removed_members = await self._remove_extra_members(
- team["id"],
- github_team_members,
- grafana_team_members,
- all_grafana_users,
- )
-
- return SyncFigures(added=added_members, removed=removed_members)
-
- @tasks.loop(hours=12)
- async def sync_github_grafana_teams(self, channel: discord.TextChannel | None = None) -> None:
- """Update Grafana team membership to match Github team membership."""
- grafana_teams = await grafana.list_teams(self.bot.http_session)
- embed = discord.Embed(
- title="Sync Stats",
- colour=discord.Colour.blue(),
- )
- for team in grafana_teams:
- logger.debug(f"Processing {team['name']}")
- try:
- figures = await self._sync_teams(team)
- except aiohttp.ClientResponseError as e:
- logger.error(e)
- if channel:
- await channel.send(e)
- continue
-
- lines = [
- f"Missing: {figures.added.count}",
- f"Added: {figures.added.successfully_added}",
- f"Removed: {figures.removed}",
- ]
- embed.add_field(
- name=team["name"],
- value="\n".join(lines),
- inline=False,
- )
-
- if channel:
- await channel.send(embed=embed)
-
- @sync_github_grafana_teams.error
- async def on_task_error(self, error: Exception) -> None:
- """Ensure task errors are output."""
- logger.error(error)
-
- @commands.group(name="grafana_github", invoke_without_command=True)
- async def grafana_group(self, ctx: commands.Context) -> None:
- """Commands for working with grafana API."""
- await ctx.send_help(ctx.command)
-
- @grafana_group.command(name="sync")
- async def sync_teams(self, ctx: commands.Context) -> None:
- """Sync Grafana & Github teams now."""
- await self.sync_github_grafana_teams(ctx.channel)
-
-
-async def setup(bot: KingArthur) -> None:
- """Add GrafanaGitHubTeamSync cog to bot."""
- if not all(
- (
- CONFIG.github_org,
- CONFIG.github_token,
- CONFIG.grafana_url,
- CONFIG.grafana_token,
- )
- ):
- logger.warning(
- "Not loading GrafanaGitHubTeamSync team as a required config entry is missing. See README"
- )
- return
- await bot.add_cog(GrafanaGitHubTeamSync(bot))