Skip to content

Commit 368476b

Browse files
feat: implement data-driven collaborator management
- Add collaborators.yaml as single source of truth - Auto-generate CODEOWNERS from collaborators list - Include power-edge and nikolauspschuetz as reviewers - Add pattern groupings with descriptions - Create COLLABORATORS.md documentation
1 parent 8b0d3e4 commit 368476b

File tree

5 files changed

+186
-32
lines changed

5 files changed

+186
-32
lines changed

.github/terraform/COLLABORATORS.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Collaborators Management
2+
3+
## Single Source of Truth: `collaborators.yaml`
4+
5+
All repository access, code review requirements, and CODEOWNERS are driven from `collaborators.yaml`.
6+
7+
### Structure
8+
9+
```yaml
10+
collaborators:
11+
- username: power-edge
12+
permission: admin # admin, maintain, push, triage, pull
13+
is_reviewer: true # Can review PRs
14+
is_owner: true # Organization owner
15+
16+
- username: nikolauspschuetz
17+
permission: push # write access
18+
is_reviewer: true # Can review PRs
19+
is_admin: true # Can bypass some protections
20+
```
21+
22+
### What Gets Generated
23+
24+
1. **GitHub Collaborators** (`collaborators.tf`)
25+
- Creates `github_repository_collaborator` resources
26+
- Skips `power-edge` (org owner already has access)
27+
- Grants permissions as specified
28+
29+
2. **CODEOWNERS File** (`main.tf`)
30+
- Auto-generated from `codeowner_patterns` in `collaborators.tf`
31+
- All reviewers (`is_reviewer: true`) are added to all patterns
32+
- Committed to `.github/CODEOWNERS`
33+
34+
3. **Review Requirements**
35+
- Branch protection uses CODEOWNERS
36+
- All reviewers must have at least `push` permission
37+
38+
### How to Add a New Collaborator
39+
40+
1. Edit `collaborators.yaml`:
41+
```yaml
42+
- username: new-user
43+
permission: push
44+
is_reviewer: false # or true if they can review PRs
45+
```
46+
47+
2. Apply Terraform:
48+
```bash
49+
cd .github/terraform
50+
source load-env.sh
51+
terraform apply
52+
```
53+
54+
3. User must accept invitation via email/GitHub
55+
56+
### File Patterns Requiring Review
57+
58+
Defined in `collaborators.tf` → `codeowner_patterns`:
59+
- `*` - Everything (default)
60+
- `/pymlb_statsapi/` - Core package
61+
- `/tests/` - Test files
62+
- `/.github/` - CI/CD and infrastructure
63+
- `/scripts/` - Scripts
64+
- `/docs/` - Documentation
65+
- `*.md` - Markdown files
66+
- `pyproject.toml`, `setup.py`, `*.cfg`, `*.ini` - Config files
67+
68+
To modify patterns, edit the `codeowner_patterns` list in `collaborators.tf`.
69+
70+
### Validation
71+
72+
- Reviewers must have at least `push` permission (enforced in code)
73+
- All patterns get all reviewers (simplified management)
74+
- CODEOWNERS is auto-committed on Terraform apply
75+
76+
### Outputs
77+
78+
- `collaborators_list` - All collaborator usernames
79+
- `reviewers_list` - Usernames who can review PRs

.github/terraform/collaborators.tf

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
# Repository Collaborators
2+
# Single source of truth: collaborators.yaml
3+
4+
locals {
5+
# Load collaborators from YAML file
6+
collaborators_raw = yamldecode(file("${path.module}/collaborators.yaml"))
7+
collaborators = local.collaborators_raw.collaborators
8+
9+
# Extract reviewers (must be collaborators with push+ permission)
10+
reviewers = [
11+
for collab in local.collaborators :
12+
collab.username
13+
if lookup(collab, "is_reviewer", false) == true
14+
]
15+
16+
# File patterns that require review with descriptions
17+
codeowner_patterns = [
18+
{
19+
description = "Default owners for everything in the repo"
20+
patterns = ["*"]
21+
},
22+
{
23+
description = "Core package code - requires review from maintainers"
24+
patterns = ["/pymlb_statsapi/"]
25+
},
26+
{
27+
description = "Tests - maintainers review"
28+
patterns = ["/tests/"]
29+
},
30+
{
31+
description = "Infrastructure and CI/CD - requires admin review"
32+
patterns = ["/.github/", "/scripts/"]
33+
},
34+
{
35+
description = "Documentation"
36+
patterns = ["/docs/", "*.md"]
37+
},
38+
{
39+
description = "Configuration files - requires careful review"
40+
patterns = ["pyproject.toml", "setup.py", "*.cfg", "*.ini"]
41+
},
42+
]
43+
44+
# Generate CODEOWNERS content
45+
reviewers_list = join(" ", [for r in local.reviewers : "@${r}"])
46+
47+
codeowners_content = <<-EOT
48+
# Code Owners for PyMLB StatsAPI
49+
# Auto-generated from collaborators.yaml - DO NOT EDIT MANUALLY
50+
#
51+
# These users/teams will be automatically requested for review when someone
52+
# opens a pull request that modifies files matching the patterns below.
53+
#
54+
# More info: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
55+
56+
${join("\n\n", [
57+
for group in local.codeowner_patterns :
58+
"# ${group.description}\n${join("\n", [for pattern in group.patterns : "${pattern} ${local.reviewers_list}"])}"
59+
])}
60+
EOT
61+
}
62+
63+
# Create collaborator resources from YAML
64+
resource "github_repository_collaborator" "collaborators" {
65+
for_each = {
66+
for collab in local.collaborators :
67+
collab.username => collab
68+
if collab.username != "power-edge" # Skip org owner (already has access)
69+
}
70+
71+
repository = github_repository.repo.name
72+
username = each.value.username
73+
permission = each.value.permission
74+
}
75+
76+
# Output for use in other resources
77+
output "collaborators_list" {
78+
description = "List of all collaborators"
79+
value = [for collab in local.collaborators : collab.username]
80+
}
81+
82+
output "reviewers_list" {
83+
description = "List of users who can review PRs"
84+
value = local.reviewers
85+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Single source of truth for repository collaborators
2+
# This file drives both GitHub collaborator settings and review requirements
3+
4+
collaborators:
5+
- username: power-edge
6+
permission: admin
7+
is_reviewer: true
8+
is_owner: true # Organization owner
9+
10+
- username: nikolauspschuetz
11+
permission: push # write access
12+
is_reviewer: true
13+
is_admin: true # Can bypass some protections
14+
15+
# Add more collaborators here:
16+
# - username: another-user
17+
# permission: push
18+
# is_reviewer: false

.github/terraform/main.tf

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ resource "github_repository_environment" "testpypi" {
209209
}
210210

211211
# CODEOWNERS file for automatic review requests
212+
# Dynamically generated from collaborators.yaml
212213
resource "github_repository_file" "codeowners" {
213214
repository = github_repository.repo.name
214215
branch = "main"
@@ -218,38 +219,9 @@ resource "github_repository_file" "codeowners" {
218219
commit_email = "nikolauspschuetz@gmail.com"
219220
overwrite_on_create = true
220221

221-
content = <<-EOT
222-
# Code Owners for PyMLB StatsAPI
223-
#
224-
# These users/teams will be automatically requested for review when someone
225-
# opens a pull request that modifies files matching the patterns below.
226-
#
227-
# More info: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
228-
229-
# Default owners for everything in the repo
230-
# power-edge is the organization owner and ultimate admin
231-
* @power-edge @nikolauspschuetz
232-
233-
# Core package code - requires review from maintainers
234-
/pymlb_statsapi/ @power-edge @nikolauspschuetz
235-
236-
# Tests - maintainers review
237-
/tests/ @power-edge @nikolauspschuetz
238-
239-
# Infrastructure and CI/CD - requires admin review
240-
/.github/ @power-edge @nikolauspschuetz
241-
/scripts/ @power-edge @nikolauspschuetz
242-
243-
# Documentation
244-
/docs/ @power-edge @nikolauspschuetz
245-
*.md @power-edge @nikolauspschuetz
246-
247-
# Configuration files - requires careful review
248-
pyproject.toml @power-edge @nikolauspschuetz
249-
setup.py @power-edge @nikolauspschuetz
250-
*.cfg @power-edge @nikolauspschuetz
251-
*.ini @power-edge @nikolauspschuetz
252-
EOT
222+
content = local.codeowners_content
223+
224+
depends_on = [github_repository_collaborator.collaborators]
253225
}
254226

255227
# Outputs for documentation

.github/terraform/tfplan

18.3 KB
Binary file not shown.

0 commit comments

Comments
 (0)