Skip to content

Commit a2587a5

Browse files
authored
Merge pull request #2 from bytebase/oncall-sync-implementation
Add automated oncall rotation sync to Google Group
2 parents 9aa3447 + 03e081d commit a2587a5

14 files changed

Lines changed: 2138 additions & 1 deletion

File tree

.github/workflows/sync-oncall.yml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
name: Sync Oncall to Google Group
2+
3+
on:
4+
schedule:
5+
# Run daily at 01:00 UTC (rotation starts at 00:00 UTC)
6+
- cron: '0 1 * * *'
7+
push:
8+
branches:
9+
- main
10+
workflow_dispatch: # Allow manual trigger
11+
12+
jobs:
13+
sync:
14+
runs-on: ubuntu-latest
15+
steps:
16+
- name: Checkout code
17+
uses: actions/checkout@v4
18+
19+
- name: Set up Go
20+
uses: actions/setup-go@v5
21+
with:
22+
go-version: '1.23'
23+
24+
- name: Build synconcall
25+
run: |
26+
cd synconcall
27+
go build -o synconcall
28+
29+
- name: Sync oncall rotation
30+
env:
31+
GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_SERVICE_ACCOUNT }}
32+
run: |
33+
cd synconcall
34+
./synconcall --config=../dev.oncall --group=dev-oncall@bytebase.com --admin-user=d@bytebase.com

.github/workflows/test.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Test
2+
3+
on:
4+
pull_request:
5+
branches: [ main ]
6+
7+
jobs:
8+
test:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- name: Checkout code
12+
uses: actions/checkout@v4
13+
14+
- name: Set up Go
15+
uses: actions/setup-go@v5
16+
with:
17+
go-version: '1.23'
18+
19+
- name: Run Go tests
20+
run: |
21+
cd synconcall
22+
go test -v ./...
23+
24+
- name: Validate dev.oncall schedule
25+
run: |
26+
cd synconcall
27+
go run . validate --config=../dev.oncall

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
synconcall/synconcall

README.md

Lines changed: 135 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,135 @@
1-
# oncall
1+
# Oncall Rotation System
2+
3+
Automated oncall rotation management system that syncs the current oncall schedule to a Google Group.
4+
5+
## Overview
6+
7+
This repository contains:
8+
- **`dev.oncall`**: Oncall rotation schedule (CSV format)
9+
- **`synconcall/`**: Go CLI tool that syncs current rotation to Google Group
10+
- **GitHub Actions**: Automated daily sync workflow
11+
12+
## Quick Start
13+
14+
### Schedule File Format
15+
16+
Edit `dev.oncall` to define your rotation schedule:
17+
18+
```csv
19+
2026-01-12T00:00:00Z,d@bytebase.com,vh@bytebase.com
20+
2026-02-09T00:00:00Z,vh@bytebase.com,xz@bytebase.com
21+
2026-03-09T00:00:00Z,xz@bytebase.com,zp@bytebase.com
22+
```
23+
24+
Each line: `start_time,primary_email,secondary_email`
25+
- Timestamps in RFC3339 format (ISO 8601)
26+
- Rotations in chronological order
27+
- Each rotation period starts at the specified timestamp
28+
29+
### How It Works
30+
31+
1. GitHub Actions runs daily (configurable)
32+
2. Reads `dev.oncall` to determine current rotation
33+
3. Syncs Google Group membership to match current primary + secondary
34+
4. Old oncall members are removed, current ones are added
35+
36+
The sync is **declarative** - the group always reflects exactly who is currently oncall.
37+
38+
## Setup
39+
40+
**Service Account:** `dev-tools@bytebase-dev.iam.gserviceaccount.com`
41+
42+
### 1. Create Service Account
43+
44+
1. Go to [Google Cloud Console](https://console.cloud.google.com/)
45+
2. Create a service account
46+
3. Download JSON key file
47+
4. Enable domain-wide delegation
48+
49+
### 2. Grant API Permissions
50+
51+
In Google Workspace Admin Console:
52+
1. Go to Security > API Controls > Domain-wide Delegation
53+
2. Add the service account client ID
54+
3. Grant OAuth scopes (comma-separated):
55+
- `https://www.googleapis.com/auth/admin.directory.group,https://www.googleapis.com/auth/admin.directory.group.member`
56+
57+
**Note:** The service account uses domain-wide delegation to impersonate a domain admin user (`d@bytebase.com`) to access the Admin SDK.
58+
59+
### 3. Configure GitHub Secrets
60+
61+
Add repository secret:
62+
- Name: `GOOGLE_SERVICE_ACCOUNT`
63+
- Value: Contents of the service account JSON key file
64+
65+
### 4. Customize Workflow
66+
67+
Edit `.github/workflows/sync-oncall.yml`:
68+
- Change cron schedule (default: daily at midnight UTC)
69+
- Update group email if different from `dev-oncall@bytebase.com`
70+
71+
## Manual Sync
72+
73+
Build and run locally:
74+
75+
```bash
76+
cd synconcall
77+
go build -o synconcall
78+
79+
GOOGLE_CREDENTIALS="$(cat /path/to/service-account.json)" \
80+
./synconcall --config=../dev.oncall --group=dev-oncall@bytebase.com --admin-user=d@bytebase.com
81+
```
82+
83+
## Updating the Schedule
84+
85+
1. Edit `dev.oncall` to add new rotation periods
86+
2. Commit and push changes
87+
3. Next scheduled run will pick up the changes
88+
4. Or trigger manually: Actions tab → "Sync Oncall to Google Group" → Run workflow
89+
90+
## Project Structure
91+
92+
```
93+
oncall/
94+
├── dev.oncall # Rotation schedule
95+
├── synconcall/ # Sync tool
96+
│ ├── main.go # CLI entry point
97+
│ ├── schedule.go # Schedule parsing
98+
│ ├── groups.go # Google API client
99+
│ ├── sync.go # Sync logic
100+
│ ├── *_test.go # Comprehensive tests
101+
│ └── README.md # Tool documentation
102+
├── .github/workflows/
103+
│ └── sync-oncall.yml # Automated sync workflow
104+
└── docs/plans/
105+
└── 2026-01-23-oncall-sync-design.md # Design document
106+
```
107+
108+
## Testing
109+
110+
Run tests:
111+
```bash
112+
cd synconcall
113+
go test -v
114+
```
115+
116+
## Troubleshooting
117+
118+
### Sync fails with authentication error
119+
- Check service account has domain-wide delegation enabled
120+
- Verify OAuth scopes are granted correctly
121+
- Ensure JSON key is valid in GitHub secrets
122+
123+
### Members not updating
124+
- Check schedule file format (timestamps, emails)
125+
- Verify current time falls within a rotation period
126+
- Check GitHub Actions logs for errors
127+
128+
### Wrong people in group
129+
- Verify `dev.oncall` has correct rotation schedule
130+
- Check timestamps are in chronological order
131+
- Ensure timestamps use RFC3339 format with timezone
132+
133+
## Design Documentation
134+
135+
See [docs/plans/2026-01-23-oncall-sync-design.md](docs/plans/2026-01-23-oncall-sync-design.md) for detailed design decisions and architecture.

0 commit comments

Comments
 (0)