Files
ephemere/python/cohort/add_github_team_members.py
T
naomi a40188413a docs: add data file documentation and fix data path resolution
All Python cohort scripts now use DATA_DIR = Path(__file__).parent.parent.parent / "data"
to correctly resolve the repo-root data/ directory regardless of the working directory
set by run.sh. All TypeScript scripts have expanded JSDoc headers documenting data file
requirements and environment variables.
2026-02-23 15:42:03 -08:00

148 lines
4.5 KiB
Python
Executable File

#!/usr/bin/env python3
"""Add GitHub users to their appropriate teams in the cohort GitHub organisation.
Uses the GitHub CLI to add each member to their corresponding team and, for
leaders, to the team's leaders sub-team.
Data files (place in data/):
- team_assignments.json Team rosters with leaders and participants per team
- discord_to_github.json Mapping of Discord IDs to GitHub usernames
Env vars:
- None (uses `gh` CLI for authentication)
"""
import json
import subprocess
import time
from pathlib import Path
DATA_DIR = Path(__file__).parent.parent.parent / "data"
# Load team assignments and Discord to GitHub mappings
with open(DATA_DIR / "team_assignments.json") as f:
teams = json.load(f)
with open(DATA_DIR / "discord_to_github.json") as f:
discord_to_github = json.load(f)
# Map team names to GitHub team slugs
team_name_to_slug = {
"Jade Jasmine": "jade-jasmine",
"Crimson Dahlia": "crimson-dahlia",
"Rose Camellia": "rose-camellia",
"Amber Wisteria": "amber-wisteria",
"Ivory Orchid": "ivory-orchid",
"Teal Iris": "teal-iris",
"Peach Gardenia": "peach-gardenia",
"Violet Carnation": "violet-carnation",
"Azure Lotus": "azure-lotus",
"Coral Sunflower": "coral-sunflower",
"Indigo Tulip": "indigo-tulip",
"Scarlet Hydrangea": "scarlet-hydrangea",
"Mint Narcissus": "mint-narcissus",
"Sage Marigold": "sage-marigold",
}
org = "nhcarrigan-spring-2026-cohort"
total_added = 0
total_skipped = 0
total_errors = 0
def add_user_to_team(username, team_slug, role="member"):
"""Add a user to a GitHub team"""
try:
# Check if user is already a member
check_cmd = (
f"gh api orgs/{org}/teams/{team_slug}/memberships/{username} 2>/dev/null"
)
result = subprocess.run(
check_cmd, shell=True, capture_output=True, text=True, check=False
)
if result.returncode == 0:
print(f"{username} is already in {team_slug}")
return "already_member"
# Add user to team
add_cmd = (
f"gh api -X PUT orgs/{org}/teams/{team_slug}/memberships/{username} "
f"-f role={role}"
)
result = subprocess.run(
add_cmd, shell=True, capture_output=True, text=True, check=False
)
if result.returncode == 0:
print(f" ✓ Added {username} to {team_slug} as {role}")
return "added"
else:
print(f" ✗ Failed to add {username} to {team_slug}: {result.stderr}")
return "error"
except Exception as e:
print(f" ✗ Error adding {username} to {team_slug}: {str(e)}")
return "error"
# Process each team
for team_data in teams:
team_name = team_data["name"]
team_slug = team_name_to_slug[team_name]
print(f"\n{'=' * 60}")
print(f"Processing Team {team_data['team_id']}: {team_name}")
print(f"{'=' * 60}")
# Add leaders to leaders team
leaders_team_slug = f"{team_slug}-leaders"
print(f"\nAdding leaders to {leaders_team_slug}:")
for discord_id in team_data["leaders"]:
github_username = discord_to_github.get(discord_id)
if not github_username or github_username == "nhcarrigan-2025-hackathon":
print(
f" ⚠ Skipping Discord ID {discord_id} - "
"Missing/invalid GitHub username"
)
total_skipped += 1
continue
result = add_user_to_team(github_username, leaders_team_slug, "member")
if result == "added":
total_added += 1
elif result == "error":
total_errors += 1
# Rate limiting
time.sleep(0.5)
# Add participants to main team
print(f"\nAdding participants to {team_slug}:")
for discord_id in team_data["participants"]:
github_username = discord_to_github.get(discord_id)
if not github_username or github_username == "nhcarrigan-2025-hackathon":
print(
f" ⚠ Skipping Discord ID {discord_id} - "
"Missing/invalid GitHub username"
)
total_skipped += 1
continue
result = add_user_to_team(github_username, team_slug, "member")
if result == "added":
total_added += 1
elif result == "error":
total_errors += 1
# Rate limiting
time.sleep(0.5)
print(f"\n{'=' * 60}")
print("Summary:")
print(f"- Total users added: {total_added}")
print(f"- Total users skipped (missing GitHub): {total_skipped}")
print(f"- Total errors: {total_errors}")
print(f"{'=' * 60}")