Skip to content

Branch Protection Setup

This document outlines the branch protection strategy for the OpenPets repository.

Current Limitation

Branch protection rules require GitHub Pro for private repositories. This repo currently uses the free tier.

Options

Option 1: Upgrade to GitHub Pro

Enables full branch protection via the setup script below.

Option 2: Use GitHub Actions (Current Implementation)

We use CI/CD workflows to enforce similar protections. See .github/workflows/pr-checks.yml.

Option 3: Make Repository Public

Enables branch protection features on the free tier.

For main branch:

Pull Request Requirements

  • Require pull request reviews: At least 1 approval
  • Dismiss stale reviews: When new commits are pushed
  • Require review from code owners: If CODEOWNERS file exists
  • Require approval of most recent push: Ensures latest code is reviewed

Status Checks

  • Require status checks to pass: Yes
  • Require branches to be up to date: Yes
  • Required checks:
    • validate - Pets configuration validation
    • build-test - Build and test all pets
    • lint - Code linting
    • type-check - TypeScript type checking

Additional Rules

  • Require conversation resolution: All PR comments must be resolved
  • Require signed commits: Optional but recommended for security
  • Require linear history: Prevents merge commits (use squash or rebase)
  • Include administrators: Admins must follow these rules too
  • Restrict pushes: Only allow via pull requests
  • Allow force pushes: Never
  • Allow deletions: Never

Setup Script

When GitHub Pro is available or repository is public, run:

bash
./scripts/setup-branch-protection.sh

Or manually configure using GitHub CLI:

bash
gh api repos/$(gh repo view --json nameWithOwner -q .nameWithOwner)/branches/main/protection \
  --method PUT \
  --field required_status_checks[strict]=true \
  --field required_status_checks[contexts][]=validate \
  --field required_status_checks[contexts][]=build-test \
  --field enforce_admins=true \
  --field required_pull_request_reviews[dismiss_stale_reviews]=true \
  --field required_pull_request_reviews[require_code_owner_reviews]=false \
  --field required_pull_request_reviews[required_approving_review_count]=1 \
  --field required_pull_request_reviews[require_last_push_approval]=true \
  --field required_conversation_resolution=true \
  --field required_linear_history=true \
  --field allow_force_pushes=false \
  --field allow_deletions=false \
  --field restrictions=null

Current Enforcement via CI/CD

Until branch protection is available, we enforce quality through:

  1. PR Checks Workflow - Runs validation, tests, linting
  2. Auto-publish Workflow - Only runs on main after merge
  3. Manual Review Process - Team members review before merging

Verification

Check current branch protection status:

bash
gh api repos/$(gh repo view --json nameWithOwner -q .nameWithOwner)/branches/main/protection

Or view in GitHub UI: Settings → Branches → Branch protection rules

Additional Security Measures

CODEOWNERS File

Create .github/CODEOWNERS to require reviews from specific team members:

# Default owners for everything
* @anduimagui

# Specific pet owners
/pets/github/ @anduimagui
/pets/stripe/ @anduimagui

# Core infrastructure
/src/ @anduimagui
/.github/ @anduimagui
/scripts/ @anduimagui

Required Workflows

Configure in Settings → Actions → General → Required workflows when available.

Deployment Branch Rules

Configure in Settings → Environments to restrict deployments:

  • Only allow deployments from main branch
  • Require reviewers for production deployments
  • Add deployment protection rules

Best Practices

  1. Never commit directly to main - Always use pull requests
  2. Keep branches up to date - Rebase or merge main before PR
  3. Write descriptive PR descriptions - Explain what and why
  4. Request reviews - Don't merge your own PRs
  5. Resolve all comments - Address feedback before merging
  6. Run tests locally - Don't rely solely on CI
  7. Use conventional commits - Follow commit message format
  8. Squash merge - Keep main branch history clean

Local Git Hooks

Consider adding pre-commit hooks to enforce quality locally:

bash
# Install pre-commit framework
bun add -D husky lint-staged

# Setup pre-commit hook
npx husky install
npx husky add .husky/pre-commit "npx lint-staged"

Add to package.json:

json
{
  "lint-staged": {
    "*.ts": ["eslint --fix", "prettier --write"],
    "*.md": ["prettier --write"],
    "pets/*/package.json": ["pets validate"]
  }
}

Troubleshooting

"Branch protection failed" error

  • Ensure you're on GitHub Pro or repository is public
  • Check you have admin access to the repository
  • Verify required status checks exist in Actions

Required checks not appearing

  • Ensure workflows have run at least once on main
  • Check workflow names match exactly in branch protection settings
  • Verify workflows are enabled in Actions settings

References