Branch targeting patterns¶
Rulesets can follow a repository's current default branch, name one branch, match a family, or enumerate a fixed set. The correct form depends on the repository's release model.
Configuration¶
octoform.yml
# octoform has no opinion on how you name or structure branches. This file
# shows four unrelated ways different projects do it — none of them is "the"
# convention, they are just different valid choices, targeted with the same
# `target_branches` field:
#
# - a single default branch, whatever it is called (~DEFAULT_BRANCH)
# - one explicit, hand-picked branch name
# - a family of branches matched by a glob
# - several explicit branches at once
#
# Pick whichever shape matches how your own project actually branches, or
# none of them — `rulesets` is entirely optional.
#
# `org-name` and the repository names below are placeholders — replace them
# with your own organisation and repositories before running this:
# export GITHUB_TOKEN=...
# octoform plan --config octoform.yml
owner: org-name
types:
# Whatever the default branch is named. Survives a rename from master to
# main, or any other rename, without editing this file.
default-branch-only:
rulesets:
- name: default-branch
target_branches: ['~DEFAULT_BRANCH']
block_force_push: true
# One specific, always-present branch, regardless of which one is default.
named-branch:
rulesets:
- name: trunk
target_branches: [trunk]
block_force_push: true
# A family of branches sharing a prefix. "release/*" is one common shape;
# your project might use "deploy/*", "env/*", or something else entirely.
release-branches:
rulesets:
- name: release-branches
target_branches: ['release/*']
required_approvals: 1
block_force_push: true
block_deletion: true
# More than one explicit branch protected the same way — useful when a
# project maintains a small, fixed, hand-managed set of long-lived lines
# rather than an open-ended pattern.
fixed-set-of-branches:
rulesets:
- name: maintained-lines
target_branches: [main, stable, lts]
block_force_push: true
# org-name has no type recorded for any repository (no custom property, and
# this file has no `classify.rules`), so without this section none of the
# four types above would ever be assigned and `plan` would report nothing
# for any of them. Assigning one placeholder repository to each type here is
# purely to make the example concrete — an organisation with a `classify`
# block, or custom properties already set, would not need this.
repos:
library-a: { type: default-branch-only }
library-b: { type: named-branch }
web-app: { type: release-branches }
cli-tool: { type: fixed-set-of-branches }
Choose a targeting strategy¶
| Strategy | Use it when |
|---|---|
~DEFAULT_BRANCH |
Protection should follow a future default-branch rename. |
| Exact name | One branch has a permanent role independent of the default. |
Glob such as release/* |
New branches in a named family should inherit the policy. |
| Fixed list | A small, reviewed set of long-lived lines is maintained. |
Each placeholder repository is assigned a different type so the plan makes all four strategies visible. Replace those names and type assignments with the classification model used by the target owner.
Review destructive restrictions
Blocking deletion or force-push changes how maintainers recover and retire branches. Confirm the intended branch lifecycle before applying a ruleset.