136

How to trigger a build remotely from Jenkins?
How to configure Git post commit hook?

My requirement is whenever changes are made in the Git repository for a particular project it will automatically start Jenkins build for that project.

In Jenkins trigger build section I selected trigger build remotely.
In .git directory, hooks directory is there in that we have to configure post commit file.
I am confusing how to trigger a build from there (I know some part we should use curl command).


curl cmbuild.aln.com/jenkins/view/project name/job/myproject/buildwithparameters?Branch=feat-con

I have placed this command in my git server hooks directory (post commit hook).
Whenever the changes happen in repository it is running automate build.

I want to check in changeset whether in at least one java file is there the build should start.
Suppose the developers changed only xml files or property files the build should not start.
Along with xml, suppose the .java files is there the build should start.

Cœur
  • 37,241
  • 25
  • 195
  • 267
phanikumar Raja
  • 1,539
  • 3
  • 14
  • 18

4 Answers4

173

As mentioned in "Polling must die: triggering Jenkins builds from a git hook", you can notify Jenkins of a new commit:

With the latest Git plugin 1.1.14 (that I just release now), you can now do this more >easily by simply executing the following command:

curl http://yourserver/jenkins/git/notifyCommit?url=<URL of the Git repository>

This will scan all the jobs that’s configured to check out the specified URL, and if they are also configured with polling, it’ll immediately trigger the polling (and if that finds a change worth a build, a build will be triggered in turn.)

This allows a script to remain the same when jobs come and go in Jenkins.
Or if you have multiple repositories under a single repository host application (such as Gitosis), you can share a single post-receive hook script with all the repositories. Finally, this URL doesn’t require authentication even for secured Jenkins, because the server doesn’t directly use anything that the client is sending. It runs polling to verify that there is a change, before it actually starts a build.

As mentioned here, make sure to use the right address for your Jenkins server:

since we're running Jenkins as standalone Webserver on port 8080 the URL should have been without the /jenkins, like this:

http://jenkins:8080/git/notifyCommit?url=git@gitserver:tools/common.git

To reinforce that last point, ptha adds in the comments:

It may be obvious, but I had issues with:

curl http://yourserver/jenkins/git/notifyCommit?url=<URL of the Git repository>. 

The url parameter should match exactly what you have in Repository URL of your Jenkins job.
When copying examples I left out the protocol, in our case ssh://, and it didn't work.


You can also use a simple post-receive hook like in "Push based builds using Jenkins and GIT"

#!/bin/bash
/usr/bin/curl --user USERNAME:PASS -s \

http://jenkinsci/job/PROJECTNAME/build?token=1qaz2wsx

Configure your Jenkins job to be able to “Trigger builds remotely” and use an authentication token (1qaz2wsx in this example).

However, this is a project-specific script, and the author mentions a way to generalize it.
The first solution is easier as it doesn't depend on authentication or a specific project.


I want to check in change set whether at least one java file is there the build should start.
Suppose the developers changed only XML files or property files, then the build should not start.

Basically, your build script can:

  • put a 'build' notes (see git notes) on the first call
  • on the subsequent calls, grab the list of commits between HEAD of your branch candidate for build and the commit referenced by the git notes 'build' (git show refs/notes/build): git diff --name-only SHA_build HEAD.
  • your script can parse that list and decide if it needs to go on with the build.
  • in any case, create/move your git notes 'build' to HEAD.

May 2016: cwhsu points out in the comments the following possible url:

you could just use curl --user USER:PWD http://JENKINS_SERVER/job/JOB_NAME/build?token=YOUR_TOKEN if you set trigger config in your item

http://i.imgur.com/IolrOOj.png


June 2016, polaretto points out in the comments:

I wanted to add that with just a little of shell scripting you can avoid manual url configuration, especially if you have many repositories under a common directory.
For example I used these parameter expansions to get the repo name

repository=${PWD%/hooks}; 
repository=${repository##*/} 

and then use it like:

curl $JENKINS_URL/git/notifyCommit?url=$GIT_URL/$repository
Cœur
  • 37,241
  • 25
  • 195
  • 267
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • hi von as you said on first call i have to put a build notes.my first call is to read .java file whenever the developer push the changes in to git repo. i am new to all these things thats why i am asking each and every step. please don't mind and i have to complete this task. – phanikumar Raja Oct 12 '12 at 14:27
  • I had to add the curl call to the post-receive file, which isn't totally clear from this answer. Very helpful anyway! – Magnilex Jan 08 '13 at 10:06
  • Where do you put that bash script for the post-receive hook? I haven't found where in Jenkins to store that... – IgorGanapolsky Jan 30 '14 at 18:24
  • 1
    @IgorGanapolsky in the hooks folder of your bare repo which is receiving commits and which has to call jenkins: `yourRepo.git/hooks/post-receive` – VonC Jan 30 '14 at 19:36
  • 2
    It may be obvious, but I had issues with: `curl http://yourserver/jenkins/git/notifyCommit?url=`. The **url** parameter should match exactly what you have in **Repository URL** of your Jenkins job. When copying examples I left out the protocol, in our case **ssh://** and it didn't work. – ptha Jul 16 '15 at 16:35
  • @ptha Good point. I have included your comment in the answer for more visibility. – VonC Jul 16 '15 at 17:55
  • In latest jenkins, I think you could just use `curl --user USER:PWD http://JENKINS_SERVER/job/JOB_NAME/build?token=YOUR_TOKEN` if you set trigger config in your item. – cwhsu May 04 '16 at 07:37
  • @cwhsu sounds great! Do you have a link to a documentation illustrating that? – VonC May 04 '16 at 07:40
  • @VonC I think it is there by default. I take a screenshot. Check http://imgur.com/IolrOOj – cwhsu May 06 '16 at 04:09
  • @cwhsu Nice! I have included your comment in the answer for more visibility. – VonC May 06 '16 at 04:59
  • Great answer! I found the git plugin method to be the most versatile one. I wanted to add that with just a little of shell scripting you can avoid manual url configuration, especially if you have many repositories under a common directory. For example I used these parameter expansions to get the repo name `repository=${PWD%/hooks}; repository=${repository##*/}` and the use it like `curl $JENKINS_URL/git/notifyCommit?url=$GIT_URL/$repository` – polaretto May 13 '16 at 10:34
  • @polaretto Well done. I have included your comment in the answer for more visibility. – VonC May 13 '16 at 11:00
  • So if there are multiple Jenkins jobs set up with the same Git URL, will they all get triggered? How can the API be job specific? – Chris F Mar 01 '18 at 19:00
  • @ChrisF That would be the last part of the answer: `curl --user USER:PWD http://JENKINS_SERVER/job/JOB_NAME/build?token=YOUR_TOKEN`. The first part is *not* job-specific. – VonC Mar 01 '18 at 20:07
  • For me $JENKINS_URL and $GIT_URL prints empty. Any idea why? Tried post-receive and post-update hooks - both seems to have empty global parameters.. – Paulius Vindzigelskis Jul 12 '18 at 20:33
  • @PauliusVindzigelskis It might depend on the exact account used for those commands: a variable environment might be defined for one account, empty for another. – VonC Jul 12 '18 at 20:35
  • Is it possible that the hook checks in which folder of the repository the change was made before triggering the build ? – aymen0406 Jan 20 '22 at 22:50
  • @aymen0406 If this is you who is notifying Jenkins through a `curl $JENKINS_URL/git/notifyCommit?url=$GIT_URL/$repository` call, the folder check would be done on your side, not on the Jenkins Git plugin side. – VonC Jan 20 '22 at 23:18
  • @VonC Actually i was wondering if the check of the folder and the execution of curl command could be done on the post-receive hook so that the Jenkins notification would be automated and it won't trigger unnecessary builds – aymen0406 Jan 21 '22 at 00:48
  • @aymen0406 OK. I believe it is possible: https://stackoverflow.com/a/66890675/6309 – VonC Jan 21 '22 at 07:35
19

Hope this helps: http://nrecursions.blogspot.in/2014/02/how-to-trigger-jenkins-build-on-git.html

It's just a matter of using curl to trigger a Jenkins job using the git hooks provided by git.
The command

curl http://localhost:8080/job/someJob/build?delay=0sec

can run a Jenkins job, where someJob is the name of the Jenkins job.

Search for the hooks folder in your hidden .git folder. Rename the post-commit.sample file to post-commit. Open it with Notepad, remove the : Nothing line and paste the above command into it.

That's it. Whenever you do a commit, Git will trigger the post-commit commands defined in the file.

Gottlieb Notschnabel
  • 9,408
  • 18
  • 74
  • 116
Nav
  • 19,885
  • 27
  • 92
  • 135
  • After doing commit from the dev machine, post-receive gets called, not post-commit. Verified by putting log statements in both the hooks. Am I reading the docs wrong, should it not be be post-commit which gets called? – Shirish Hirekodi Apr 29 '15 at 08:40
  • @Shirish: Thats strange. Perhaps you are doing something differently – Nav Apr 30 '15 at 16:39
  • this is build successfully when i have push last change commit but not build when i commit changes...??? –  Aug 01 '16 at 13:29
3

As the previous answer did show an example of how the full hook might look like here is the code of my working post-receive hook:

#!/usr/bin/python

import sys
from subprocess import call

if __name__ == '__main__':
    for line in sys.stdin.xreadlines():
        old, new, ref = line.strip().split(' ')
        if ref == 'refs/heads/master':
            print "=============================================="
            print "Pushing to master. Triggering jenkins.        "
            print "=============================================="
            sys.stdout.flush()
            call(["curl", "-sS", "http://jenkinsserver/git/notifyCommit?url=ssh://user@gitserver/var/git/repo.git"])

In this case I trigger jenkins jobs only when pushing to master and not other branches.

Zitrax
  • 19,036
  • 20
  • 88
  • 110
  • 1
    How do you tie this Python script into Jenkins? Or do you just run it one time? – IgorGanapolsky Jan 30 '14 at 15:52
  • Jenkins does not know about this hook, the main part is loading the notifyCommit url on the jenkins server which will trigger a poll. I think the polling is enabled but without a schedule on the jenkins side. – Zitrax Jan 30 '14 at 22:44
  • So where does this python script reside? I assume you tie it in with your git installation to track commits... – IgorGanapolsky Jan 31 '14 at 14:33
  • 1
    Late answer - but the script location would be on the git server in hooks/post-receive. Read up on git hooks to learn more. – Zitrax Mar 06 '14 at 08:41
3

I want to add to the answers above that it becomes a little more difficult if Jenkins authorization is enabled.

After enabling it I got an error message that anonymous user needs read permission.

I saw two possible solutions:

1: Changing my hook to:

curl --user name:passwd -s http://domain?token=whatevertokenuhave

2: setting project based authorization.

The former solutions has the disadvantage that I had to expose my passwd in the hook file. Unacceptable in my case.

The second works for me. In the global auth settings I had to enable Overall>Read for Anonymous user. In the project I wanted to trigger I had to enable Job>Build and Job>Read for Anonymous.

This is still not a perfect solution because now you can see the project in Jenkins without login. There might be an even better solution using the former approach with http login but I haven't figured it out.

anhoppe
  • 4,287
  • 3
  • 46
  • 58