Skip to main content

Branch protection

Branch protection on fremforge follows the upstream Forgejo model: rules attach to branches by glob pattern, enforce review + status + history requirements, and block writes that violate them. fremforge adds org-wide defaults so the same posture applies to every repo without per-repo configuration drift.

Org defaults vs per-repo overrides

The Org → Repos page sets the rules that apply to every repo in the org. The defaults configure each repo’s main (or whatever your default branch is) on creation, and an hourly backfill reconciler fills in any repo that has zero branch protection — it never overrides a repo admin’s existing settings. Two cases rely on that second pass: repos created before org defaults existed, and repos whose default branch was not yet visible when the create-time installer ran (an empty repo you push your own first commit into). Both are protected within the hour without you doing anything. Repos that already have protection but have drifted weaker than the org default are surfaced by the drift detector as an alert rather than being auto-reverted (see below).

Per-repo overrides live on the repo settings page (/<org>/<repo>/settings/branches). Override only when the repo has a genuine policy exception — most teams set the org default once and never touch repo-level rules.

Settings that map directly to Forgejo

  • Require pull request reviews before merging. Set a minimum reviewer count (typically 1 or 2). Dismiss stale reviews on push to prevent rubber-stamps from surviving a force-amend.

  • Require status checks to pass before merging. Name the status contexts that must report success. fremforge emits six, and requiring only some of them leaves the others unable to block a merge:

    • fremforge/sast — static analysis
    • fremforge/dep-scan — dependency vulnerabilities
    • fremforge/license-scan — licence policy
    • fremforge/image-scan — container image and IaC misconfiguration
    • fremforge/cosign-verify — signature verification
    • fremforge/secret-scan — committed-secret detection

    The org default requires all six; if you set required checks by hand, list all six. See Re-running scans for what each one covers.

  • Require signed commits. When on, unsigned commits on the protected branch are rejected at push. See Cosign for the commit-signing path with Sigstore short-lived certs.

  • Require linear history. When enabled, fremforge disables merge commits on the repo — merges are squash or rebase only, so the protected branch keeps a linear history.

  • Block force pushes. Refuses --force on the protected branch entirely.

  • Block branch deletion. A protected branch cannot be deleted — this is inherent to having a branch-protection rule attached, not a separate toggle. As long as the branch is protected, delete operations against it are refused.

Settings fremforge adds on top

  • Enforce protection on org owners/admins too. Forgejo exempts org owners from branch protection by default (matching GitHub/GitLab parity), so owners can bypass required reviews and status checks. fremforge exposes this as a per-tenant toggle on the Repos admin page — “Enforce protection on org owners/admins too” — which is off by default. Turn it on to make even owners subject to required reviews + status checks (Forgejo’s apply_to_admins).
  • Require CODEOWNERS review. Forgejo enforces CODEOWNERS automatically whenever a CODEOWNERS file exists in the repo and reviews are required — the matching code owners are added as required reviewers with no extra rule-level flag. The toggle on the Repos page is informational: it documents that the org expects CODEOWNERS coverage; there is no separate standalone control to switch on.
  • Status-check allowlist for fremforge-emitted checks. The six canonical names are listed above. They are held in one place internally, shared between the create-time install and the hourly backfill, so the set a new repo gets and the set the backfill enforces cannot drift apart.
  • Drift detector. A separate daily gap-scan flags any repo whose branch protection is absent or weaker than the org default — weaker meaning fewer required approvals, or a required check the default demands and the repo does not. (The backfill above is hourly and only fills in repos with no protection; this daily scan is what notices a repo that has protection but has been loosened.) This surfaces as a distinct admin Bell alert — “N repos with weakened branch protection” — that links to the Repos admin page. It is detect-and-alert only: fremforge does not auto-revert weakened settings, because a repo owner’s explicit settings win. Use the alert to decide whether to follow up with the repo owner.

Setting it up

  1. Open the Org → Repos page.
  2. Pick the branch glob (typically main or main, master, release/*).
  3. Set the toggles above. Save.
  4. The change is recorded in the audit log as repo-defaults.branch-protection.updated. A retroactive apply to existing zero-protection repos is logged as repo-defaults.branch-protection.retro-applied, and resetting the org defaults to the fremforge baseline is logged as repo-defaults.reset-baseline.

See also

  • Scorecard — branch protection drives the Branch-Protection OpenSSF score.
  • Authentication policy — the broader posture (signed commits, SSH transport, MFA).
  • Cosign — required-signed-commits implementation.