Jenkins – Poor man’s Gitlab CE and Jenkins integration

gitlabJenkins

UPDATE
The script in the answer is obsolete now, since Gitlab plugin for Jenkins can now report build status back to Jenkins.

I'm trying to integrate Gitlab CE 8.4 and Jenkins. I've read that Jenkins CI integration is available in Gitlab EE, but currently its not an option.

I've already set up Jenkins gitlab plugin and Web hooks, and pushes to my repo trigger builds of Jenkins jobs.
However, these builds are not shown in the 'Builds' tab in the respective Gitlab page.
If I commit .gitlab-ci.yml file to the repository, web hooks still work, Jenkins jobs run, but the 'Builds' page shows that the build is stuck, since no runners are defined.

Indeed, I haven't set up any Gitlab CI runners, since they are not related to Jenkins, as far as I understand.

I'd like to keep my Jenkins job since some useful information is published there, and I also would like to have its status on the Gitlab page.
I'm thinking in this regard about a simple script for Gitlab CI runner, that would capture console output from a Jenkins job and translate it to Gitlab. Something like running wget or curl, because Jenkins provides API to see job's output.

However, documentation about Gitlab CI and .gitlab-ci.yml is limited, as well as examples.

How could I write that job file?
Am I right in thinking that Gitlab receives job's stdout?

Best Answer

Yes, Gitlab-CI prints stdout of a job and relates on exit codes.

My solution consists of installed Gitlab-CI runner and the python script, called from .gitlab-ci.yml, that gets git commit ID from CI_BUILD_REF environment variable, connects to the Jenkins host, finds respective build console, reads the output via urllib2.urlopen(...).readlines(), and prints it to stdout.

It uses bySHA1 url, provided by the Jenkins Git plugin, to find the build console.

The script also looks for the line, starting with the word Finished: and exits with the exit code, according to what follows that word: 0 if it is SUCCESS, and 1 if FAILURE, or UNSTABLE.

Script text:

import urllib2
import os
import sys
import time

TIMEOUT = 5

def get_build_console_for_sha1(url, sha1):
    return '{}/scm/bySHA1/{}/consoleText'.format(url, sha1)


def parse_console(build_con):
    retcode = 0

    if build_con:
        total_read_lines = 0
        finished_line = None

        while not finished_line:
            current_read_lines = 0
            try:
                for line in urllib2.urlopen(build_con, 
                                             None, TIMEOUT).readlines():
                    current_read_lines += 1
                    if current_read_lines >= total_read_lines:
                        print line,
                        total_read_lines += 1
                        sys.stdout.flush()
                        if line.startswith('Finished: '):
                            finished_line = line
            except urllib2.HTTPError as e:
                if e.code == 404:
                    time.sleep(2)
                    pass

        if 'FAILURE' in finished_line or 'UNSTABLE' in finished_line:
            retcode = 1

    print "retcode = ", retcode
    return retcode


def main():
    URL = 'JENKINS_JOB_URL'
    sha1 = os.getenv('CI_BUILD_REF')
    bc = get_build_console_for_sha1(URL, sha1)
    return parse_console(bc)


if __name__ == '__main__' :
    sys.exit(main())

And in addition, .gitlab-ci.yml:

jenkins-translate:
  script: 
    - python jenkins-translate.py

Drawbacks are obvious: pressing cancel button actually cancels the translation, not the Jenkins job, no clickable links to the Jenkins job page.

At least it informs about Jenkins job statuses.

UPDATE. This script does not authorize to Jenkins, it assumes relaxed security setting, when everyone can see job output.

UPDATE2. Jenkins-Gitlab plugin can now report build status back to Gitlab, which obsoletes this script.