GitHub Team Management
Overview
Repository access is controlled through GitHub Teams, which are automatically synced from Keycloak groups via SCIM.
Principle: Keycloak is the source of truth, GitHub teams mirror Keycloak groups.
Team Structure
@company-org/
├── @all-engineering (all engineers, read-all)
├── @backend-team (backend repos, write)
├── @frontend-team (frontend repos, write)
├── @devops-team (infrastructure repos, write + admin)
├── @mobile-team (mobile app repos, write)
├── @security-team (security reviews)
└── @admins (org-level admins)
Repository Access Model
Public vs Private Repositories
- Private repos (default): Require team membership for access
- Internal repos: Visible to all org members, write access requires team membership
- Public repos: Only for open-source projects, strict review required
Default: All company repos are private.
Access Levels
| Role | Permissions | Use Case |
|---|---|---|
| Read | Clone, pull, view issues/PRs | Default for all engineers |
| Triage | Manage issues, no code changes | Product managers, support |
| Write | Push, create branches, merge PRs | Team members |
| Maintain | Manage repo settings (no danger) | Tech leads |
| Admin | Full control including deletion | DevOps, CTO only |
Team-to-Repository Mapping
Backend Team
Keycloak Group: engineering-backend
GitHub Team: @backend-team
Repositories (Write Access):
api-serverauth-servicenotification-workershared-backend-libs
Repositories (Admin Access):
- None (DevOps manages repo settings)
Frontend Team
Keycloak Group: engineering-frontend
GitHub Team: @frontend-team
Repositories (Write Access):
web-appadmin-dashboardshared-ui-componentsdesign-system
DevOps Team
Keycloak Group: engineering-devops
GitHub Team: @devops-team
Repositories (Write Access):
infrastructure(Ansible playbooks)terraform-configsdocker-images.github(org-level workflows)
Repositories (Admin Access):
- All repositories (for settings management, branch protection)
Cross-Team Repositories
Some repos need access from multiple teams:
Example: shared-libraries
@backend-team→ Write@frontend-team→ Write@mobile-team→ Write
Managed via: Repository settings → Collaborators and teams
Branch Protection Rules
All production code repositories must have branch protection on main:
Standard Protection (All Repos)
Branch: main
Protections:
- Require pull request before merging
- Require 1 approval
- Dismiss stale reviews when new commits pushed
- Require status checks to pass
- CI build
- Unit tests
- Linting
- Security scan
- Require conversation resolution before merging
- Include administrators (yes - no one bypasses)
- Require linear history
- Allow force pushes: No
- Allow deletions: No
Infrastructure Repos (Extra Protection)
Branch: main
Additional protections:
- Require 2 approvals (peer + DevOps lead)
- Require code owner review
- Restrict who can push:
- @devops-team only
CODEOWNERS file:
# Infrastructure changes require DevOps approval
/ansible/ @devops-team
/terraform/ @devops-team
*.tf @devops-team
Required Status Checks
Every PR must pass these automated checks before merge:
Standard Checks (All Repos)
- Build: Code compiles/builds successfully
- Tests: All unit tests pass
- Lint: Code style checks pass
- Security: No high/critical vulnerabilities found
Defined in: .github/workflows/ci.yml
Additional Checks (By Repo Type)
Backend APIs:
- API contract tests
- Database migration tests
- Integration tests
Frontend:
- Visual regression tests (Chromatic/Percy)
- Accessibility tests
- Bundle size check
Infrastructure:
- Ansible syntax check
- Terraform plan validation
- Cost estimation (Infracost)
Code Review Requirements
Who Can Approve
Any team member can approve PRs for their team's repositories.
Special cases:
- Infrastructure changes → Require DevOps team member approval
- Security-sensitive code → Auto-tag
@security-teamfor review (async, non-blocking) - Breaking API changes → Require tech lead approval
Automated tagging based on file changes:
# .github/CODEOWNERS
/ansible/ @devops-team
/terraform/ @devops-team
**/auth* @security-team
**/secrets* @security-team
Review Expectations
Reviewers should check:
- ✅ Code quality and readability
- ✅ Tests included for new features
- ✅ No obvious security issues
- ✅ Documentation updated if needed
- ✅ No secrets committed
Not required:
- ❌ Perfection (we iterate)
- ❌ Complete rewrite suggestions
- ❌ Nitpicking formatting (linters handle that)
Timeline: Aim to review PRs within 24 hours (4 hours for urgent).
Automated Workflows
PR Auto-Labeling
PRs are automatically labeled based on changes:
# .github/workflows/labeler.yml
frontend:
- web-app/**/*
- admin-dashboard/**/*
backend:
- api-server/**/*
- auth-service/**/*
infrastructure:
- ansible/**/*
- terraform/**/*
security-review:
- "**/*auth*"
- "**/*secret*"
- "**/*password*"
Auto-Assign Reviewers
# .github/workflows/auto-assign.yml
# PRs automatically assigned to team members based on files changed
Dependency Updates (Dependabot)
# .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
reviewers:
- "frontend-team"
labels:
- "dependencies"
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"
reviewers:
- "backend-team"
Auto-merge minor updates if CI passes (via Dependabot auto-merge).
GitHub Actions Secrets
Secrets for CI/CD workflows are managed at different scopes:
Organization Secrets
Available to all repos:
DIGITALOCEAN_TOKEN- For deploymentsDOCKER_REGISTRY_TOKEN- For pushing imagesSLACK_WEBHOOK(if using) - For notifications
Who can manage: @devops-team only
Repository Secrets
Specific to one repo:
API_KEY_FOR_SERVICE_XDATABASE_URL_STAGING
Who can manage: Repo admins (@devops-team)
Environment Secrets
Tied to deployment environments:
Production environment:
- Requires approval from @devops-team
- Secrets:
PROD_DB_URL,PROD_API_KEY, etc.
Staging environment:
- No approval required
- Secrets:
STAGING_DB_URL, etc.
Common Tasks
Request Access to a Repository
Self-service (if you're in the right Keycloak group):
# Access granted automatically within 15 minutes via SCIM sync
# Just wait for the GitHub invitation email
Manual request (for special access):
# In Rocket.Chat
/access request github-repo=infrastructure-repo justification="Need to review Ansible playbook for bug fix"
Create a New Repository
- Create repo in GitHub
- Configure teams:
- Add
@all-engineeringwith Read - Add relevant team(s) with Write
- Add
@devops-teamwith Admin
- Add
- Set up branch protection (required)
- Add required status checks (CI workflow)
- Announce in Rocket.Chat #engineering
Template checklist: docs/06-self-service/new-service-checklist.md
Transfer Repository Ownership
When: Moving repo between teams
Process:
- Update team permissions in GitHub
- Update CODEOWNERS file
- Announce in both team channels
- Update documentation
Remove Someone's Access
Automatic when removed from Keycloak group:
- SCIM sync removes from GitHub team within 15 min
- GitHub automatically revokes repo access
Manual (immediate removal needed):
- Go to GitHub org → People
- Find user → Remove from organization
- Document reason in #security channel
Security Best Practices
Personal Access Tokens (PATs)
When to use: For local Git operations, API access
How to create:
- GitHub Settings → Developer settings → Personal access tokens → Fine-grained tokens
- Set expiration (max 90 days)
- Scope to specific repos only
- Minimum permissions needed
Do NOT:
- ❌ Use classic tokens (use fine-grained)
- ❌ Set no expiration
- ❌ Grant full org access
- ❌ Commit tokens to code
SSH Keys
Recommended over HTTPS for Git operations.
Setup:
# Generate key
ssh-keygen -t ed25519 -C "your.email@company.com"
# Add to GitHub
cat ~/.ssh/id_ed25519.pub
# Copy and paste into GitHub Settings → SSH Keys
Best practice: Different SSH keys for different machines.
Commit Signing
Recommended for all commits (not enforced yet).
Setup GPG signing:
# Generate GPG key
gpg --gen-key
# Configure Git
git config --global user.signingkey YOUR_KEY_ID
git config --global commit.gpgsign true
# Add public key to GitHub
gpg --armor --export YOUR_KEY_ID
# Paste into GitHub Settings → SSH and GPG keys
Monitoring & Auditing
GitHub audit log tracks:
- Repository access changes
- Team membership changes
- Branch protection modifications
- Secret access
- Failed auth attempts
Reviewed by: @devops-team weekly Alerts on:
- Org admin additions
- Repo deletions
- Branch protection removals
Audit export: Monthly backup to DigitalOcean Spaces
Troubleshooting
I can't access a repository:
- Check if you're in the right Keycloak group
- Wait 15 min for SCIM sync
- Check GitHub email for team invitation (accept it)
- If still blocked, post in #it-support
PR checks failing:
- Click "Details" on failing check
- Review error logs
- Fix locally and push again
- If CI is broken, post in #devops
Can't push to branch:
- Check if branch is protected (you need a PR)
- Check if you have write access to the repo
- Check if you need to update your local branch
Need urgent merge but reviewer unavailable:
- Tag another team member for review
- For emergencies: Tag @devops-team (can merge with override)
- Document why it was urgent in PR description