Branch Protection & CI Gating¶
This document describes the strict CI gating strategy implemented for the solve-it-mcp repository to ensure code quality and prevent broken releases for forensic software.
๐ก๏ธ Overview¶
Goal: Prevent merging code to main and publishing Docker images unless all quality, security, and build validation checks pass.
Strategy: Multi-layered protection using: 1. GitHub Branch Protection Rules (required checks) 2. Separate focused workflows (parallel execution for speed) 3. Docker-only builds on main branch (no PR noise) 4. Forensic integrity features (SBOM, image signing, provenance)
๐ Branch Protection Rules¶
Configuring Branch Protection for main¶
Navigate to: Settings โ Branches โ Branch protection rules โ Add rule
Required Settings:¶
Branch name pattern: main
โ Require a pull request before merging
โ Require approvals: 0 (or 1+ for team review)
โ Dismiss stale pull request approvals when new commits are pushed
โ Require review from Code Owners: โ (optional)
โ Require status checks to pass before merging
โ Require branches to be up to date before merging
Required status checks (add these exact names):
- CI Summary (from ci.yml)
- Security Summary (from security.yml)
- PR Validation Summary (from docker-pr-validation.yml)
Note: These are the summary jobs that depend on all other checks passing.
โ Require conversation resolution before merging
โ Require linear history (recommended for forensic audit trail)
โ Do not allow bypassing the above settings
โ Allow specific actors to bypass (optional - for emergencies only)
โ Restrict who can push to matching branches (optional)
โ Allow force pushes: โ DISABLED (protects git history)
โ Allow deletions: โ DISABLED (prevents branch deletion)
๐ Workflow Architecture¶
New Modular Workflow Structure¶
The repository now uses 4 separate focused workflows instead of one monolithic CI:
1. ci.yml - Code Quality & Tests (~5 min)¶
- Ruff linting & formatting
- MyPy type checking
- Pytest with coverage (Python 3.11 & 3.12)
- YAML validation
- Runs on: PR + Main push
2. security.yml - Vulnerability Scanning (~3 min)¶
- Bandit (Python security)
- pip-audit & Safety (dependency vulnerabilities)
- Hadolint (Dockerfile security)
- TruffleHog (secret scanning)
- Runs on: PR + Main push + Daily schedule
3. docker-pr-validation.yml - Build Validation (~12 min)¶
- Single-arch Docker build (linux/amd64)
- Health check tests (/healthz, /readyz)
- Multi-arch build verification
- Trivy security scan
- Runs on: PR only
- Does NOT publish images
4. docker-publish.yml - Production Build (~20 min)¶
- Multi-arch builds (amd64, arm64, arm/v7)
- SBOM generation (SPDX, CycloneDX)
- Image signing with Cosign (keyless)
- Provenance attestation
- Push to Docker Hub
- Full Trivy scans
- Runs on: Main push + Git tags only
Workflow Execution Flow¶
graph TD
A[PR Created/Updated] --> B[ci.yml]
A --> C[security.yml]
A --> D[docker-pr-validation.yml]
B --> E{All Jobs Pass?}
C --> E
D --> E
E -->|Yes| F[PR Can Be Merged]
E -->|No| G[PR Blocked]
F --> H[Merge to Main]
H --> I[ci.yml on Main]
H --> J[security.yml on Main]
I --> K{Both Pass?}
J --> K
K -->|Yes| L[docker-publish.yml]
K -->|No| M[No Docker Build]
L --> N[Build & Publish Images]
N --> O[Sign Images + Attach SBOM] Benefits of This Architecture¶
For Pull Requests: - โ Fast parallel feedback (~12 min total) - โ Clear separation of concerns - โ Build validation without publishing - โ Security checks before merge
For Main Branch: - โ Production builds only after all checks pass - โ No wasted Docker builds on PRs - โ Complete forensic audit trail - โ SBOM and signatures for compliance
For Forensic Software: - โ Every image traceable to source commit - โ SBOM lists all dependencies - โ Cryptographic signatures verify integrity - โ Provenance attestation proves build source
๐ Workflow Gating Strategy¶
How CI Gating Works¶
Branch Protection enforces that all required status checks pass before allowing merge:
- CI Summary - Must pass (from ci.yml)
- Security Summary - Must pass (from security.yml)
- PR Validation Summary - Must pass (from docker-pr-validation.yml)
Each summary job only succeeds if all its dependent jobs pass.
Docker Publish Gating¶
The docker-publish.yml workflow: - โ
Only triggered by main branch push or git tags - โ
Never runs on PRs (no wasted builds) - โ
Relies on GitHub branch protection (CI must pass before merge allowed) - โ
Includes verify-ci job as safety check
๐ฏ Required Checks Breakdown¶
Workflow: ci.yml (Code Quality & Tests)¶
Must Pass Before Merge:
1. Code Quality Job¶
- Checks: Ruff linting, Ruff formatting, MyPy type checking
- Duration: ~2 minutes
- Failure: Blocks merge
2. Unit Tests (Python 3.11 & 3.12)¶
- Jobs: Matrix across Python versions
- Checks: pytest with coverage, Codecov upload
- Duration: ~3 minutes per version
- Failure: Blocks merge
3. YAML Linting¶
- Checks: yamllint on workflow files
- Duration: ~1 minute
- Failure: Blocks merge
4. CI Summary¶
- Checks: Aggregates all ci.yml job results
- Duration: ~10 seconds
- Failure: Blocks merge if any ci.yml job failed
Workflow: security.yml (Vulnerability Scanning)¶
Must Pass Before Merge:
1. Code Security (Bandit)¶
- Checks: Python code security issues
- Duration: ~1 minute
- Failure: Blocks merge
2. Dependency Security¶
- Checks: pip-audit & Safety for vulnerable dependencies
- Duration: ~1 minute
- Failure: Blocks merge
3. Dockerfile Security (Hadolint)¶
- Checks: Dockerfile best practices and security
- Duration: ~1 minute
- Failure: Blocks merge
4. Secret Scanning¶
- Checks: TruffleHog for exposed secrets
- Duration: ~1 minute
- Failure: Warning (doesn't block, but should be reviewed)
5. Security Summary¶
- Checks: Aggregates all security.yml job results
- Duration: ~10 seconds
- Failure: Blocks merge if any security job failed
Workflow: docker-pr-validation.yml (Build Validation)¶
Must Pass Before Merge:
1. Build & Test (AMD64)¶
- Checks: Docker build, health checks (/healthz, /readyz), multi-arch capability
- Duration: ~8 minutes
- Failure: Blocks merge
2. Trivy Security Scan¶
- Checks: Container image vulnerabilities
- Duration: ~3 minutes
- Failure: Blocks merge if CRITICAL vulnerabilities found
3. PR Validation Summary¶
- Checks: Aggregates all docker-pr-validation.yml job results
- Duration: ~10 seconds
- Failure: Blocks merge if any validation job failed
โ๏ธ How It Works¶
Scenario 1: Normal PR Flow¶
1. Developer creates PR
โ
2. Three workflows run in PARALLEL:
โโ ci.yml (~5 min)
โ โโ Code Quality โ
โ โโ Tests (3.11) โ
โ โโ Tests (3.12) โ
โ โโ YAML Lint โ
โ
โโ security.yml (~3 min)
โ โโ Bandit โ
โ โโ pip-audit โ
โ โโ Hadolint โ
โ โโ Secret Scan โ
โ
โโ docker-pr-validation.yml (~12 min)
โโ Build & Test โ
โโ Trivy Scan โ
โ
3. Total time: ~12 minutes (parallel execution)
โ
4. All 3 summary jobs pass:
โโ CI Summary โ
โโ Security Summary โ
โโ PR Validation Summary โ
โ
5. "Merge" button ENABLED
โ
6. Maintainer merges PR
โ
7. ci.yml + security.yml run on main
โ
8. Both pass โ docker-publish.yml triggered
โโ verify-ci job โ
โโ Multi-arch builds (amd64, arm64, arm/v7)
โโ SBOM generation
โโ Image signing
โโ Full Trivy scans
โโ Push to Docker Hub
Scenario 2: Tests Fail on PR¶
1. Developer creates PR
โ
2. Workflows run
โโ ci.yml
โ โโ Code Quality โ
โ โโ Tests (3.11) โ FAILED
โโ security.yml โ
โโ docker-pr-validation.yml โ
โ
3. CI Summary โ FAILED
โ
4. "Merge" button DISABLED
โ
5. Developer fixes tests, pushes commit
โ
6. Workflows run again
โโ All checks โ
โ
7. "Merge" button ENABLED
Scenario 3: Security Vulnerability Found¶
1. Developer creates PR
โ
2. security.yml runs
โโ Bandit โ
โโ pip-audit โ
โโ Hadolint โ CRITICAL issue found
โโ Secret Scan โ
โ
3. Security Summary โ FAILED
โ
4. "Merge" button DISABLED
โ
5. Developer fixes Dockerfile, updates PR
โ
6. security.yml runs again
โโ All checks โ
โ
7. "Merge" button ENABLED
Scenario 4: Release Tag Created¶
1. Maintainer creates tag: v0.2025-10-0.1.0
โ
2. Tag pushed to GitHub
โ
3. docker-publish.yml triggered by tag
โโ verify-ci job โ
(checks main branch CI)
โโ Multi-arch builds
โโ SBOM generation
โโ Image signing
โโ Version tags: v0.2025-10-0.1.0, latest
โโ Full Trivy scans
โโ Push to Docker Hub
Scenario 5: Monthly SOLVE-IT Update¶
1. Monthly cron trigger (1st of month, 3 AM UTC)
โ
2. docker-monthly.yml runs
โโ Check SOLVE-IT latest release
โโ Compare with published version
โโ New version found? v0.2025-11
โ
3. Calls docker-publish.yml workflow
โโ Create new release tag
โโ Build with new SOLVE-IT data
โโ Full security scans
โโ Publish
๐จ Bypassing Protection (Emergency Only)¶
When to Bypass:¶
- โ Critical security hotfix needed immediately
- โ Known flaky test, but code is verified manually
- โ CI infrastructure issue (GitHub Actions outage)
How to Bypass:¶
Method 1: Workflow Dispatch (Recommended)¶
# Go to Actions โ Docker Build and Publish โ Run workflow
# Select branch: main
# Run manually (skips verify-ci for workflow_dispatch events)
Method 2: Temporarily Disable Branch Protection¶
# Settings โ Branches โ Edit rule for main
# Temporarily uncheck "Require status checks to pass"
# Merge PR
# RE-ENABLE protection immediately!
Method 3: Admin Override (If enabled)¶
# Only if "Allow specific actors to bypass" is configured
# Admin can merge despite failing checks
# Should be logged and reviewed
โ ๏ธ IMPORTANT: Document all bypasses in a GitHub Issue with: - Reason for bypass - Timestamp - Who authorized it - Follow-up action to fix root cause
๐ Monitoring & Alerts¶
Check Workflow Status¶
GitHub Actions Page: - https://github.com/3soos3/solve-it-mcp/actions
Workflow Badges (add to README):
[](https://github.com/3soos3/solve-it-mcp/actions)
[](https://github.com/3soos3/solve-it-mcp/actions)
Email Notifications¶
Configure in: Settings โ Notifications โ Actions - โ Send notifications for failed workflows - โ Include workflow logs
๐งช Testing the Setup¶
Test 1: Verify Branch Protection¶
# Try to push directly to main (should fail)
git checkout main
git commit --allow-empty -m "test: direct push"
git push origin main
# Expected: remote rejected (branch protected)
Test 2: Verify CI Gating¶
# Create PR with failing test
# 1. Add a failing test to tests/
# 2. Create PR
# 3. Verify "Merge" button is disabled
# 4. Check "Required" status checks section
Test 3: Verify Docker Workflow Gating¶
# Check workflow file
cat .github/workflows/docker-publish.yml | grep -A5 "verify-ci"
# Expected: Job exists and checks CI status
๐ Step-by-Step Setup Instructions¶
1. Enable Branch Protection¶
1. Go to: https://github.com/3soos3/solve-it-mcp/settings/branches
2. Click "Add rule" or "Edit" for existing main rule
3. Branch name pattern: main
4. Enable these checkboxes:
โ Require a pull request before merging
โ Require status checks to pass before merging
โ Require branches to be up to date before merging
5. In "Status checks that are required", search and add:
- CI Summary
- Security Summary
- PR Validation Summary
6. Click "Create" or "Save changes"
2. Verify Workflow Files¶
# Ensure workflows are in place
ls -la .github/workflows/
# Should show:
# - ci.yml (Code Quality & Tests)
# - security.yml (Vulnerability Scanning)
# - docker-pr-validation.yml (PR Build Validation)
# - docker-publish.yml (Production Build & Publish)
# - docker-monthly.yml (Smart Monthly Rebuilds)
3. Test the Setup¶
# Create a test PR
git checkout -b test/branch-protection
echo "# Test" >> TEST.md
git add TEST.md
git commit -m "test: branch protection"
git push -u origin test/branch-protection
# Create PR on GitHub
# Verify CI runs automatically
# Verify merge button state
4. Monitor First Real PR¶
# After setup, monitor first real PR:
# 1. Check all CI jobs run
# 2. Check status checks appear in PR
# 3. Verify merge button behavior
# 4. Check Docker workflow triggers after merge
๐ง Troubleshooting¶
Issue: "Merge" button enabled despite failing CI¶
Cause: Status checks not configured correctly in branch protection
Fix: 1. Go to branch protection settings 2. Ensure "Require status checks to pass" is checked 3. Verify exact job names match what appears in Actions tab 4. Job names are case-sensitive!
Issue: Docker workflow runs even though CI failed¶
Cause: verify-ci job not working correctly
Fix:
# Check workflow logs
# Look for "Verify CI Status" job
# Check if it's being skipped incorrectly
# Verify the if conditions in the job
Issue: CI checks not appearing in PR¶
Cause: CI workflow not triggering on PRs
Fix:
Issue: Status check names don't match¶
Cause: Job names in workflow don't match configured status checks
Fix:
# Job name in workflow file MUST match status check name
# Example:
# Workflow: name: "Code Quality"
# Branch protection: Add status check "Code Quality" (exact match)
๐ Additional Resources¶
๐ Forensic Software Features¶
SBOM (Software Bill of Materials)¶
Every published Docker image includes an SBOM for complete dependency transparency:
Formats Generated: - SPDX JSON - Industry standard, ISO/IEC 5962:2021 compliant - CycloneDX JSON - OWASP standard for software supply chain - Syft JSON - Anchore's detailed format
How to Access:
# Download SBOM from GitHub artifacts
gh run download <run-id> --name sbom-<commit-sha>
# View SBOM attached to image (requires cosign)
cosign download sbom ghcr.io/3soos3/solve-it-mcp:latest
# View SBOM in container
docker run --rm ghcr.io/3soos3/solve-it-mcp:latest cat /sbom/sbom.spdx.json
Use Cases: - Compliance audits (GDPR, HIPAA, PCI-DSS) - Vulnerability tracking across fleet - License compliance verification - Evidence chain of custody
Image Signing with Cosign¶
All images are cryptographically signed using Sigstore Cosign (keyless signing):
Verification:
# Verify image signature
cosign verify ghcr.io/3soos3/solve-it-mcp:latest \
--certificate-identity-regexp=github \
--certificate-oidc-issuer=https://token.actions.githubusercontent.com
# Expected output:
# โ Verified signature
# โ Certificate identity matches
# โ OIDC issuer matches
Provenance:
# View build provenance
cosign download attestation ghcr.io/3soos3/solve-it-mcp:latest | jq
# Shows:
# - Source repository
# - Commit SHA
# - Build workflow
# - Build timestamp
# - Builder identity
Forensic Benefits: - Integrity: Prove image hasn't been tampered with - Authenticity: Verify image source and builder - Non-repudiation: Signatures are tied to GitHub identity - Transparency: Public Sigstore transparency log (Rekor)
Audit Trail¶
Complete traceable history for every Docker image:
Image Tags Include: - sha-<commit> - Exact source commit - v<version> - Release version - latest - Current stable
Metadata in Image Labels:
docker inspect ghcr.io/3soos3/solve-it-mcp:latest | jq '.[0].Config.Labels'
# Shows:
# - org.opencontainers.image.created
# - org.opencontainers.image.revision (git commit)
# - org.opencontainers.image.source (repo URL)
# - org.opencontainers.image.version
CI/CD Artifacts: - Workflow logs (retained 90 days) - Security scan results (SARIF format) - Test coverage reports - SBOM files
GitHub Audit: - All commits signed/verified - PR reviews required - Branch protection enforced - Workflow runs logged
โ Checklist for New Repositories¶
- Enable branch protection for
main - Configure required status checks (CI Summary, Security Summary, PR Validation Summary)
- Add all 4 workflows (ci, security, docker-pr-validation, docker-publish)
- Set up Docker Hub secrets (DOCKERHUB_USERNAME, DOCKERHUB_TOKEN)
- Test with a failing PR (verify blocked)
- Test with a passing PR (verify can merge)
- Verify Docker workflow only runs on main
- Verify SBOM generation works
- Verify image signing works
- Document bypass procedures
- Set up monitoring/alerts
- Add workflow badges to README
๐ฏ Summary¶
What This Setup Provides: - โ No broken code can be merged to main - โ No Docker images built from failing checks - โ Fast parallel feedback (~12 min for PRs) - โ Automated quality gates at every step - โ Clear separation of concerns - โ Complete forensic audit trail - โ SBOM for compliance - โ Cryptographic image signatures - โ Provenance attestation
Forensic Software Benefits: - โ Every image traceable to source commit - โ Complete dependency transparency (SBOM) - โ Cryptographic integrity verification - โ Non-repudiatable build provenance - โ Compliance-ready audit trail - โ Court-defensible evidence chain
Maintenance Required: - Review status check names when workflows change - Update branch protection rules if adding new critical checks - Monitor security scans for new vulnerabilities - Rotate Docker Hub tokens annually - Document any bypass usage
Questions or Issues? - File an issue: https://github.com/3soos3/solve-it-mcp/issues - Workflow docs: .github/workflows/README.md