Repository: devopsabcs-engineering/gh-advsec-devsecops
Target Branch: main
Last Updated: 2026-02-04
GitHub branch protection rules must be configured through the web UI or API. Follow these steps:
- Navigate to: Repository → Settings → Branches
- Click Add rule (or edit existing rule for
main) - Apply the following settings:
main
- Required number of approvals before merging:
2 - ✅ Dismiss stale pull request approvals when new commits are pushed
- ✅ Require review from Code Owners
- ✅ Require approval of the most recent reviewable push
- ✅ Require branches to be up to date before merging
- Status checks that are required:
ci_build(from .github/workflows/ci.yml)dependency-review(from .github/workflows/SCA-GitHubAdvancedSecurity-DependencyReview.yml)CodeQL(from .github/workflows/SAST-GitHubAdvancedSecurity-CodeQL.yml)
- Configure after CD pipeline is established
- Enable when team is ready to use GPG/SSH signing
- IMPORTANT: This applies to administrators and prevents emergency bypasses
- Only enable after testing that all required checks work properly
Use GitHub CLI or REST API to configure programmatically:
# Install GitHub CLI if needed: https://cli.github.com/
# Configure branch protection
gh api repos/devopsabcs-engineering/gh-advsec-devsecops/branches/main/protection \
--method PUT \
--field required_status_checks[strict]=true \
--field required_status_checks[contexts][]=ci_build \
--field required_status_checks[contexts][]=dependency-review \
--field required_status_checks[contexts][]=CodeQL \
--field enforce_admins=true \
--field required_pull_request_reviews[dismissal_restrictions][]=null \
--field required_pull_request_reviews[dismiss_stale_reviews]=true \
--field required_pull_request_reviews[require_code_owner_reviews]=true \
--field required_pull_request_reviews[required_approving_review_count]=2 \
--field required_pull_request_reviews[require_last_push_approval]=true \
--field restrictions=null \
--field required_linear_history=true \
--field allow_force_pushes=false \
--field allow_deletions=false \
--field required_conversation_resolution=true# Set variables
$org = "devopsabcs-engineering"
$repo = "gh-advsec-devsecops"
$branch = "main"
$token = $env:GITHUB_TOKEN # Set this environment variable first
# Branch protection configuration
$body = @{
required_status_checks = @{
strict = $true
contexts = @("ci_build", "dependency-review", "CodeQL")
}
enforce_admins = $true
required_pull_request_reviews = @{
dismiss_stale_reviews = $true
require_code_owner_reviews = $true
required_approving_review_count = 2
require_last_push_approval = $true
}
restrictions = $null
required_linear_history = $true
allow_force_pushes = $false
allow_deletions = $false
required_conversation_resolution = $true
} | ConvertTo-Json -Depth 10
# Apply configuration
$headers = @{
"Authorization" = "Bearer $token"
"Accept" = "application/vnd.github.v3+json"
}
Invoke-RestMethod `
-Uri "https://api.github.com/repos/$org/$repo/branches/$branch/protection" `
-Method Put `
-Headers $headers `
-Body $body `
-ContentType "application/json"# View current branch protection settings
gh api repos/devopsabcs-engineering/gh-advsec-devsecops/branches/main/protection | jq- Navigate to Settings → Branches
- Verify
mainbranch shows:- ✅ 2 approvals required
- ✅ Code owners required
- ✅ 3 status checks required
- ✅ Linear history required
- ✅ Administrators not exempt
# Test 1: Try to push directly to main (should fail)
git checkout main
git commit --allow-empty -m "test: direct push"
git push origin main
# Expected: ERROR - protected branch
# Test 2: Create PR without required checks passing (should block merge)
gh pr create --base main --head feature/test --title "Test PR"
# Expected: Merge blocked until checks pass
# Test 3: Create PR with only 1 approval (should block merge)
# Expected: Merge blocked until 2 approvals receivedEnsure these GitHub Actions workflows are properly configured:
- Workflow:
.github/workflows/ci.yml - Job:
ci_build - Triggers:
pull_requestonmain - Status: ✅ Active
- Workflow:
.github/workflows/SCA-GitHubAdvancedSecurity-DependencyReview.yml - Job:
dependency-review - Triggers:
pull_requestonmain - Status: ✅ Active
- Workflow:
.github/workflows/SAST-GitHubAdvancedSecurity-CodeQL.yml - Job:
analyze - Triggers:
pull_requestonmain - Status: ✅ Active (verify it runs on PRs)
Solution:
- Ensure workflows trigger on
pull_requestevents targetingmain - Create a test PR to trigger workflows
- Wait for workflows to run at least once
- Status checks will then appear in branch protection settings
Solution:
- First verify all required status checks pass on a test PR
- Ensure CODEOWNERS file is valid
- Test with bypass enabled first
- Enable bypass protection after confirming everything works
Solution:
- Verify CODEOWNERS file is at
.github/CODEOWNERS - Ensure syntax is correct (no markdown headers in CODEOWNERS)
- Test by creating PR that modifies a protected path
- Verify appropriate owners are auto-requested as reviewers
If enabling all protections at once is too disruptive, use this phased approach:
- ✅ Require pull requests
- ✅ Require 1 approval
- ✅ Require status checks (but allow bypass for admins)
- ✅ Increase to 2 approvals
- ✅ Enable CODEOWNERS requirement
- ✅ Enable stale review dismissal
- ✅ Enable linear history requirement
- ✅ Enable conversation resolution requirement
- ✅ Disable admin bypass
⚠️ Consider enabling signed commits (requires team setup)⚠️ Add deployment protection rules (when CD is ready)
In case branch protection must be temporarily disabled:
- Document the reason in security log
- Get approval from security team (@CalinL)
- Disable protection temporarily
- Make emergency change
- Re-enable protection immediately
- Create follow-up PR with proper review process
- Document in incident log
# Temporarily disable enforcement for admins only
gh api repos/devopsabcs-engineering/gh-advsec-devsecops/branches/main/protection \
--method PUT \
--field enforce_admins=false
# Make emergency change
# ...
# Re-enable enforcement
gh api repos/devopsabcs-engineering/gh-advsec-devsecops/branches/main/protection \
--method PUT \
--field enforce_admins=true- GitHub Branch Protection Rules
- Required Status Checks
- CODEOWNERS Documentation
- Supply Chain Security Report
- Remediation Guide
Configuration Owner: @CalinL
Last Verified: 2026-02-04
Next Review: 2026-03-04