Read in Results of Jenkins

Jenkins is an automation server for building, deploying and automating software deployment and test.
It can be useful, to read in results in OpenHAB, maybe you want to turn on the candy maker when all tests pass?

Architecture
Jenkins provides a JSON interface with all / specialized test results we can read in.
I use a Item to store raw JSON string, and if this changes (= at least one test result changed), I trigger a rule to parse the values.

OpenHAB Prerequisites
OpenHAB: Version 2.3.0 or newer (could be adapted to older versions by not using Units Of Measurement in items definition)
Bindings: http1
Transformations: RegEx, Map

OpenHAB Configuration
rules/jenkins.rules

rule "Update Jenkins Status"
when
    Item Debug_Trigger_Jenkins_Update changed to ON or
    Item Jenkins_json changed
then
    var jenkinsJobsCountSuccessful = 0
    var jenkinsJobsCountFailed = 0
    var jenkinsJobsCount = 0

    //logInfo("jenkins.rules", "Update Jenkins Status rule triggered")

    jenkinsJobsCount = Integer.parseInt(transform("JSONPATH", "$.jobs.length()", Jenkins_json.state.toString))
    //logInfo("jenkins.rules", "found " + jenkinsJobsCount + " jobs")

    val currentJob = 0
    val currentJobResult_string = ""
    val currentJobResult_integer = 0
    try {
        while (currentJob < jenkinsJobsCount) {

            currentJobResult_string = transform("JSONPATH", "$.jobs[" + currentJob + "].color", Jenkins_json.state.toString)
            currentJobResult_integer = transform("MAP", "jenkins.map", currentJobResult_string)

            //logInfo("jenkins.rules", "Job " + currentJob + " result: " + currentJobResult_string + " => " + currentJobResult_integer)

            // map transforms to strings, so compare with strings
            if(currentJobResult_integer == "1") {
                jenkinsJobsCountSuccessful += 1
            }
            if(currentJobResult_integer == "0") {
                jenkinsJobsCountFailed += 1
            }

            currentJob += 1
        }
    }
    catch(Throwable t) {
        logError("jenkins.rules", "Some bad stuff happened in my rule: " + T.toString)
    }
    finally {
        Jenkins_Successful_Percent.postUpdate(jenkinsJobsCountSuccessful * 100.0 / (jenkinsJobsCountSuccessful + jenkinsJobsCountFailed))
        Jenkins_Job_Count.postUpdate(jenkinsJobsCount)
        Jenkins_Job_Failed.postUpdate(jenkinsJobsCountFailed)
        Jenkins_Job_Successful.postUpdate(jenkinsJobsCountSuccessful)
        logInfo("jenkins.rules", "found " + jenkinsJobsCount + " jobs, " + jenkinsJobsCountSuccessful + " of them successful (" + Jenkins_Successful_Percent.state.toString + ")")
    }

    if(Debug_Trigger_Jenkins_Update.state == ON) { Debug_Trigger_Jenkins_Update.postUpdate(OFF) }
end

This rule depends on:

services/http.cfg

jenkinsCache.url=https://amplab.cs.berkeley.edu/jenkins/api/json
jenkinsCache.updateInterval=60000

Use your own Jenkins URL here.
This can be the main URL to Jenkins or the URL of a view (each appended with api/json). Caution: URL of a view changes when view name gets changed!

items/jenkins.items

Switch Debug_Trigger_Jenkins_Update
String Jenkins_json "Raw JSON Value of Jenkins result" { http="<[jenkinsCache:60000:REGEX((.*))]" }

Number Jenkins_Job_Count "Jenkins Job Count [%s]"
Number Jenkins_Job_Successful "Jenkins Job Successful [%s]"
Number Jenkins_Job_Failed "Jenkins Job Failed [%s]"

Number:Dimensionless Jenkins_Successful_Percent "Jenkins Successful Jobs [%.2f %%]"

I use REGEX((.*)) transformation to put all content into the string. Currently there’s no other solution for that.

transform/jenkins.map

aborted=-1
aborted_anime=-1
blue=1
blue_anime=1
disabled=-1
disabled_anime=-1
grey=-1
grey_anime=-1
notbuilt=-1
notbuilt_anime=-1
red=0
red_anime=0
yellow=0
yellow_anime=0

I just care for good (green/blue) and bad (red) tests, so I map it accordingly. Could be more detailed if needed.

Have fun :slight_smile:
Questions and suggestions for improvement are welcome!

3 Likes

Maybe you could also use the MQTT notification plugin?

https://wiki.jenkins.io/display/JENKINS/MQTT+Notification+Plugin

Interestingly enough, I am just playing around with having Jenkins notify me of broken builds by flashing my Hue lamps :grin:

Thanks! To be notified immediately, that would be the better way to go, you are correct.
I decided on JSON API solution because I’m not the admin of this Jenkins server and so not having to change the server (except of adding a view for the tests to be visualized) was a huge advantage.

At some point I have to keep track of “are jobs X and Y green?”
With MQTT that logic would be on OpenHAB side, because I only get updates.
With JSON API I just can fetch the result again, calculate what I need, and forget the rest.