Enforce hook for branch creation in GitHub enterprise to not allow creating branches with names with certain regex pattern

Viewed 1054

We have a requirement where collaborators with write access to a GitHub repository should not be allowed to create branches with certain names. They can create locally but can't push to remote and also can't create directly using the GitHub UI. I know we can do something like this using git hook and enable that for that repo on the server side (on github enterprise server), but struggling to figure out how. Is that even possible?

If so I would like a shell script or something similar that I can use as hook to reject creation/push of any branches that start with the string release. I tried the below by adding a pre-receive hook on the github enterprise server but it doesn't do any good. Created a repo with a branch_hook.sh file and configured that hook and enabled it on a repo to test.

#!/bin/bash
branch=`git rev-parse --abbrev-ref HEAD`
if [[ "$branch" == release* ]]; then
    echo "Your branch starts with release and is not allowed to be        
          pushed. Please create one that doesn't start with the release"
    exit 1
fi

It looks like GitHub server doesn't validate the branch name at all. If I execute it locally under a git repo, it works fine but git commit or push doesn't consider it at all.

Based on VonC's suggestions I tried this but doesn't seem to work. Since I couldn't get the script at https://gist.github.com/caniszczyk/1327469 to work so tried something of my own.

#!/bin/bash
# Reject branch pushes that contain commits under those branches that have names starting with release

first_commit='0000000000000000000000000000000000000000'

while read -r oldrev newrev refname; do

    [ "$newrev" = "$first_commit" ] && continue


    [ "$oldrev" = "$first_commit" ] && range="$newrev" || range="$oldrev..$newrev"

    for commit in $(git rev-list "$range" --not --all); do
        if [[ "${refname#refs/heads/}" == release* ]]; then
    
            echo "ERROR: Your push was rejected because the commit"
            echo "ERROR: $commit in ${refname#refs/heads/}"
            echo "ERROR: is not allowed as ${refname#refs/heads/} is not supported branch name"
            echo "ERROR: Please fix your branch name or contact your repository admin."
            exit 1
        fi
    done

done

This works great when you create branch locally (just created newly or created newly and some commits added) and try to push to remote however there is no way to prevent creating branches using GitHub UI as the hook doesn't work in that scenario as its not a push event. So I am wondering how to get the script at https://gist.github.com/caniszczyk/1327469 to work if that is a true solution that works in both the cases.

2 Answers

Since it is an on-premise GitHub Enterprise server, you can add n

A pre-receive hook script executes in a pre-receive hook environment on the GitHub Enterprise Server appliance.
When you create a pre-receive hook script, consider the available input, output, exit-status and environment variables.

For example, this hook will enforce a naming convention policy on any branch pushed, which means it will disallow said push if the branch name does not follow a certain convention.

You can try and fix this using a GitHub action such as this one:

name: Fail when incorrect branch names are used
on:
  push:
    branches:
    - 'release*'
    - 'release*/**'

jobs:
  no_release_in_branch_names:
    runs-on: ubuntu-latest
    steps:
      - name: If this is triggered, it should fail
        run: |
          __msg="::error::This branch ${GITHUB_REF_NAME} includes «release»; please don't use that in branch names
          Please rename the local branch with
              git checkout ${GITHUB_REF_NAME}
              git branch -m name_without_release
          echo "$__msg"
          echo ::set-output name=status::failure
          exit 1

That will prevent pushing to any branch created either locally or from the UI, by failing with the first commit that's done to that branch. Essentially, uses GitHub actions for a workflow that's triggered (and fails) just for the branch names that you don't want.

Related