Jenkins - how to count jenkins job build per state

In this article I would like to explain my view on how to count build filtered by status.

 

You can refer to this article to know how to do a REST call to jenkins. In this case the type of call is something like this:

<JENKINS_URL>/job/<SOMEPIPELINE>/api/json?tree=allBuilds[id,timestamp,duration,result]&pretty=true

the endpoint is evidenced in bold characters.

 

This request retrieve this kind of response:

 

{

  "_class" : "org.jenkinsci.plugins.workflow.job.WorkflowJob",

  "allBuilds" : [

{

      "_class" : "org.jenkinsci.plugins.workflow.job.WorkflowRun",

      "duration" : 837491,

      "id" : "46671",

  "result" : null,

      "timestamp" : 1647202842314

    },

    {

      "_class" : "org.jenkinsci.plugins.workflow.job.WorkflowRun",

      "duration" : 991915,

      "id" : "46670",

  "result" : "SUCCESS",

      "timestamp" : 1647195253529

    },

{

      "_class" : "org.jenkinsci.plugins.workflow.job.WorkflowRun",

      "duration" : 678418,

      "id" : "46669",

      "result" : "UNSTABLE",

      "timestamp" : 1648292021523

    },

    {

      "_class" : "org.jenkinsci.plugins.workflow.job.WorkflowRun",

      "duration" : 646110,

      "id" : "46668",

      "result" : "FAILURE",

      "timestamp" : 1648290252397

    },

    {

      "_class" : "org.jenkinsci.plugins.workflow.job.WorkflowRun",

      "duration" : 615499,

      "id" : "46667",

      "result" : "ABORTED",

      "timestamp" : 1648290014257

    },

    {

      "_class" : "org.jenkinsci.plugins.workflow.job.WorkflowRun",

      "duration" : 538937,

      "id" : "46666",

      "result" : "ABORTED",

      "timestamp" : 1648288902869

    }

  ]

}

 

We can understand, from the json structure, that there are different records with the information requested plus one that is not so important for us.

 

We know that if the duration is 0 the build should be running; in this case the value of the result is "null". In all the other case we can count the records filtered by result state.

 

Now we have to understand how to read json text in vbscript. There isn't any native function in vbscript to read a json structure so we need to think a way to do the job.

 

We can see that the structure is well defined and it is rigid like an xml or other format type. We can see that what I call records (you can think them as objects) are inside a open "[" parenthesis and a close "]" parenthesis, and inside this context, every single item is inside a open "{" parenthesis and a close "}" parenthesis. So we can try to use regular expression within these two patterns:

 

FirstPattern = "\[[\s\S]*?\]" <-- find open "[" and the FIRST close "]"

SecondPattern= "\{[\w\W]*?\}" <-- the same thing for "{ }"

 

In this solution I used also a class to manage the build item. It has only one member, a multidimensional array of 4 rows and n columns.

 

In the code I recreate the respose above in a string variable. Here is the code:

 

'Class to manage all the element of the json file returns from the request to jenkins

Class BuildManager

Private theAllBuildsTag()

 

'Getter

Public Property Get allBld()

        allBld = theAllBuildsTag

    End Property

    

'Setter

    Public Property Let allBld(data)

Dim arrData : arrData = split(data,"|")

Dim Lim1 : Lim1 = Ubound(theAllBuildsTag,2)

 

theAllBuildsTag(0, Lim1) = arrData(0)

theAllBuildsTag(1, Lim1) = arrData(1)

theAllBuildsTag(2, Lim1) = arrData(2)

theAllBuildsTag(3, Lim1) = arrData(3)

Lim1 = Lim1 + 1

 

'Using Preserve option it is possible to modify only last dimension of the multidimensional array

Redim Preserve theAllBuildsTag(3, Lim1)

 

'The matrix will be 4 x buildnumber with:

'at position 0:  the Duration of all the builds

'at position 1:   all the IDs

'at position 2: the Results of all the builds

'at position 3: the Timestamp of all the builds

 

'0,0 - 0,1 - 0,2 - 0,3 ... 0,n = Duration

'1,0 - 1,1 - 1,2 - 1,3 ... 1,n = IDs

'2,0 - 2,1 - 2,2 - 2,3 ... 2,n = Results

'3,0 - 3,1 - 3,2 - 3,3 ... 3,n = Timestamps

 

'so data of the single build must be read in vertical direction not in horizontal direction

 

    End Property

 

    ' Parameterless Constructor

    Public Sub Class_Initialize()

Redim theAllBuildsTag(3, 0)

    End Sub

 

Public Sub Class_Terminate()

End Sub

 

'Function to retrieve the number of Running builds

Public Function NRunningBuild()

Dim intRes : intRes = 0

for i = 0 to Ubound(theAllBuildsTag,2) - 1

 

if theAllBuildsTag(0,i) = "0" then

intRes = intRes + 1

end if

 

next

NRunningBuild = intRes

End Function

 

'Function to retrieve the number of all the build in the state passed as arguments. For Example "SUCCESS", "FAILURE", "ABORTED", etc...

Public Function NStateBuild(state)

Dim intRes : intRes = 0

for i = 0 to Ubound(theAllBuildsTag,2) - 1

if theAllBuildsTag(2,i) = chr(34) & state & chr(34) then

intRes = intRes + 1

end if

next

NStateBuild = intRes

End Function

 

End Class

 

'******************************************************************************************************

'The simulation of a jenkins response and store it in a string variable

'strInp is for a test - it simulate a Jenkins response of:

'<JENKINS_URL>/job/<SOMEPIPELINE>/api/json?tree=allBuilds[id,timestamp,duration,result]&pretty=true

'******************************************************************************************************

dim strInp

strInp = "{" & chr(34) & _

  "_class" & chr(34) & " : " & chr(34) & "org.jenkinsci.plugins.workflow.job.WorkflowJob" & chr(34) & "," & chr(34) & _

  "allBuilds" & chr(34) & " : [ " & _

"{" & _

      chr(34) & "_class" & chr(34) & " : " & chr(34) & "org.jenkinsci.plugins.workflow.job.WorkflowRun" & chr(34) & "," & _

      chr(34) & "duration" & chr(34) & " : 0," & _

      chr(34) & "id" & chr(34) & " : " & chr(34) & "46671" & chr(34) & "," & _

  chr(34) & "result" & chr(34) & " : null," & _ 

      chr(34) & "timestamp" & chr(34) & " : 1647202842314" & _

    "}," & _

    "{" & _

      chr(34) & "_class" & chr(34) & " : " & chr(34) & "org.jenkinsci.plugins.workflow.job.WorkflowRun" & chr(34) & "," & _

      chr(34) & "duration"  & chr(34) & " : 991915," & _

      chr(34) & "id" & chr(34) & " : " & chr(34) & "46670" & chr(34) & "," & _ 

  chr(34) & "result" & chr(34) & " : " & chr(34) & "SUCCESS" & chr(34) & "," & _ 

      chr(34) & "timestamp" & chr(34) & " : 1647195253529" & _

    "}," & _

"{" & _

      chr(34) & "_class" & chr(34) & " : " & chr(34) & "org.jenkinsci.plugins.workflow.job.WorkflowRun" & chr(34) & "," & _

      chr(34) & "duration"  & chr(34) & " : 678418," & _

      chr(34) & "id" & chr(34) & " : " & chr(34) & "46669" & chr(34) & "," & _ 

      chr(34) & "result" & chr(34) & " : " & chr(34) & "UNSTABLE" & chr(34) & "," & _ 

      chr(34) & "timestamp" & chr(34) & " : 1648292021523" & _

    "}," & _

"{" & _

      chr(34) & "_class" & chr(34) & " : " & chr(34) & "org.jenkinsci.plugins.workflow.job.WorkflowRun" & chr(34) & "," & _

      chr(34) & "duration"  & chr(34) & " : 646110," & _

      chr(34) & "id" & chr(34) & " : " & chr(34) & "46668" & chr(34) & "," & _ 

      chr(34) & "result" & chr(34) & " : " & chr(34) & "FAILURE" & chr(34) & "," & _

      chr(34) & "timestamp" & chr(34) & " : 1648290252397" & _

    "}," & _

"{" & _

      chr(34) & "_class" & chr(34) & " : " & chr(34) & "org.jenkinsci.plugins.workflow.job.WorkflowRun" & chr(34) & "," & _

      chr(34) & "duration"  & chr(34) & " : 615499," & _

      chr(34) & "id" & chr(34) & " : " & chr(34) & "46667" & chr(34) & "," & _

      chr(34) & "result" & chr(34) & " : " & chr(34) & "ABORTED" & chr(34) & "," & _

      chr(34) & "timestamp" & chr(34) & " : 1648290014257" & _

    "}," & _

"{" & _

      chr(34) & "_class" & chr(34) & " : " & chr(34) & "org.jenkinsci.plugins.workflow.job.WorkflowRun" & chr(34) & "," & _

      chr(34) & "duration"  & chr(34) & " : 538937," & _

      chr(34) & "id" & chr(34) & " : " & chr(34) & "46666" & chr(34) & "," & _

      chr(34) & "result" & chr(34) & " : " & chr(34) & "ABORTED" & chr(34) & "," & _

      chr(34) & "timestamp" & chr(34) & " : 1648288902869" & _

    "}" & _

  "]" & _

"}"

'******************************************************************************************************

' here is the MAIN that is only a series of call to the AnalyzeBuild sub 

' to returns different number of builds filter by status

'******************************************************************************************************

AnalyzeBuild strInp, "RUNNING"

AnalyzeBuild strInp, "SUCCESS"

AnalyzeBuild strInp, "UNSTABLE"

AnalyzeBuild strInp, "FAILURE"

AnalyzeBuild strInp, "ABORTED"

' end of the MAIN

'******************************************************************************************************

 

'******************************************************************************************************

' the SUB that do the job

'******************************************************************************************************

Sub AnalyzeBuild(inpJson, state)

 

dim FirstPattern : FirstPattern = "\[[\s\S]*?\]"

dim SecondPattern: SecondPattern= "\{[\w\W]*?\}"

dim regEx : set regEx = CreateObject("VBScript.RegExp")

dim regEx2 : set regEx2 = CreateObject("VBScript.RegExp")

dim myRec, arrElements, dur, idR, resR, tmstmpR

dim oBM

with regEx

.Pattern = FirstPattern

.IgnoreCase = True

.Global = True

end with

 

if regEx.Test(inpJson) then

set colMatch = regEx.Execute(inpJson)

if colMatch.Count > 0 then

with regEx2

.Pattern = SecondPattern

.IgnoreCase = true

.Global = true

end with

if regEx2.Test(colMatch.Item(0).Value) then

set oBM = new BuildManager

set mtch2 = regEx2.Execute(colMatch.Item(0).Value)

if mtch2.Count > 0 then

for j=0 to mtch2.Count-1

myRec = mtch2.Item(j).Value

arrElements = split(myRec, ",")

 

dur = split(arrElements(1)," : ")(1)

idR = split(arrElements(2)," : ")(1)

resR = split(arrElements(3)," : ")(1)

tmstmpR = left(split(arrElements(4)," : ")(1), len(split(arrElements(4)," : ")(1)) - 1)

 

oBM.allBld = dur & "|" & idR & "|" & resR & "|" & tmstmpR

 

next

end if

end if

end if

end if

 

Select Case state

case "RUNNING":

msgbox "The number of RUNNING builds are: " & oBM.NRunningBuild

 

case else:

msgbox "The number of " & state & " builds are: " & oBM.NStateBuild(state)

 

End Select

 

End Sub

 

'******************************************************************************************************

 

This code could be copied, saved as vbs file and executed. It will show you the number of the builds filtered by state.

 

 

Pag: <<   <