Branch Protection Setup
This guide explains how to configure branch protection rules to enforce CI/CD checks and prevent direct commits to protected branches.
Overview
Branch protection ensures that:
- All code changes go through pull requests
- CI checks pass before merging
- Code reviews are required
- Direct commits to main/dev are blocked
Setting Up Branch Protection
For main Branch
- Go to Settings → Branches in GitHub repository
- Click Add branch protection rule
- Configure the following:
Branch name pattern
mainProtect matching branches
✅ Require a pull request before merging
- Require approvals:
1 - ✅ Dismiss stale pull request approvals when new commits are pushed
- ✅ Require review from Code Owners (optional, if CODEOWNERS file exists)
✅ Require status checks to pass before merging
- ✅ Require branches to be up to date before merging
- Required status checks:
lint(from CI workflow)build(from CI workflow)test(from CI workflow)validate-firestore-indexes(from CI workflow)all-checks-complete(from CI workflow)
✅ Require conversation resolution before merging
✅ Require signed commits (optional, recommended for production)
✅ Require linear history (optional, prevents merge commits)
✅ Do not allow bypassing the above settings
- Even admins must follow the rules
Rules applied to administrators
- ✅ Include administrators (recommended to prevent accidents)
- Click Create
For dev Branch
Repeat the same steps as above, but with dev as the branch name pattern.
Difference from main:
- May allow more relaxed approval requirements (0-1 reviewers)
- Same CI checks required
- Allows faster iteration while maintaining quality
GitHub Actions Required Secrets
Before branch protection will work with CI/CD, ensure these secrets are set:
Go to Settings → Secrets and variables → Actions
Firebase (Development)
VITE_FIREBASE_API_KEY_DEV
VITE_FIREBASE_AUTH_DOMAIN_DEV
VITE_FIREBASE_PROJECT_ID_DEV
VITE_FIREBASE_STORAGE_BUCKET_DEV
VITE_FIREBASE_MESSAGING_SENDER_ID_DEV
VITE_FIREBASE_APP_ID_DEVFirebase (Production)
VITE_FIREBASE_API_KEY_PROD
VITE_FIREBASE_AUTH_DOMAIN_PROD
VITE_FIREBASE_PROJECT_ID_PROD
VITE_FIREBASE_STORAGE_BUCKET_PROD
VITE_FIREBASE_MESSAGING_SENDER_ID_PROD
VITE_FIREBASE_APP_ID_PRODCloudflare
CLOUDFLARE_API_TOKEN
CLOUDFLARE_ACCOUNT_IDFirebase CLI
FIREBASE_TOKENGet Firebase token by running:
firebase login:ciDiscord
DISCORD_WEBHOOK_COMMITS
DISCORD_WEBHOOK_DEV_DEPLOY
DISCORD_WEBHOOK_PROD_DEPLOYSee DISCORD_WEBHOOK_SETUP.md for detailed setup instructions.
Optional
CODECOV_TOKENGet from codecov.io after linking repository.
Testing Branch Protection
Test Required Status Checks
Create a feature branch:
bashgit checkout -b test/branch-protectionMake a small change (e.g., add a comment to a file)
Commit and push:
bashgit add . git commit -m "test: verify branch protection" git push origin test/branch-protectionOpen a pull request to
mainordevVerify:
- ✅ CI workflow runs automatically
- ✅ All checks must pass before "Merge" button is enabled
- ✅ If any check fails, merge is blocked
Test Direct Commit Block
Try to push directly to main:
bashgit checkout main git commit --allow-empty -m "test: direct commit" git push origin mainExpected result:
remote: error: GH006: Protected branch update failed remote: error: Required status checks are not passingIf push succeeds, branch protection is not configured correctly!
Troubleshooting
Merge button is disabled but all checks passed
Issue: Required status checks are not configured correctly
Fix:
- Go to Settings → Branches → Edit protection rule
- Scroll to "Require status checks to pass before merging"
- Search for and add each required check:
- Type
lintand select it - Type
buildand select it - Type
testand select it - Type
validate-firestore-indexesand select it - Type
all-checks-completeand select it
- Type
- Save changes
Note: Status checks only appear in the list AFTER they've run at least once on a PR!
Status checks never run
Issue: GitHub Actions not triggering
Fix:
- Verify
.github/workflows/ci.ymlexists in the repository - Check workflow file syntax (no YAML errors)
- Ensure GitHub Actions are enabled: Settings → Actions → General → Allow all actions
- Push a new commit to trigger workflows
Can still push directly to main
Issue: Branch protection not enabled or admin bypass allowed
Fix:
- Verify protection rule exists for
mainbranch - Check "Include administrators" is enabled
- Check "Do not allow bypassing" is enabled
Codecov check failing
Issue: Missing CODECOV_TOKEN secret
Fix:
- Set
continue-on-error: truefor codecov step in CI workflow (already configured) - Or, add
CODECOV_TOKENsecret to repository
Environment Protection (Production)
For additional safety on production deployments, enable environment protection:
- Go to Settings → Environments
- Click New environment
- Name:
production - Configure protection rules:
- ✅ Required reviewers: Add team members who can approve production deploys
- ✅ Wait timer: 5 minutes (optional, gives time to cancel)
- Environment secrets: Add production-specific secrets here (optional)
- Save
Now production deployments will:
- Require manual approval from designated reviewers
- Wait 5 minutes before deploying (if configured)
- Only deploy to production environment after approval
Best Practices
Required Reviewers
- Main branch: Require at least 1 approval
- Dev branch: 0-1 approvals (team preference)
- Production environment: Require senior engineer approval
Status Checks
- Always require
lint,build,testto pass - Include
validate-firestore-indexesto catch index issues early - Use
all-checks-completeas final gate
Bypass Settings
- Never allow bypassing for
mainbranch - Include administrators in rules to prevent accidents
- Document any exceptions in team wiki
Monitoring
- Review failed CI checks in GitHub Actions tab
- Set up Slack/Discord notifications for failed merges
- Regularly audit branch protection rules
Updating Branch Protection
To modify rules:
- Go to Settings → Branches
- Find the rule you want to edit
- Click Edit
- Make changes
- Click Save changes
⚠️ Changes take effect immediately
Rollback Procedure
If you need to bypass branch protection in an emergency:
- Go to Settings → Branches
- Find the protection rule
- Click Edit
- Temporarily disable "Do not allow bypassing"
- Make emergency commit
- IMMEDIATELY re-enable protection
⚠️ Document all bypasses in team log
See Also
- CI/CD Guide - Full CI/CD documentation
- Contributing Guide - Contribution workflow
- GitHub Branch Protection Docs