Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Github webhooks - pre-push hooks

My requirement is that whenever developers are pushing to github, then before the push a CI build should trigger on Jenkins server. If that build fails, then push to github should be rejected. I need to write hooks for this, but I don't want to write client-side hooks as they can be disabled by developers. I want server-side github webhooks or pre-receive hooks.

Now, is this even possible to achieve ? If yes, then where to begin? Do I need knowledge of Rest API? Do I need to write shell scripts?

like image 904
Gauranga Rathod Avatar asked Jul 10 '15 06:07

Gauranga Rathod


People also ask

What is a pre-push hook in Git?

This hook can likewise validate the presence of files external to Git control that you may want copied in when the working tree changes. The pre-push hook runs during git push, after the remote refs have been updated but before any objects have been transferred.

What is a hook in GitHub?

Git hooks are run locally. These hook scripts are only limited by a developer's imagination. Some example hook scripts include: pre-commit: Check the commit message for spelling errors.

What is a pre-receive hook for GitHub Enterprise Server?

You can see examples of pre-receive hooks for GitHub Enterprise Server in the github/platform-samples repository. A pre-receive hook script executes in a pre-receive hook environment on your GitHub Enterprise Server instance. When you create a pre-receive hook script, consider the available input, output, exit status, and environment variables.

What is GitHub webhooks API?

GitHub Pages, Releases, Metrics, Webhooks REST API pages. The webhooks API allows you to create and manage webhooks for your repositories. Repository webhooks allow you to receive HTTP POST payloads whenever certain events happen in a repository. The webhook REST APIs enable you to manage repository, organization, and app webhooks.


Video Answer


2 Answers

This isn't generally the workflow possible with GitHub.
You would rather use a "guarded commits" model with 2 GitHub repo:

  • one for pushing, where you can enable a CI service like, for instance, Travis (or your own CI server),
  • one for valid commits (the ones that passed CI), pushed by Travis (as in this question), and used by developer to sync their repo (pull only, no push)

that's what the requirement is for my project, which can't be changed

In that case, It is best to follow Building a CI server which will:

  • detect the pushes and trigger a compilation
  • push back on dedicated branch for valid comimt (it could be the master branch for instance)

That means the devs should push only to a "dev" branch, monitored by your server, and your CI engine would push those commits to the master branch if the compilation passes.

like image 63
VonC Avatar answered Oct 11 '22 11:10

VonC


It's not possible to do exactly what you're asking for but it's possible to do something that should be close enough.

You can configure GitHub's hooks to invoke your CI server to run a build on every push. When the CI job is started, it should clone the repository and then forcibly push the branch to its previous state. If the build succeeds, push the branch again.

This requires your Jenkins job to have credentials that enable it to write to the repository.

However, you should understand that this method is prone to merge conflicts. It's possible that someone will push to the same branch while the first job is running (or worse, queued). You might have two jobs working on the same branch. Queued jobs are bound to cause problems, the least of which is that the branch will be updated on GitHub until the job runs and someone might pull the changes.

Having said this, my advice is that this workflow is not scalable. A possible alternative is to use protected branches and let your CI jobs merge feature branches into protected branches after successful builds (as long as it's a fast-forward merge).

like image 20
Hosam Aly Avatar answered Oct 11 '22 11:10

Hosam Aly