Skip to main content
Repository-level settings provide the highest precedence in Safe Settings’ configuration hierarchy. These settings override both org-level and suborg-level configurations for specific repositories.

File Location

Repository settings are stored in the .github/repos/ folder of your admin repository, with one YAML file per repository:
admin/
└── .github/
    └── repos/
        ├── api-gateway.yml
        ├── web-app.yml
        ├── mobile-app.yml
        └── core-service.yml
The filename must match the repository name exactly: <repo-name>.yml or <repo-name>.yaml
The repo directory structure (.github/repos/) cannot be customized.

When to Use Repo Settings

Use repository-specific settings when:
  • A repository has unique requirements that differ from team defaults
  • You need to exempt a critical repository from standard policies
  • You want to enforce stricter controls on high-value repositories
  • A repository requires special branch protection, teams, or features
Repo settings have the highest precedence and will override any org-level or suborg-level configuration.

Basic Structure

Repo configuration files follow the same structure as org and suborg settings:
.github/repos/api-gateway.yml
# All settings from org and suborg levels can be overridden here

repository:
  description: "Production API Gateway - Critical Service"
  has_wiki: false
  has_projects: false

branches:
  - name: default
    protection:
      required_pull_request_reviews:
        required_approving_review_count: 3  # Override: critical repo needs 3 approvals

teams:
  - name: api-team
    permission: admin

Repository-Specific Features

Repo settings include two special features not available at other levels:

Force Create

Automatically create the repository if it doesn’t exist:
.github/repos/new-project.yml
repository:
  force_create: true
  private: true
  description: "New project repository"
  auto_init: true
Use force_create carefully. Once set to true, Safe Settings will create the repository on the next sync.

Template Repository

Create repositories from a template:
.github/repos/new-service.yml
repository:
  force_create: true
  template: template-microservice  # Use this repo as a template
  private: true
  description: "New microservice"
The template field is used with force_create to specify which template repository to use when creating the new repository.

Complete Examples

.github/repos/api-gateway.yml
repository:
  description: "Production API Gateway - Critical Infrastructure"
  private: true
  has_wiki: false
  has_projects: false
  topics:
    - api
    - gateway
    - production
    - critical
  security:
    enableVulnerabilityAlerts: true
    enableAutomatedSecurityFixes: true

branches:
  - name: default
    protection:
      required_pull_request_reviews:
        required_approving_review_count: 3
        require_code_owner_reviews: true
        dismiss_stale_reviews: true
        require_last_push_approval: true
      required_status_checks:
        strict: true
        contexts:
          - "CI/test"
          - "CI/integration-test"
          - "security/sast"
          - "security/dependency-scan"
          - "security/secret-scan"
          - "performance/load-test"
      enforce_admins: true
      restrictions:
        teams:
          - senior-engineers
          - sre-team
  
  - name: "release/*"
    protection:
      required_pull_request_reviews:
        required_approving_review_count: 2
      enforce_admins: true

teams:
  - name: api-team
    permission: admin
  - name: sre-team
    permission: push
  - name: security-team
    permission: push

custom_properties:
  - name: criticality
    value: critical
  - name: on-call-team
    value: api-team
  - name: security-tier
    value: "1"

environments:
  - name: production
    wait_timer: 30
    reviewers:
      - type: Team
        id: api-team
      - type: Team
        id: sre-team
    deployment_branch_policy:
      protected_branches: true
      custom_branch_policies: false

Overriding Patterns

Override Specific Settings

You only need to specify the settings you want to override:
repository:
  private: true
  has_issues: true
  has_wiki: true
  has_projects: true

branches:
  - name: default
    protection:
      required_pull_request_reviews:
        required_approving_review_count: 1

Disable Settings with Null

Set settings to null to explicitly disable them:
.github/repos/legacy-project.yml
repository:
  has_wiki: false
  has_projects: false

branches:
  - name: default
    protection:
      required_pull_request_reviews:
        required_approving_review_count: 1
      required_status_checks: null  # Explicitly disable status checks
      enforce_admins: false
      restrictions: null            # Explicitly disable restrictions

Add Additional Teams

Teams are merged, not replaced:
.github/repos/cross-team-project.yml
# Teams from org and suborg levels are preserved
# These teams are added to the existing teams
teams:
  - name: special-project-team
    permission: admin
  - name: external-consultants
    permission: pull

Renaming Repositories

Repo renaming requires special attention in Safe Settings.

Using Safe Settings to Rename

To rename a repository using Safe Settings, rename the repo config file:
# In your admin repo
mv .github/repos/old-name.yml .github/repos/new-name.yml
Safe Settings will:
  1. Detect the file rename
  2. Rename the repository in GitHub
  3. Use the new name going forward

Manual Renames

By default, Safe Settings ignores manual renames (for backward compatibility). To prevent manual renames:
# Set environment variable
BLOCK_REPO_RENAME_BY_HUMAN=true
With this setting:
  • Manual renames are reverted automatically
  • Bot-initiated renames are allowed
  • Safe Settings copies old-repo.yml to new-repo.yml (if new file doesn’t exist)

Working with Status Checks

You can allow status checks to be defined outside of Safe Settings:
.github/repos/dynamic-checks.yml
branches:
  - name: default
    protection:
      required_pull_request_reviews:
        required_approving_review_count: 2
      required_status_checks:
        strict: true
        contexts:
          - "{{EXTERNALLY_DEFINED}}"  # Allow external status checks
For rulesets:
.github/repos/dynamic-checks.yml
rulesets:
  - name: Status Checks
    target: branch
    enforcement: active
    rules:
      - type: required_status_checks
        parameters:
          required_status_checks:
            - context: "{{EXTERNALLY_DEFINED}}"
  • For new branch protection/rulesets: Deployed with no status checks initially
  • For existing configurations: Existing status checks remain unchanged
  • Status checks can be added/modified via GitHub UI
  • If you remove {{EXTERNALLY_DEFINED}}, checks revert to Safe Settings configuration

Configuration Tips

Start Minimal

Only define settings that need to differ from org/suborg defaults. This keeps configs maintainable.

Use Comments

Document why specific overrides exist:
# Requires 3 reviewers due to PCI compliance
required_approving_review_count: 3

Group Related Settings

Keep related settings together for readability. Add blank lines between major sections.

Test in PR

Always test repo config changes in a PR. Safe Settings will run in dry-run mode and show you what will change.

Validation

Repo-level settings are subject to validation rules defined in your deployment settings:
deployment-settings.yml
overridevalidators:
  - plugin: branches
    error: |
      Branch protection required_approving_review_count cannot be overridden to a lower value
    script: |
      if (baseconfig.protection.required_pull_request_reviews.required_approving_review_count && 
          overrideconfig.protection.required_pull_request_reviews.required_approving_review_count) {
        return overrideconfig.protection.required_pull_request_reviews.required_approving_review_count >= 
               baseconfig.protection.required_pull_request_reviews.required_approving_review_count
      }
      return true
This prevents repos from weakening security policies set at the org or suborg level.
If a repo config fails validation:
  1. The PR check will fail with an error message
  2. The settings will not be applied
  3. The error will be shown in the check run and PR comment
  4. You must fix the invalid configuration before merging

Troubleshooting

Check:
  1. Is the filename exactly <repo-name>.yml or <repo-name>.yaml?
  2. Is the YAML valid? Use a YAML validator.
  3. Check the Safe Settings check run in the admin repo for errors.
  4. Is the repository in the restricted repos list?
Your repo config may be violating an override validator. Check your deployment-settings.yml for validators that prevent certain overrides. The error message will indicate which validator failed.
Repo settings are merged with suborg and org settings. If you explicitly set a value to null or override it, the suborg value will not be used. Review your merge hierarchy.
Ensure:
  1. force_create: true is set
  2. You’ve pushed to the default branch (not a PR)
  3. Safe Settings has permissions to create repositories
  4. Check Safe Settings logs for errors

Best Practices

  1. Use Sparingly - Only create repo configs when truly needed. Most repos should use org/suborg defaults.
  2. Document Exceptions - Add comments explaining why a repo needs special treatment:
    # This repo handles PII and requires extra security controls
    branches:
      - name: default
        protection:
          required_approving_review_count: 3
    
  3. Leverage CODEOWNERS - Ensure the right team approves changes:
    .github/repos/critical-api.yml @org/api-team @org/security-team
    
  4. Regular Reviews - Periodically review repo configs to see if they can be consolidated into suborg configs.
  5. Test First - Always create a PR to test changes before applying them.

Next Steps

Configuration Hierarchy

Understand how repo settings merge with org and suborg settings

Deployment Settings

Configure validators and restrictions

Sample Repo Config

View sample repository configuration

Status Checks

Learn about status check inheritance

Build docs developers (and LLMs) love