(1 comment)

Jenkins CI is a great tool for continuous integration - it allows running tests, executing nightly builds of your code or any other kind of repetitive tasks. It offers a nice web UI to it's users, through which they can edit or add new jobs. It is, definetly, a must-have software for all kind of developers.

Imagine now situation when Job's configuration needs to be portable, quick (re)deployable and collaborable between other developers. With such requirements a sharing problem might arise, especially when having lots of already defined jobs. What you could do is to consider defining jobs in an easy readable file format first, and keep them, up-to-date, in your precious GIT repository, to which other devs will have access. Then, with a dedicated cmd tool you could parse job's definition and update/add it to the Jenkins instance just within few seconds. Sounds reasonable? Then this is where the Jenkins Job Builder (JJB) is worth looking at.


Installation

JJB requires six, PyYAML and python-jenkins pkgs to work. Use pip to install JJB, which will also take care of these dependencies.

# pip install jenkins-job-builder


Example & Usage

First we will start with defining a Job using YAML syntax. Lets create a file named my_first_job.yaml with the below content.

# File: jobs/my_first_job.yaml
- job:
# Specify your job name.
    name: my_first_job
    builders:
      - shell:
          !include-raw './scripts/my_first_job.sh'
    description: 'This is my first Jenkins Job defined in YAML file format.'
    # Node's label
node: my_first_job_label
# Define Vars used by the shell script; assign them default values.
    parameters:
        - string:
            name: MESSAGE
            default: 'Free Hello for all.'
        - string:
            name: MAX_COUNT
            default: '3'
# Automatically start (trigger) the job's build at 12:00 and 15:00 on every day.
    triggers:
        - timed: '0 12,15 * * *'
    wrappers:
      - timeout:
          fail: true
# Timeout job after 120 seconds of its execution. If timeout happens = fail the build.
          timeout: 2

Next, fill job's script shell, which will be executed on job's build, with the following:

#!/bin/bash
#
# File: jobs/scripts/my_first_job.sh
#

# Enable 'debug' mode.
set -ex

COUNT=0

while [[ ${COUNT} -lt ${MAX_COUNT} ]]; do
    echo ${MESSAGE}
    sleep 1
    COUNT=$((COUNT+1))
done

exit 0

Lastly you need to specify username and password in config file, which JJB will use while accessing Jenkins' HTTP API. In my case Jenkins is accessible under localhost, port 8080.

# File: jenkins_job.ini
[jenkins]
user=admin
password=admin
url=http://localhost:8080/

Configs done. Deploy -  add a new job (or update existing one) by execing the below cmd.

$ jenkins-jobs --conf jenkins_job.ini -l DEBUG update jobs/ my_first_job 

where "jobs/" is a relative path to directory (kind of a search path), which holds my_first_job.yaml file. Last parameter is our job's name.

As a result you should get lots of output ending with:

INFO:jenkins_jobs.builder:Creating jenkins job my_first_job
INFO:jenkins_jobs.builder:Cache saved

If so - success! Now in Jenkins UI you should see on the list newly created task.

Below is an output of successfully executed job's build.

Started by timer
Building on master in workspace /var/lib/jenkins/jobs/my_first_job/workspace
[workspace] $ /bin/bash /tmp/hudson9196219744193638273.sh
+ COUNT=0
+ [[ 0 -lt 3 ]]
+ echo Free Hello for all.
Free Hello for all.
+ sleep 1
+ COUNT=1
+ [[ 1 -lt 3 ]]
+ echo Free Hello for all.
Free Hello for all.
+ sleep 1
+ COUNT=2
+ [[ 2 -lt 3 ]]
+ echo Free Hello for all.
Free Hello for all.
+ sleep 1
+ COUNT=3
+ [[ 3 -lt 3 ]]
+ exit 0
Finished: SUCCESS

Note, that Started by timer indicates, that Job has been automatically triggered, as it has been specified in jobs config.

For detailed infor about Jenkins Job Builder please have a look into it's documentation.

Current rating: 5

Comments

Ram 3 years, 10 months ago

Really nice article.

Link | Reply
Currently unrated

New Comment

required

required (not published)

optional