This comprehensive guide documents the GitHub Actions automation that powers the Open Elements repository. These workflows automate routine tasks, enforce quality standards, manage contributor workflows, and maintain issue/PR lifecycle consistency.
Target Audience: Maintainers, repository administrators, developers debugging automation behavior
Key Concepts: GitHub Actions workflows, environment variables, repository rules, automation triggers
The automation system is designed according to these principles:
- All automation runs through GitHub Actions (not external CI/CD platforms)
- Workflows are version-controlled in
.github/workflows/ - Configuration is transparent and auditable
- No external dependencies or specialized tools required
- Uses only
GITHUB_TOKEN(automatically provided by GitHub) - Requires repository-level environment variables (no secrets needed)
- No third-party API integrations unless absolutely necessary
- No CODEOWNERS file dependency
- Branch protection rules aren't used for requirement enforcement
- Automation works through labeling, comments, and PR status checks
- Maintainers have clear override capability
- Contributor experience remains flexible
Contributors can interact with issues through special comment commands. These commands are processed by automated workflows:
Purpose: Assign the issue to yourself
Syntax:
/assign
Behavior:
- Assigns the issue to the comment author
- Subject to
ASSIGN_ALLOWLISTrules (if configured) - Updates issue status label to
status: in-progress - Triggers first-timer guidance if applicable
Example:
This looks interesting! /assign
Result: You are now assigned, issue shows "assigned to @yourname"
Purpose: Mark that you are actively working on the issue
Syntax:
/working
Behavior:
- Updates issue to show
status: in-progress - Persists a timestamped marker comment
- Prevents stale assignment reminders (resets timer)
- Signals to other contributors that work is active
When to use:
- After being assigned but before starting work
- When you've been idle and are resuming work
- To communicate continuous progress to maintainers
Example:
Starting implementation now. /working
Purpose: Remove yourself from the issue
Syntax:
/unassign
Behavior:
- Removes your assignment
- Updates status to
status: triage(ready for new assignment) - Frees the issue for other contributors
- Clears the "active work" marker
When to use:
- If you cannot complete the work
- If you need to pause for an extended period
- When passing work to another team member
Example:
Hitting a blocker here. /unassign
(and create a follow-up issue for the blocker)
The system automatically sends reminders to assignees when certain conditions are met, helping keep issues moving forward.
Trigger: Runs daily via scheduled workflow
Conditions for sending a reminder (ALL must be true):
- Issue is assigned to someone
- Issue has been open longer than
REMIND_AFTER_DAYS(typically 7 days) - No
/workingcomment in the lastWORKING_GRACE_DAYS(typically 3 days) - Issue doesn't have a "blocked" label
- Issue isn't already in recent reminder spam window
- No open PR is linked to the issue
Reminder content: Polite nudge asking for status update
What happens after reminder:
- If you respond with
/working→ Reminder timer resets - If PR is linked → Reminder stops
- If issue is closed → Reminder stops
- If labeled as blocked → Reminder stops
When a new contributor (or someone working on their first issue) is assigned an issue, they automatically receive helpful guidance.
Trigger: When issue is assigned to first-time contributor
Guidance source (in priority order):
.github/FIRST_TIMER_GUIDE.md- if file exists in repo- Embedded default guidance in workflow YAML
Content typically includes:
- Welcome message
- Link to contributor documentation
- Link to relevant guides
- How to ask questions
- Expected timeline for first contribution
Example guidance comment:
Welcome to your first contribution! Here's what you need to know:
1. Start with: docs/README.md → "Getting Started"
2. Next, read: docs/01-repo-overview.md
3. For implementation help: see docs/03-adding-pages.md
4. Before submitting PR: review docs/05-first-contribution-checklist.md
Questions? Ask here in the issue - maintainers are happy to help!
When a PR is created, the system automatically:
-
Applies labels based on which files changed
label: content- if markdown files modifiedlabel: frontend- if React/TypeScript components changedlabel: i18n- if translation files changedlabel: automation- if GitHub workflows changed
-
Auto-assigns the PR to its author
- Helps track ownership
- Makes author's PRs easily discoverable
Implementation: Reads changed files from PR diff, applies configured labels
The system automatically requests reviews from appropriate team members based on code ownership and expertise.
Configuration: .github/reviewers.json
Example reviewers.json structure:
{
"defaultReviewers": ["@maintainer1", "@maintainer2"],
"pathReviewers": {
"src/i18n/*": ["@i18n-specialist"],
"src/app/[locale]/*": ["@frontend-lead"],
"content/*": ["@content-editor"],
".github/workflows/*": ["@devops-lead"]
}
}Assignment logic:
- Collect default reviewers (apply to all PRs)
- Identify changed file paths
- Match paths against
pathReviewersconfiguration - Combine both sets (default + path-specific)
- Remove PR author from reviewer list (don't self-request review)
- Avoid duplicate requests (don't re-request already-requested reviewers)
- Send GitHub pull request review request
Example scenario:
PR changes:
- src/app/[locale]/about/page.tsx
- content/about/index.md
- docs/README.md
Result:
- Default reviewers: @maintainer1, @maintainer2
- Path-based: @frontend-lead (matched src/app), @content-editor (matched content)
- Final list: @maintainer1, @maintainer2, @frontend-lead, @content-editor
The system prevents contributors from removing required reviewers, ensuring quality gates remain in place.
Maintainer privileges:
- Defined via
MAINTAINER_ALLOWLISTenvironment variable - Maintainers can remove/modify reviewers if needed
- Maintainers can approve their own code
Non-maintainer restrictions:
- Cannot remove already-requested reviewers
- Cannot modify reviewer configuration files
- If they try to modify
.github/reviewers.json, workflow fails with clear error
Purpose: Ensures quality standards aren't bypassed accidentally
The system maintains consistent status labels on both issues and PRs, providing visibility into work progress.
Status labels on issues indicate their current state in the workflow:
| Label | Meaning | When Applied | Cleared When |
|---|---|---|---|
status: triage |
Issue is new, needs initial review | Automatically on creation | Assigned or labeled blocked |
status: in-progress |
Someone is actively working | /assign command or PR linked |
Issue closed |
status: blocked |
Cannot proceed (external blocker) | Manual label by maintainer | Blockage removed |
status: blocked-reviewer |
Waiting for reviewer feedback | Auto-applied if PR in review stage | Reviewer provides feedback |
status: closed |
Issue resolved | Issue closed | N/A (terminal state) |
Status labels on PRs indicate their current stage:
| Label | Meaning | When Applied | Advanced To |
|---|---|---|---|
status: draft |
Early work, not ready for review | Auto on PR creation if marked draft | Converted to ready for review |
status: in-review |
Ready for review, awaiting feedback | Auto when review requested | Changes requested or approved |
status: changes-requested |
Reviewer wants modifications | Auto when review shows changes-requested | Resolved and re-reviewed |
status: approved |
Reviewer approved changes | Auto on approval | Merged (if all approvals met) |
status: merged |
PR successfully merged | Auto on merge | N/A (terminal state) |
status: closed |
PR closed without merging | Auto on close | N/A (terminal state) |
How it works:
- Workflow monitors all issue and PR events
- Evaluates current state
- Compares against expected status labels
- Adds/removes labels as needed
- Maintains single source of truth
Example scenario:
Timeline:
1. Issue created → Gets `status: triage` label
2. Issue assigned → Label changes to `status: in-progress`
3. PR created and linked → Keeps `status: in-progress`
4. PR review requested → PR gets `status: in-review`
5. Reviewer requests changes → PR gets `status: changes-requested`
6. PR updated → Label changes back to `status: in-review`
7. Review approved → PR gets `status: approved`
8. PR merged → PR gets `status: merged`, issue gets `status: closed`
| File | Purpose | Modifiable By | When to Edit |
|---|---|---|---|
.github/workflows/issue-commands.yml |
Handles /assign, /working, /unassign commands |
Maintainers | Adding new commands or changing command behavior |
.github/workflows/issue-reminders.yml |
Sends daily reminders to stale assignees | Maintainers | Adjusting reminder timing or conditions |
.github/workflows/first-timer-guidance.yml |
Sends welcome message to new contributors | Maintainers | Updating onboarding message or conditions |
.github/workflows/pr-automation.yml |
Auto-labels and assigns reviewers to PRs | Maintainers | Adding new labels/paths or changing reviewer logic |
.github/workflows/status-labels.yml |
Maintains status labels on issues/PRs | Maintainers | Changing status conditions or labels |
.github/reviewers.json |
Maps file paths to responsible reviewers | Maintainers | Adding expertise areas or reorganizing teams |
Repository variables control automation behavior:
Key Variables:
| Variable | Purpose | Example Value | Usage |
|---|---|---|---|
MAINTAINER_ALLOWLIST |
Users with override permissions | maintainer1,maintainer2,maintainer3 |
Determines who can adjust reviewer requirements |
WORKING_LABEL |
Label applied when work is active | status: in-progress |
Applied by /working command |
REMIND_AFTER_DAYS |
Days before stale reminder sent | 7 |
Issue must be open this long before reminder |
WORKING_GRACE_DAYS |
Days since /working before reminder |
3 |
If no /working in this many days, send reminder |
SKIP_REMINDER_LABELS |
Labels that prevent reminders | blocked,blocked-blocker,no-reminder |
Any issue with these labels skips reminders |
ASSIGN_ALLOWLIST |
Who can use /assign command |
(Optional) Restrict to team | Controls who can self-assign issues |
DEFAULT_MAINTAINER |
Fallback reviewer if none matched | @default-maintainer |
Ensures all PRs get reviewed |
Viewing Variables:
GitHub → Repo Settings → Environments → Production/Development
Modifying Variables: Only repository admins can change these settings.
Issue: /assign command doesn't assign issue
Possible Causes:
- User isn't in
ASSIGN_ALLOWLIST(if configured) - Issue already assigned to someone else
- Workflow is disabled or has errors
Fix:
- Check if
ASSIGN_ALLOWLISTrestricts access - Unassign first if needed
- Try command again
- If persists, check
.github/workflows/issue-commands.ymlfor errors
Issue: Expected reminder didn't arrive after 7 days
Possible Causes:
- Someone commented
/workingrecently (resets timer) - Issue has
status: blockedor similar label - PR is linked to issue
- Issue is closed already
Check:
- Scroll through issue comments for recent
/working - Check issue labels
- Look for linked PRs in issue sidebar
Issue: Expected reviewer not added to PR
Possible Causes:
- Reviewer not in
pathReviewersordefaultReviewers - Reviewer is PR author (author excluded)
- Reviewer already requested (duplicate prevention)
- File path doesn't match any rules
Fix:
- Check
.github/reviewers.jsonconfiguration - Verify file paths match expected patterns
- Manually request if needed
Issue: PR has wrong status label
Possible Causes:
- Workflow didn't evaluate state correctly
- Label was manually removed
- Timing issue (workflow hadn't run yet)
** Fix**:
- Wait 1-2 minutes, refresh page
- Check workflow run history in Actions tab
- Manually correct label if needed
If you need to modify workflow behavior:
- Document the reason: Why is this change needed?
- Plan the impact: What PRs/issues will be affected?
- Test if possible: GitHub supports
workflow_dispatchfor manual testing - Notify team: Let maintainers know about planned changes
-
Update
.github/workflows/*.ymlfile(s):- Modify conditions, labels, or behavior
- Test logic carefully (YAML syntax is strict)
-
Update
.github/reviewers.json(if applicable):- Add/modify path-to-reviewer mappings
- Ensure JSON is valid
-
Update this documentation:
- In the same PR, update this file (07-github-automation.md)
- Explain what changed and why
- Give examples if behavior is user-visible
-
Include in same PR:
- Workflow changes
- Configuration changes
- Documentation updates
- All together in one PR
Your PR description must include:
## Automation Change
### What's changing
[Description of workflow/configuration changes]
### Why
[Business reason or problem being solved]
### Impact on contributors
[How will this affect day-to-day contributor experience]
### Testing
[How was this tested/validated]
### Rollback plan (if needed)
[How to revert if issues arise]From a contributor's perspective, here's the automated journey:
Day 1:
1. Open issue #123 about typo fix
2. Read instructions (automated guidance as first-timer)
3. Comment "/assign" → Issue assigned, becomes status: in-progress
4. Fork repo, fix typo, submit PR
Day 2:
* GitHub automation automatically:
- Labels PR as `label: content`
- Assigns PR to contributor (you)
- Requests review from @content-editor and @maintainer1
- Sets PR status to `status: in-review`
Day 3:
* Reviewer @content-editor approves PR
* Status changes to `status: approved`
* Maintainer merges PR
* Issue #123 closes automatically
* Status changes to `status: merged`
Result: PR is merged, issue closed, contributor gets credit!
From a maintainer's perspective, here's what they see:
Daily:
* Run check: Are there stale issues?
* Workflow sends reminder comments to assignees
(after 7 days with no /working comment)
During Code Review:
* Automation already assigned reviewers
* Maintainer focuses on code quality (automation handles logistics)
* Can override reviewer requirements if needed (in MAINTAINER_ALLOWLIST)
On Merge:
* Automation updates all related labels
* Issue closes automatically
* PR status set to merged
* Everything synced with no manual steps
- Keep configuration DRY: Don't repeat logic in multiple workflows
- Document changes: Always update this guide when modifying automation
- Monitor workflow runs: Check Actions tab for failures
- Respond to issues: Automation enables tracking, but humans drive resolution
- Test changes: Use
workflow_dispatchwhen available before deploying - Keep GitHub Actions up to date: Periodically check for deprecated features