@@ -50,15 +50,24 @@ const PR_TREE =
5050const COMMIT_TREE =
5151 `result,url,number,${ ACTION_TREE } ,${ CHANGE_TREE } ,builtOn,` +
5252 `subBuilds[${ BUILD_FIELDS } ]` ;
53+ const CITGM_MAIN_TREE =
54+ `result,url,number,${ ACTION_TREE } ,${ CHANGE_TREE } ,builtOn` ;
55+
5356// com.tikal.jenkins.plugins.multijob.MultiJobBuild
5457const FANNED_TREE =
5558 `result,url,number,subBuilds[phaseName,${ BUILD_FIELDS } ]` ;
59+
5660// hudson.matrix.MatrixBuild
5761const BUILD_TREE = 'result,runs[url,number,result],builtOn' ;
5862const LINTER_TREE = 'result,url,number,builtOn' ;
5963const CAUSE_TREE = 'upstreamBuild,upstreamProject,shortDescription,_class' ;
6064const RUN_TREE = `actions[causes[${ CAUSE_TREE } ]],builtOn` ;
6165
66+ // hudson.tasks.test.MatrixTestResult
67+ const RESULT_TREE = 'result[suites[cases[name,status]]]' ;
68+ const CITGM_REPORT_TREE =
69+ `failCount,skipCount,totalCount,childReports[child[url],${ RESULT_TREE } ]` ;
70+
6271function getPath ( url ) {
6372 return url . replace ( `https://${ CI_DOMAIN } /` , '' ) . replace ( 'api/json' , '' ) ;
6473}
@@ -115,11 +124,11 @@ class Job {
115124 return `https://${ CI_DOMAIN } /${ path } console` ;
116125 }
117126
118- async getBuildData ( ) {
127+ async getBuildData ( type = 'Build' ) {
119128 const { cli, path } = this ;
120129 cli . startSpinner ( `Querying data for ${ path } ` ) ;
121130 const data = await this . getAPIData ( ) ;
122- cli . stopSpinner ( 'Build data downloaded' ) ;
131+ cli . stopSpinner ( ` ${ type } data downloaded` ) ;
123132 return data ;
124133 }
125134
@@ -133,13 +142,13 @@ class Job {
133142 async getAPIData ( ) {
134143 const { cli, request, path } = this ;
135144 const url = this . apiUrl ;
136- cli . updateSpinner ( `Querying API of ${ path } ` ) ;
145+ cli . updateSpinner ( `Querying API for ${ path } ` ) ;
137146 return request . json ( url ) ;
138147 }
139148
140149 async getConsoleText ( ) {
141150 const { cli, request, path } = this ;
142- cli . updateSpinner ( `Querying console text of ${ path } ` ) ;
151+ cli . updateSpinner ( `Querying console text for ${ path } ` ) ;
143152 const data = await request . text ( this . consoleUrl ) ;
144153 return data . replace ( / \r / g, '' ) ;
145154 }
@@ -334,10 +343,13 @@ class TestBuild extends Job {
334343 }
335344
336345 formatAsJson ( ) {
337- const result = this . failures . map ( item => Object . assign ( {
338- source : this . sourceURL ,
339- upstream : this . jobUrl
346+ const { jobUrl, failures, sourceURL } = this ;
347+
348+ const result = failures . map ( item => Object . assign ( {
349+ source : sourceURL ,
350+ upstream : jobUrl
340351 } , item ) ) ;
352+
341353 return JSON . parse ( JSON . stringify ( result ) ) ;
342354 }
343355}
@@ -740,6 +752,147 @@ class PRBuild extends TestBuild {
740752 }
741753}
742754
755+ class CITGMBuild extends TestBuild {
756+ constructor ( cli , request , id ) {
757+ const path = `job/citgm-smoker/${ id } /` ;
758+ const tree = CITGM_MAIN_TREE ;
759+
760+ super ( cli , request , path , tree ) ;
761+
762+ this . id = id ;
763+ }
764+
765+ async getResults ( ) {
766+ const { id } = this ;
767+
768+ let headerData ;
769+ try {
770+ headerData = await this . getBuildData ( 'Summary' ) ;
771+ } catch ( err ) {
772+ this . failures = [
773+ new NCUFailure ( { url : this . apiUrl } , err . message )
774+ ] ;
775+ return this . failures ;
776+ }
777+ const { result } = headerData ;
778+
779+ this . setBuildData ( headerData ) ;
780+
781+ // CITGM jobs store results in a different location than
782+ // they do summary data, so we need to update the endpoint
783+ // and issue a second API call in order to fetch result data.
784+ this . tree = CITGM_REPORT_TREE ;
785+ this . path = `job/citgm-smoker/${ this . id } /testReport/` ;
786+
787+ let resultData ;
788+ try {
789+ resultData = await this . getBuildData ( 'Results' ) ;
790+ } catch ( err ) {
791+ this . failures = [
792+ new NCUFailure ( { url : this . apiUrl } , err . message )
793+ ] ;
794+ return this . failures ;
795+ }
796+
797+ this . results = this . parseResults ( resultData ) ;
798+
799+ // Update id again so that it correctly displays in Summary output.
800+ this . path = `job/citgm-smoker/${ id } /` ;
801+
802+ return { result } ;
803+ }
804+
805+ parseResults ( data ) {
806+ const { childReports, totalCount, skipCount, failCount } = data ;
807+ const results = { all : { } , failures : { } , statistics : { } } ;
808+
809+ const passCount = totalCount - failCount - skipCount ;
810+ results . statistics . passed = passCount ;
811+ results . statistics . total = totalCount ;
812+ results . statistics . skipped = skipCount ;
813+ results . statistics . failed = failCount ;
814+
815+ childReports . forEach ( platform => {
816+ const cases = flatten ( platform . result . suites [ 0 ] . cases ) ;
817+ const url = platform . child . url ;
818+ const nodeName = getNodeName ( url ) ;
819+
820+ results . all [ nodeName ] = { url, modules : cases } ;
821+
822+ const failedModules = cases . filter ( c => c . status === 'FAILED' ) ;
823+ results . failures [ nodeName ] = { url, modules : failedModules } ;
824+ } ) ;
825+
826+ return results ;
827+ }
828+
829+ displayBuilds ( ) {
830+ const { cli, results } = this ;
831+ const { failed, skipped, passed, total } = results . statistics ;
832+
833+ cli . separator ( 'Statistics' ) ;
834+ console . table ( {
835+ Failed : failed ,
836+ Skipped : skipped ,
837+ Passed : passed ,
838+ Total : total
839+ } ) ;
840+
841+ cli . separator ( 'Failures' ) ;
842+ const output = { } ;
843+ for ( const platform in results . failures ) {
844+ const modules = results . failures [ platform ] . modules ;
845+ const failures = modules . map ( f => f . name ) ;
846+
847+ output [ platform ] = failures ;
848+ }
849+
850+ console . table ( output ) ;
851+ }
852+
853+ formatAsJson ( ) {
854+ const { jobUrl, results, sourceURL } = this ;
855+
856+ const result = {
857+ source : sourceURL ,
858+ upstream : jobUrl ,
859+ ...results . statistics ,
860+ ...results . failures
861+ } ;
862+
863+ return JSON . parse ( JSON . stringify ( result ) ) ;
864+ }
865+
866+ formatAsMarkdown ( ) {
867+ const { jobUrl, result, results, id } = this ;
868+
869+ let output = `# CITGM Data for [${ id } ](${ jobUrl } )\n\n` ;
870+
871+ const { failed, skipped, passed, total } = results . statistics ;
872+
873+ output += `## Statistics for job [${ id } ](${ jobUrl } )\n\n` ;
874+ output += '| FAILED | SKIPPED | PASSED | TOTAL |\n' ;
875+ output += '| -------- | --------- | -------- | ------- |\n' ;
876+ output += `| ${ pad ( failed , 8 ) } | ${ pad ( skipped , 9 ) } |` ;
877+ output += ` ${ pad ( passed , 8 ) } | ${ pad ( total , 7 ) } |\n\n` ;
878+
879+ if ( result === SUCCESS ) {
880+ output += `Job [${ id } ](${ jobUrl } ) is green.` ;
881+ return output ;
882+ }
883+
884+ output += `## Failures in job [${ id } ](${ jobUrl } )\n\n` ;
885+ for ( const failure in results . failures ) {
886+ const data = results . failures [ failure ] ;
887+ output += `### [${ failure } ](${ data . url } )\n\n` ;
888+
889+ const failures = data . modules . map ( f => `* ${ f . name } ` ) ;
890+ output += `${ failures . join ( '\n' ) } \n\n` ;
891+ }
892+ return output ;
893+ }
894+ }
895+
743896function filterBuild ( builds , type ) {
744897 return builds
745898 . filter ( build => build . result === type )
@@ -1034,6 +1187,7 @@ module.exports = {
10341187 PRBuild,
10351188 BenchmarkRun,
10361189 CommitBuild,
1190+ CITGMBuild,
10371191 HealthBuild,
10381192 jobCache,
10391193 parseJobFromURL,
0 commit comments