Rulesets reference

Repository rulesets — branch or tag protection rules — are declared under a config's rulesets: section. Each entry is matched to a live ruleset by name and updated to exactly the declared spec.

Ruleset shape

FieldTypeDefaultNotes
namestringrequiredMatch key
targetbranch | tagbranch
enforcementactive | evaluate | disabledactive
bypass_actorslist[]See Bypass actors
conditionsobjectempty ref_nameSee Conditions
ruleslist[]See Rule types
rulesets:
  - name: main-branch-protection
    target: branch
    enforcement: active
    conditions:
      ref_name:
        include: ["~DEFAULT_BRANCH"]
        exclude: []
    bypass_actors:
      - actor_type: OrganizationAdmin
        bypass_mode: always
    rules:
      - type: pull_request
        required_approving_review_count: 1
        dismiss_stale_reviews_on_push: true
      - type: required_status_checks
        required_checks: [ci, lint]
        strict_required_status_checks_policy: true

Rulesets merge across extends: layers the same way as the config's other keyed lists — by name, same-key item replaces in place, new items append. See composing with extends in the config reference.

Tag rulesets

Setting target: tag protects tags instead of branches — the same rule types, conditions, and bypass actors apply, just matched against tag names. A common case is locking down release tags so only an automated release process can create them, closing a publish trust boundary: if a CI workflow trusts "pushing a v* tag" as the signal to publish, anyone who can push that tag can trigger a publish from an arbitrary tree.

rulesets:
  - name: protect release tags
    target: tag
    enforcement: active
    conditions:
      ref_name:
        include: ["v*"]
        exclude: []
    rules:
      - type: creation
      - type: update
      - type: deletion
    bypass_actors:
      - actor_type: RepositoryRole
        actor_id: 5   # Repository Admins
        bypass_mode: always
      - actor_type: Integration
        actor_id: 123456
        bypass_mode: always

The bypass_actors entries are what let the automated process (here, a GitHub App) still create/move/delete the tag while everyone else is blocked by the three rules above. Give admins a bypass too, not just the automation: without one, a broken App installation or key locks every repo owner out of their own tags until the ruleset itself is edited.

Matching and drift

A ruleset is matched to a live one by name. Once matched, every declared list — rules, bypass_actors, and the ref-name include/exclude patterns in conditions — must equal the live list exactly, not just be a subset. A rule someone added by hand in the GitHub UI counts as drift and triggers an update that removes it, same as any other mismatch.

Server-supplied metadata that the config never sets — a check's integration_id, a bypass actor's resolved actor_id, timestamps — is ignored when comparing, so values GitHub fills in on its own can't cause spurious churn on every plan.

Rulesets inherited from an organization or enterprise are never matched or deleted: the listing call uses includes_parents=false, so only rulesets defined directly on the repo are ever in scope.

Conditions

Conditions select which refs a ruleset applies to, via ref_name.include and ref_name.exclude pattern lists.

FieldTypeDefaultNotes
ref_name.includelist[string][]Two special tokens: ~DEFAULT_BRANCH, ~ALL
ref_name.excludelist[string][]
conditions:
  ref_name:
    include: ["~DEFAULT_BRANCH"]
    exclude: ["refs/heads/releases/**"]

Bypass actors

FieldTypeDefaultNotes
actor_typeIntegration | OrganizationAdmin | RepositoryRole | Team | DeployKeyrequired
actor_idintunsetNot needed for actor types without an id, e.g. OrganizationAdmin
bypass_modealways | pull_requestalways

Rule types

Each entry in rules: has a type discriminator plus that type's own parameters. The groups below cover every supported type.

Parameterless

These take no parameters — just the type:

rules:
  - type: creation
  - type: deletion
  - type: non_fast_forward
  - type: required_linear_history
  - type: required_signatures

Pattern rules

commit_message_pattern, commit_author_email_pattern, committer_email_pattern, branch_name_pattern, and tag_name_pattern all share the same parameter shape:

FieldTypeDefaultNotes
operatorstarts_with | ends_with | contains | regexrequired
patternstringrequired
namestringunsetLabel shown for the pattern in the GitHub UI
negateboolfalse
rules:
  - type: commit_message_pattern
    operator: regex
    pattern: '^(feat|fix|docs|refactor|chore)(\(.+\))?: .+'
    name: conventional-commits

update

FieldTypeDefaultNotes
update_allows_fetch_and_mergeboolfalse

pull_request

FieldTypeDefaultNotes
required_approving_review_countint0
dismiss_stale_reviews_on_pushboolfalse
require_code_owner_reviewboolfalse
require_last_push_approvalboolfalse
required_review_thread_resolutionboolfalse
allowed_merge_methodslist of merge | squash | rebaseunsetUnset allows all methods

required_status_checks

FieldTypeDefaultNotes
required_checkslist[]Bare strings are coerced to {context: ...}; entries may also set integration_id
strict_required_status_checks_policyboolfalse
do_not_enforce_on_createboolfalse
rules:
  - type: required_status_checks
    required_checks: [ci, lint]      # shorthand for [{context: ci}, {context: lint}]
    strict_required_status_checks_policy: true

required_deployments

FieldTypeDefaultNotes
required_deployment_environmentslist[string][]Environment names

merge_queue

FieldTypeDefaultNotes
check_response_timeout_minutesint60
grouping_strategyALLGREEN | HEADGREENALLGREEN
max_entries_to_buildint5
max_entries_to_mergeint5
merge_methodMERGE | SQUASH | REBASEMERGE
min_entries_to_mergeint1
min_entries_to_merge_wait_minutesint5

File restrictions

Four separate rule types, each gating one kind of file-level change:

Rule typeFieldDefaultNotes
file_path_restrictionrestricted_file_paths[]Paths that cannot be added or modified
max_file_path_lengthmax_file_path_lengthrequiredMaximum path length, in characters
file_extension_restrictionrestricted_file_extensions[]Extensions that cannot be added or modified
max_file_sizemax_file_sizerequiredMaximum blob size, in MB

workflows

FieldTypeDefaultNotes
workflowslist of {repository_id, path, ref?, sha?}[]repository_id and path required per entry
do_not_enforce_on_createboolfalse
rules:
  - type: workflows
    workflows:
      - repository_id: 123456789
        path: .github/workflows/ci.yml
        ref: refs/heads/main

code_scanning

FieldTypeDefaultNotes
code_scanning_toolslist of {tool, security_alerts_threshold, alerts_threshold}[]security_alerts_threshold defaults to high_or_higher, alerts_threshold to errors