An automated system for managing rotating responsibilities across engineering tasks. This system automatically assigns team members to various tasks on a weekly basis, sends notifications, and tracks assignments via GitHub issues.
The rotation system uses ISO week numbers to deterministically assign team members to tasks using a round-robin algorithm. Every week, the system:
- Calculates current and next week's assignments
- Creates a GitHub issue tracking the assignments
- Sends email notifications to all team members
- Posts a message to Slack with the assignments
- Automated Weekly Rotation: Runs automatically every Friday at 1:00 PM UTC
- Deterministic Assignment: Uses ISO week numbers for consistent, repeatable rotations
- Multiple Tasks: Support for multiple tasks with different staff rotations
- Multi-Channel Notifications: Email and Slack notifications
- GitHub Integration: Automatic issue creation and assignment
- Calendar View: Generate Markdown tables showing task assignments for any month
- Manual Triggering: Can be triggered manually for testing or special cases
- Dry-Run Mode: Test the system without sending notifications
Edit .github/rotation-config.yml to define your tasks and staff:
tasks:
- name: "DevOps Duty"
description: "Monitor production systems and handle deployments"
staff:
- alice-dev
- bob-engineer
- charlie-ops
email_addresses:
- alice@example.com
- bob@example.com
- charlie@example.com
notifications:
slack_channel: "#engineering"
timezone: "UTC"Important: The number of email_addresses must match the number of staff members for each task.
Configure the following secrets in your repository settings (Settings → Secrets and variables → Actions):
SMTP_HOST- SMTP server hostname (e.g.,smtp.gmail.com)SMTP_PORT- SMTP server port (e.g.,587)SMTP_USERNAME- SMTP authentication usernameSMTP_PASSWORD- SMTP authentication passwordSMTP_FROM_EMAIL- Email address to send from
SLACK_WEBHOOK_URL- Slack incoming webhook URL
GITHUB_TOKEN- Automatically provided by GitHub Actions (no setup needed)
Note: Email and Slack notifications are optional. The system will work with GitHub issues only if these secrets are not configured.
Ensure GitHub Actions is enabled for your repository:
- Go to repository Settings → Actions → General
- Under "Actions permissions", select "Allow all actions and reusable workflows"
- Save changes
Manually trigger the test workflow:
- Go to Actions tab
- Select "Test Rotation System" workflow
- Click "Run workflow"
- Enter a week number (e.g.,
1) - Click "Run workflow"
This will run in dry-run mode and show you what assignments would be made without sending notifications.
The configuration file (.github/rotation-config.yml) has two main sections:
Each task requires:
name: Task name (displayed in notifications and issues)description: Brief description of the task responsibilitiesstaff: List of GitHub usernames (in rotation order)email_addresses: List of email addresses (must match staff order and count)
Example:
tasks:
- name: "Code Review Champion"
description: "Ensure timely code reviews and maintain quality standards"
staff:
- developer1
- developer2
- developer3
email_addresses:
- dev1@example.com
- dev2@example.com
- dev3@example.comConfigure notification preferences:
slack_channel: Slack channel to post messages (e.g.,#engineering)timezone: Timezone for date/time display (e.g.,UTC,America/New_York)
To modify staff assignments:
- Edit
.github/rotation-config.yml - Add or remove GitHub usernames from the
stafflist - Add or remove corresponding emails from the
email_addresseslist - Commit and push changes
The rotation will automatically adjust based on the new staff list.
To add a new task:
- Edit
.github/rotation-config.yml - Add a new task entry under the
taskssection - Include all required fields (
name,description,staff,email_addresses) - Commit and push changes
The system uses a simple round-robin rotation based on ISO week numbers:
assigned_index = (week_number - 1) % number_of_staff
For example, with 3 staff members:
- Week 1: Staff member at index 0
- Week 2: Staff member at index 1
- Week 3: Staff member at index 2
- Week 4: Staff member at index 0 (rotation repeats)
The system uses ISO 8601 week date system:
- Weeks run from Monday to Sunday
- Week 1 is the first week with a Thursday in the new year
- Most years have 52 weeks, some have 53
The main workflow runs automatically:
- Schedule: Every Friday at 1:00 PM UTC (
0 13 * * 5) - Purpose: Notify team about current week and upcoming week assignments
To manually trigger the rotation assignment:
- Go to Actions tab
- Select "Rotation Assignment" workflow
- Click "Run workflow"
- Configure options:
- dry_run: Check to run without sending notifications
- week_number: Leave empty for current week, or specify a week number
- Click "Run workflow"
To test assignments for a specific week:
python scripts/rotation-manager.py --dry-run --week 15To generate a calendar view showing task assignments for a specific month:
python scripts/rotation-manager.py --calendar --month 2 --year 2026This will output a Markdown table showing who is assigned to each task for every week that overlaps with the specified month. For example:
# Rotation Calendar: February 2026
| Week | DevOps Duty |
|------|---------|
| Week 5 | fede |
| Week 6 | federico |
| Week 7 | fede |
| Week 8 | federico |The calendar feature is useful for:
- Planning ahead and viewing upcoming rotations
- Checking historical assignments for a specific month
- Generating reports or documentation of task assignments
To validate your configuration without running the rotation:
python scripts/rotation-manager.py --validate-only-
Create a Slack Incoming Webhook:
- Go to https://api.slack.com/messaging/webhooks
- Click "Create your Slack app"
- Select "From scratch"
- Name your app (e.g., "Rotation Bot")
- Choose your workspace
- Click "Incoming Webhooks"
- Activate Incoming Webhooks
- Click "Add New Webhook to Workspace"
- Select the channel (e.g.,
#engineering) - Copy the webhook URL
-
Add the webhook URL to GitHub secrets:
- Go to repository Settings → Secrets and variables → Actions
- Click "New repository secret"
- Name:
SLACK_WEBHOOK_URL - Value: Paste the webhook URL
- Click "Add secret"
For Gmail:
- Enable 2-factor authentication on your Google account
- Generate an App Password:
- Go to Google Account settings
- Security → 2-Step Verification → App passwords
- Generate a password for "Mail"
- Add secrets to GitHub:
SMTP_HOST:smtp.gmail.comSMTP_PORT:587SMTP_USERNAME: Your Gmail addressSMTP_PASSWORD: The app password you generatedSMTP_FROM_EMAIL: Your Gmail address
For other email providers, use their SMTP settings.
Error: "Configuration must have 'tasks' key"
- Solution: Ensure your YAML file has a
tasks:section
Error: "Task X must have same number of email_addresses as staff members"
- Solution: Make sure each task has exactly one email address per staff member
Issue: Workflow fails with "GITHUB_TOKEN" error
- Solution: Ensure the workflow has
issues: writepermission (already configured in the workflow)
Issue: Slack notification fails
- Solution: Verify
SLACK_WEBHOOK_URLis correctly set in repository secrets
Issue: Email notification fails
- Solution:
- Verify all SMTP secrets are set correctly
- Check that SMTP_PORT is a number (e.g.,
587, not"587") - For Gmail, ensure you're using an App Password, not your regular password
Issue: Wrong person assigned to task
- Solution:
- Verify the staff list order in the configuration
- The rotation is based on list order, not alphabetical
- Use the test workflow to verify assignments for specific weeks
Issue: Someone assigned to multiple tasks
- Solution: This is expected behavior. One person can be assigned to multiple tasks in the same week if they appear in multiple task staff lists.
- Python 3.11 or higher
- pip (Python package installer)
- Clone the repository:
git clone https://github.com/gbif/engineering.git
cd engineering- Install dependencies:
pip install -r requirements.txt- Set up environment variables (for testing):
export GITHUB_TOKEN="your_github_token"
export SMTP_HOST="smtp.example.com"
export SMTP_PORT="587"
export SMTP_USERNAME="username"
export SMTP_PASSWORD="password"
export SMTP_FROM_EMAIL="from@example.com"
export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/..."- Run in dry-run mode:
python scripts/rotation-manager.py --dry-runRun configuration validation:
python scripts/rotation-manager.py --validate-onlyTest specific week assignments:
python scripts/rotation-manager.py --dry-run --week 10Validate WS versions by environment policy:
export GITHUB_TOKEN="<token-with-repo-read-access>"
python scripts/ws-services-monitoring-github.py \
--github-owner gbif \
--github-repo engineeringValidate using files from a private GitHub repository:
export GITHUB_TOKEN="<token-with-repo-read-access>"
python scripts/ws-services-monitoring-github.py \
--github-owner gbif \
--github-repo engineering \
--github-ref main \
--config-path-template cli/{env}/config.sh \
--envs dev,test,prod \
--policy-file scripts/policy.json-
Configuration File (
.github/rotation-config.yml)- Defines tasks, staff, and notification settings
- YAML format for easy editing
-
Rotation Manager Script (
scripts/rotation-manager.py)- Core logic for calculating assignments
- Handles GitHub API, email, and Slack integrations
- Validates configuration
-
Main Workflow (
.github/workflows/rotation-assignment.yml)- Scheduled execution every Friday
- Manual trigger support
- Runs rotation manager script
-
Test Workflow (
.github/workflows/test-rotation.yml)- Testing without side effects
- Week-by-week rotation preview
Configuration File
↓
Rotation Manager (calculates assignments)
↓
┌──┴──┐
↓ ↓ ↓
GitHub Email Slack
Issue Notification
To change the schedule, edit .github/workflows/rotation-assignment.yml:
schedule:
# Run every Monday at 9:00 AM UTC
- cron: '0 9 * * 1'Cron format: minute hour day_of_month month day_of_week
The timezone setting in the configuration file is informational only. The system always uses UTC for week calculations to ensure consistency. If you want to display times in a different timezone in notifications, you would need to modify the script.
To contribute to this rotation system:
- Fork the repository
- Create a feature branch
- Make your changes
- Test thoroughly using dry-run mode
- Submit a pull request
This project is part of the GBIF engineering repository. Refer to the main repository license for details.
For issues or questions:
- Check the Troubleshooting section above
- Review the GitHub Actions logs for error messages
- Open an issue in the repository with details about your problem