3

I am trying to setup a pre-receive hook in Github that we will be using to avoid unnecessary commits. I am looking for few rules to be maintained

Requiring a custom commit message. Every commit should include an existing JIRA at the beginning example JIRA-XXX | Commit message

Enforce this on any pull request as well.

Requiring a branch name format.

example: abc_devName_some_br_name_jira_XXX

Can anybody here help me, how can this be done ?

Kunal Vohra
  • 2,703
  • 2
  • 15
  • 33
  • #1 Do you want to decline a pull request if commits message does not meet your pattern? #2 Do you have some continuous integration server? – JRichardsz Jul 16 '21 at 05:32
  • @JRichardsz answer to #1 Yes, Push will be declines. #2 Yes we have CI server – Kunal Vohra Jul 16 '21 at 06:22
  • #1 Is your c.i server able to receive the pull request event? or just the push event? #2 is your c.i server able to clone the repository and performs advanced git commands on the repository? #3 Pull request could be declined. Git push cannot be declined. #4 Do you want to delete the commit with incorrect message or decline the pull request? – JRichardsz Jul 16 '21 at 06:27
  • @JRichardz Answers #1. I am not 100% sure but I think both are possible #2 Yes #3. PR declined should and should not be able to merge to master. #4. Decline the pull request – Kunal Vohra Jul 16 '21 at 06:43
  • @KunalVohra Is your project node-based? because in that case, you can use Husky https://typicode.github.io/husky/#/?id=usage – Ashish Rawat Jul 16 '21 at 09:07
  • Its Go lang @AshishRawat – Kunal Vohra Jul 16 '21 at 10:23
  • The cornerstone of any automation is that your ci server can receive the webhook notification which is a json containing the event information. Check [this](https://jrichardsz.github.io/devops/devops-with-git-and-jenkins-using-webhooks) for jenkins. If your c-i server is "acme", I think your question should change slightly: How decline github pull request based on commit message using acme? If you agree with this, add the name of your ci server and the installed webhook plugins to the question details. – JRichardsz Jul 16 '21 at 14:16
  • @Jrichardsz I think both ways is needed. Code push should be stopped first of all. And by any case if it reaches the github. PR shouldn't be successful – Kunal Vohra Jul 18 '21 at 15:20
  • When `git push` is performed, the target branch receive the commit, no matter what. The only way to block the commit reception is using branch permissions [github, bitbucket, gitlab](https://i.stack.imgur.com/b7mag.png). These rules are created at the repository creation moment and usually the input parameters are just the branch name and role group. Commit message is not available in these rules. That said, there are not options in common platforms to deny or prohibit the commit reception based on commit message pattern. – JRichardsz Jul 18 '21 at 16:49
  • The only way using ci server is receive the commit, notify to the ci server using webhooks, evaluate the commit message applying some logic and then deny the pull request, revert commit on the branch using git commands, notify by email, etc. I think deny the pull request is enough. Revert the commit in the developer branch, could delete the developer work. Common practice is **protect** the master branch from accidental commits. In this case, the branch permissions feature in common platforms is enough. – JRichardsz Jul 18 '21 at 16:54

1 Answers1

7

Git webhooks and git hooks are different options. We can catalog in:

  • Client-Side Git Hooks
    • works at developer machine level
  • Server-Side Git Hooks
    • works at git server machine level
  • WebHooks
    • works notifying the event to a external services (jenkins, travis, circleci, etc) after the event in case of git push

Your title question say "webhooks" but your question details say "pre-receive hook", so that is the first thing to clarify: As I know, there are different options that works separately.

I will show you some options to accomplish your goal:

Branch Protection

Used to protect master branch of accidental pushes.

These rules are created at the repository creation moment and usually the input parameters are just the branch name and role group. Commit message is not available in these rules.

Github sample

github

More details here: https://docs.github.com/en/github/administering-a-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule#about-branch-protection-rules

Bitbucket sample

bitbucket

webhooks

Easy way, but happen after git push event. Steps:

  • configure the webhook pointing to your c.i server, in the settings section of your git platform (github in your case)
  • in your c.i server create a job/task to receive the event details (a big json containing a lot of information like: repository name, branch name, author mail, commit id, commit message)
  • in this job/task put your logic to evaluate if commit message follow your guidelines.
  • if commit message doesn't meet your guidelines, you can:
    • notify by mail
    • using some privileged account, revert the commit. This is some dangerous action for my opinion because the developer work could be deleted.
    • search a pull request related to commit and deny it or create another webhook just for pull request event and do the same.

Github server hook

pre-receive hook feature is available only for GitHub Enterprise

Basically this is a shell script which will run in the server of your github enterprise.

I think is similar to the git server side hooks. I found this link with steps to register, update and delete hooks:

Now, how to create the script:

The problem as I found is that git message string is not a ready to use variable. In webhooks it is!!

If you want to access to the commit message, you will need to test this

The main idea is having the commit id, you can access to some file in git server, which contains the message:

tree cfda3bf37b78aef7f4daf
parent 085bb3306e7e7
author Scott Chacon <schacon@gmail.com> 1205815931 -0700
committer Scott Chacon <schacon@gmail.com> 1240030591 -0700

I'm the message sent by the developer

If you achieve that, you could add a message to be showed when your developer performs a git push with an invalid git message:

> Counting objects: 7, done.
> Delta compression using up to 4 threads.
> Compressing objects: 100% (3/3), done.
> Writing objects: 100% (7/7), 700 bytes | 0 bytes/s, done.
> Total 7 (delta 0), reused 7 (delta 0)
> remote: error: rejecting all pushes
> To git@192.168.99.100:test.git
>  ! [remote rejected] main -> main (pre-receive hook declined)
> error: commit message does not meet the rule xyz

Server-Side Git Hooks

Similar to github enterprise feature. I think that install a git server in cloud or on-premise machine is not a common practice due to the ready to use services (github, bitbucket, gitlab, etc) but it is an option.

You can find more details here

As in github enterprise server, you will not have the commit message ready to use as variable. Check this:

Client-Side Git Hooks

The same idea but at developer machine level. More details here

Basically in the .git folder of any repository in the machine of your developers, you can put these scripts.

Due that this script is shell script, you will have the same problem: git message is not a ready to use variable

References

JRichardsz
  • 14,356
  • 6
  • 59
  • 94