Post-Commit Hook to trigger automatic Jenkins Build

I know that there are many similar postings, but I have not found a solution, and the advice and solutions presented in the other posts don’t quite jive with what I’m seeing.

The scenario is pretty darn simple: I have a project in Eclipse, and when I check-in changes from that project to our Subversion server (i.e., VisualSVN Server 2.5.3), I want our Jenkins continuous integration server (i.e., Jenkins 1.546) to pick up this change and kick off a new build. I do not want to poll from Jenkins.

  • Recommended continuous integeration system for Git?
  • Development workflow with Jenkins + Git + Crucible + Jira?
  • Adhering to git flow rules while taking the App Store review times into account
  • Jenkins & GitHub - Builds are not being triggered on push
  • Host key verification failed Xcode with Mavericks Server
  • Have buildbot poll a git repository for new commits?
  • I’ve been mostly following the steps in this article. Here’s my post-commit hook script:

    repos   = WScript.Arguments.Item(0)
    rev     = WScript.Arguments.Item(1)
    svnlook = WScript.Arguments.Item(2)
    jenkins = WScript.Arguments.Item(3)
    
    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objFile = objFSO.CreateTextFile("C:\Program Files (x86)\VisualSVN Server\log.txt")
    
    objFile.Writeline "repos=" & repos
    objFile.Writeline "rev=" & rev
    objFile.Writeline "svnlook=" & svnlook
    objFile.Writeline "jenkins=" & jenkins
    
    Set shell = WScript.CreateObject("WScript.Shell")
    
    Set uuidExec = shell.Exec(svnlook & " uuid " & repos)
    Do Until uuidExec.StdOut.AtEndOfStream
      uuid = uuidExec.StdOut.ReadLine()
    Loop
    
    objFile.Writeline "uuid=" & uuid
    
    Set changedExec = shell.Exec(svnlook & " changed --revision " & rev & " " & repos)
    Do Until changedExec.StdOut.AtEndOfStream
      changed = changed + changedExec.StdOut.ReadLine() + Chr(10)
    Loop
    objFile.Writeline "changed=" & changed
    
    url = jenkins + "crumbIssuer/api/xml?xpath=concat(//crumbRequestField,"":"",//crumb)"
    Set http = CreateObject("Microsoft.XMLHTTP")
    http.open "GET", url, False
    http.setRequestHeader "Content-Type", "text/plain;charset=UTF-8"
    http.send
    crumb = null
    
    objFile.Writeline "rev url=" & url
    objFile.Writeline "http.status=" & http.status
    objFile.Writeline "http.responseText=" & http.responseText
    
    if http.status = 200 then
      crumb = split(http.responseText,":")
    end if
    
    url = jenkins + "subversion/" + uuid + "/notifyCommit?rev=" + rev + "&token=pinkfloyd65"
    objFile.Writeline "url=" & url
    
    if not isnull(crumb) then 
        objFile.Writeline "crumb(0)=" & crumb(0)
        objFile.Writeline "crumb(1)=" & crumb(1)
    end if
    
    if isnull(crumb) then 
        objFile.Writeline "crumb=null"
    end if
    
    Set http = CreateObject("Microsoft.XMLHTTP")
    http.open "POST", url, False
    http.setRequestHeader "Content-Type", "text/plain;charset=UTF-8"
    if not isnull(crumb) then 
      http.setRequestHeader crumb(0),crumb(1)
      http.send changed
      if http.status <> 200 then
        objFile.Writeline "Error. HTTP Status: " & http.status & ". Body: " & http.responseText
      end if
    
      if http.status = 200 then
        objFile.Writeline "HTTP Status: " & http.status & ".\n Body: " & http.responseText
      end if
    end if
    

    The issue is that, although the POST command above ends up getting a 200 response back, the job never kicks off. Nothing ends up happening. Alright, so let’s check the Jenkins job configuration; maybe I’m missing a setting or something. Well, under the Build Triggers section, I’ve checked the option for “Trigger builds remotely (e.g., from scripts)” and I’ve supplied an authentication token as well. But, the directions underneath that section look different from what I’ve been doing:

    Use the following URL to trigger build remotely: JENKINS_URL/job/<job-name>/build?token=TOKEN_NAME or /buildWithParameters?token=TOKEN_NAME
    Optionally append &cause=Cause+Text to provide text that will be included in the recorded build cause.

    So, it seems like there’s a delta between the sets of instructions I’m seeing, and I’m not sure how to bridge that gap. It seems pretty obvious to follow the instructions on the Jenkins job configuration page, except that I don’t know how I’d get the job name, rather than the UUID.

    Another thing to note is my repository setup. Since the CI server is used by many groups and departments, I thought I’d be all smart and create a top-level repository to house just my department’s projects. So, I have a setup something like:

    VisualSVN Server  
      -- Repositories  
         -- Project_A  
         -- Project_B  
         -- <my-department>  
            -- DepartmentProject_A  
            -- DepartmentProject_B  
    

    I’m wondering if the repository structure is adding to my issues here, but I feel like I should be able to find out which specific repository any changes came from. If that were true, then I could adjust my script to use the job name, rather than UUID, and then follow the explicit instructions seen on my CI server’s configuration page. When I log the incoming repos variable in my vbs script, it points to the top-level department repository, rather than the project’s child repository (i.e., D:\<visual-svn-repos>\<my-department> rather than D:\<visual-svn-repos>\<my-department>\DepartmentProject_B).

    Any help would be greatly appreciated, thanks guys.

  • Configure Jenkins 2.0 with Ansible
  • Obtain Subversion Revision from Previous Jenkins Build
  • How to invoke Ant in Jenkins pipeline job using groovy script?
  • How to set Artifactory discardOldBuilds to true in a Jenkinsfile?
  • Jenkins Cron Expression Not Scheduled at Right time
  • Why can't this Powershell command be executed within Jenkins?
  • 2 Solutions collect form web for “Post-Commit Hook to trigger automatic Jenkins Build”

    The article you linked says

    Jobs on Jenkins need to be configured with the SCM polling option to
    benefit from this behavior. This is so that you can have some jobs
    that are never triggered by the post-commit hook (in the
    $REPOSITORY/hooks directory), such as release related tasks, by
    omitting the SCM polling option. The configured polling can have any
    schedule (probably infrequent like monthly or yearly). The net effect
    is as if polling happens out of their usual cycles.

    and

    For this to work, your Jenkins has to allow anonymous read access
    (specifically, “Job > Read” access) to the system. If access control
    to your Jenkins is more restrictive, you may need to specify the
    username and password, depending on how your authentication is
    configured.

    Does you server meets this restrictions?

    I tried to get the svn plugin examples to work, but no luck. Instead I used the build token root plugin and this works without having to poll.

    https://wiki.jenkins-ci.org/display/JENKINS/Build+Token+Root+Plugin

    Build Triggers > Trigger builds remotely option > give it a token

    On VisualSVN server add this to the post-commit hook:

    SET CSCRIPT=%windir%\system32\cscript.exe
    SET VBSCRIPT=C:\Repositories\post-commit-hook-jenkins.vbs
    "%CSCRIPT%" "%VBSCRIPT%" "MyJobName" "MyTokenFromBuildTrigger"
    

    For post-commit-hook-jenkins.vbs:

    Set args = WScript.Arguments
    JobName = args.Item(0)
    Token = args.Item(1)
    
    'URL to open....
    sUrl = "http://MyJenkinsServer.MyCompany.com/buildByToken/build?job=" + JobName + "&token=" + Token
    'POST Request to send.
    sRequest = ""
    
    HTTPPost sUrl, sRequest
    
    Function HTTPPost(sUrl, sRequest)
      set oHTTP = CreateObject("Microsoft.XMLHTTP")
      oHTTP.open "POST", sUrl,false
      oHTTP.setRequestHeader "Content-Type", "application/x-www-form-urlencoded"
      oHTTP.setRequestHeader "Content-Length", Len(sRequest)
      oHTTP.send sRequest
      HTTPPost = oHTTP.responseText
     End Function 
    
    Git Baby is a git and github fan, let's start git clone.