Skip to content

Create and edit branch protection rules for a repository #3528

Description

@martibutler

Describe the feature or problem you’d like to solve

Could the cli tool be extended to update properties on repos for an organisation? Such as setting branch protection on all repos belonging to an organisation.

Proposed solution

Could be an extension to the gh repo action to admin or update and pass in some flags/params to update certain things.

Activity

  1. mislav commented on Apr 28, 2021

    @mislav
    Contributor

    Thanks for writing in!

    Repository administration is a wide area and it's unlikely that the CLI will have dedicated commands to cover every possible aspect of it. Therefore, I will rename this issue to focus on just editing branch protection rules, since I believe it's a good idea!

    In the meantime, you may be able to use gh api to interact with GitHub API for branch protection rules. For example, to create a rule that requires at least 3 approving reviews for a PR:

    # get the repo ID of the "cli/cli" repository
    repositoryId="$(gh api graphql -f query='{repository(owner:"cli",name:"cli"){id}}' -q .data.repository.id)"
    
    # create a branch protection rule (untested!)
    gh api graphql -f query='
    mutation($repositoryId:ID!,$branch:String!,$requiredReviews:Int!) {
      createBranchProtectionRule(input: {
        repositoryId: $repositoryId
        pattern: $branch
        requiresApprovingReviews: true
        requiredApprovingReviewCount: $requiredReviews
      }) { clientMutationId }
    }' -f repositoryId="$repositoryId" -f branch=main -F requiredReviews=3
  2. changed the title [-]Administering repos?[/-] [+]Create and edit branch protection rules for a repository[/+] on Apr 28, 2021
  3. vilmibm commented on May 18, 2021

    @vilmibm
    Contributor

    In OP's post it sounds like there is an interest in org-level operations, which I wanted to point out. We've discussed adding something for managing orgs and this is at least something we can consider incorporating (operations on all of an org's repositories).

    As for directly managing a single repo's branch protection rules (which is what @mislav is addressing), I agree that it's a nice idea. I can imagine a nice multi-select prompt for specifying the rules; we should do a spike on what that UI might look like.

  4. added
    coreThis issue is not accepting PRs from outside contributors
    on May 18, 2021
  5. james-perfectserve commented on Sep 24, 2021

    @james-perfectserve

    Thanks for writing in!

    Repository administration is a wide area and it's unlikely that the CLI will have dedicated commands to cover every possible aspect of it. Therefore, I will rename this issue to focus on just editing branch protection rules, since I believe it's a good idea!

    In the meantime, you may be able to use gh api to interact with GitHub API for branch protection rules. For example, to create a rule that requires at least 3 approving reviews for a PR:

    # get the repo ID of the "cli/cli" repository
    repositoryId="$(gh api graphql -f query='{repository(owner:"cli",name:"cli"){id}}' -q .data.repository.id)"
    
    # create a branch protection rule (untested!)
    gh api graphql -f query='
    mutation(repositoryId:ID!,$branch:String!,$requiredReviews:Int!) {
      createBranchProtectionRule(input: {
        repositoryId: $repositoryId
        pattern: $branch
        requiresApprovingReviews: true
        requiredApprovingReviewCount: $requiredReviews
      }) { clientMutationId }
    }' -f repositoryId="$repositoryId" -f branch=main -F requiredReviews=3

    image

  6. james-perfectserve commented on Sep 24, 2021

    @james-perfectserve
    repositoryId="$(gh api graphql -f query='{repository(owner:"cli",name:"cli"){id}}' -q .data.repository.id)"
    
    # create a branch protection rule (untested!)
    gh api graphql -f query='
    mutation(repositoryId:ID!,$branch:String!,$requiredReviews:Int!) {
      createBranchProtectionRule(input: {
        repositoryId: $repositoryId
        pattern: $branch
        requiresApprovingReviews: true
        requiredApprovingReviewCount: $requiredReviews
      }) { clientMutationId }
    }' -f repositoryId="$repositoryId" -f branch=main -F requiredReviews=3

    You had a typo, you were missing a $ on repositoryId:ID!
    I'm not familiar with graphql so it took me a hot second to figure out
    Here is a tested working version of your snippet (I ran it inside a .sh bash file)

    owner="YourOrgName"
    name="YourRepoName"
    repositoryId="$(gh api graphql -f query='{repository(owner:"'$owner'",name:"'$name'"){id}}' -q .data.repository.id)"
    
    
    gh api graphql -f query='
    mutation($repositoryId:ID!,$branch:String!,$requiredReviews:Int!) {
      createBranchProtectionRule(input: {
        repositoryId: $repositoryId
        pattern: $branch
        requiresApprovingReviews: true
        requiredApprovingReviewCount: $requiredReviews
      }) { clientMutationId }
    }' -f repositoryId="$repositoryId" -f branch="[main,master]*" -F requiredReviews=3
  7. added
    extension-ideaAn idea that could make a good GitHub CLI extension
    on Jan 31, 2022
  8. twelvelabs commented on Oct 26, 2022

    @twelvelabs
    Contributor

    I’ve created an extension that allows you to manage repo and branch protection settings declaratively: https://github.com/twelvelabs/gh-repo-config

    It basically lets you generate and store the REST API payloads in the .GitHub die of the repo.

    @vilmibm The origin of my extension was wanting to do exactly that. I have a workflow that runs regularly to ensure that everything in one of my orgs is configured correctly: https://github.com/gostamp/.github/blob/main/.github/config/configure.sh (still need to rework it to use the extension 😬 ).

  9. Vampire commented on Nov 4, 2022

    @Vampire

    Here a little one-liner magic (mainly that I find it in the future again :-D) to set the required checks to all checks that were produced on a specific commit or reference:

    gh api -i repos/{owner}/{repo}/branches/master/protection/required_status_checks --method PATCH --input - <<<"$(gh api repos/{owner}/{repo}/commits/06354bb/check-runs --paginate --jq '{ context: .check_runs[].name }' | wsl jq -s '{ checks: . | unique }')"
    
  10. Shion1305 commented on Jun 29, 2023

    @Shion1305
    Contributor

    I really want this feature!!

  11. janeklb commented on Jul 13, 2023

    @janeklb

    Here a little one-liner magic (mainly that I find it in the future again :-D) to set the required checks to all checks that were produced on a specific commit or reference:

    gh api -i repos/{owner}/{repo}/branches/master/protection/required_status_checks --method PATCH --input - <<<"$(gh api repos/{owner}/{repo}/commits/06354bb/check-runs --paginate --jq '{ context: .check_runs[].name }' | wsl jq -s '{ checks: . | unique }')"
    

    I adjusted this a little by manually crafting the list of required checks writing them to a file status-checks.json

    {
      "checks": [
        { "context": "lint", "app_id": 100000000 },
        { "context": "detect-cyclic-imports", "app_id": 100000000 },
        { "context": "prettier", "app_id": 100000000 },
        { "context": "tsc", "app_id": 100000000 },
        { "context": "test", "app_id": 100000000 },
        { "context": "test-prod", "app_id": 100000000 },
        { "context": "build", "app_id": 100000000 },
        { "context": "UI Review", "app_id": null },
        { "context": "UI Tests", "app_id": null }
      ]
    }

    (replace list of checks as well as app_id values as you see fit)

    and then calling

    gh api repos/{owner}/{repo}/branches/master/protection/required_status_checks \
      --method PATCH \
      --input status-checks.json
  12. BenLiyanage commented on Dec 7, 2023

    @BenLiyanage

    This would be amazing. It was a lot of custom code to get this to work in a script, in addition to having to create a github app with administration permissions. I can share the script if anyone is interested.

  13. thejimbirch commented on Jan 28, 2024

    @thejimbirch
  14. fbuetler commented on Mar 25, 2024

    @fbuetler

    If you just want to protect a branch, this worked for me:

    gh api "repos/<org>/<repo>/branches/<branch>/protection" --method PUT --input branchProtection.json

    branchProtection.json:

    {
      "allow_deletions": false,
      "allow_force_pushes": false,
      "allow_fork_syncing": false,
      "block_creations": false,
      "enforce_admins": false,
      "lock_branch": false,
      "required_conversation_resolution": false,
      "required_linear_history": false,
      "required_signatures": false,
      "required_status_checks": null,
      "required_pull_request_reviews": null,
      "restrictions": null
    }
    

    If you want to further configure the branch protection rules, have a look at the docs.

    Applying the branch protection rules for all repos in an org for the default branch can be accomplished like this (pay attention to the limit):

    gh repo list <org> --limit 100 --no-archived --json "nameWithOwner,defaultBranchRef" \
      | jq -c '.[]' \
      | while read j; do 
          nameWithOwner=$(jq -r '.nameWithOwner' <<< "$j"); 
          defaultBranch=$(jq -r '.defaultBranchRef.name' <<< "$j"); 
          gh api "repos/$nameWithOwner/branches/$defaultBranch/protection" --method PUT --input branchProtection.json --silent; done
  15. remyleone commented on Jul 7, 2025

    @remyleone

    I think that rulesets are managed by the CLI and can replace features from branch protection. That being said, it would be helpful to have a migration feature between the two.

    gh ruleset list
    gh ruleset check
    gh ruleset view
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    coreThis issue is not accepting PRs from outside contributorsenhancementa request to improve CLIextension-ideaAn idea that could make a good GitHub CLI extensionpitchpitched internally for prioritisation

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions