Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-40660

Parallel Test Stage in Blue Ocean marks build as successful before completing

XMLWordPrintable

    • tethys

      See screenshot below.
      My pipeline consists of three main stages really;
      1. Checkout the code.
      2. Build the app, deploy JARs to Artifactory.
      3. Run all unit tests - a step that is executed using the Parallel Test Plugin to spread the load across several nodes and executors.

      In steps 1 and 2, the build state is "in progress", has a blue header.
      As soon as it starts step 3, and before completing it, it changes the build state to "Successful", even though, it is in fact still in progress.
      The header turns green, but the log, available "stop" action as well as the workflow below, shows that it is in fact, still in progress.

      Here's a scrubbed version of my `Jenkinsfile` too:

      #!groovy
      
      node('2times8_0') {
          stage 'Checkout'
          deleteDir()
          dcnCheckout()
          
          /* Set JAVA_HOME, and special PATH variables. */
          /* Get jdk tool. */
          String jdktool = tool name: "jdk8", type: 'hudson.model.JDK'
          
          withEnv(['CI_DEPLOY_USERNAME=???', 'CI_DEPLOY_PASSWORD=???',"PATH+JDK=${jdktool}/bin", "JAVA_HOME=${jdktool}"]) {
              stage 'Build and Deploy' 
              /* Call the Maven build without tests. */
              def server = Artifactory.server "artifactory"
              def buildInfo = Artifactory.newBuildInfo()
              buildInfo.env.capture = true
              def rtMaven = Artifactory.newMavenBuild()
              rtMaven.tool = 'maven339'
              // rtMaven.deployer releaseRepo:'libs-release-local', snapshotRepo:'libs-snapshot-local', server: server
              // rtMaven.resolver releaseRepo:'libs-release', snapshotRepo:'libs-snapshot', server: server
          
              rtMaven.run pom: 'server/bdms-parent/pom.xml',
                          goals: 'clean install -T 8 -B -e -U -Pci -DskipTests -DskipGmaven -s settings.xml ' +
                                 '-Dmaven.repository.base.url=??? ' +
                                 '-Dmaven.repository.repos.url=??? ,
                          buildInfo: buildInfo
          
              buildInfo.retention maxBuilds: 10, maxDays: 7, deleteBuildArtifacts: true
              // Publish build info.
              server.publishBuildInfo buildInfo
              
              stage 'Tests'
              timestamps {
                  runTests ""
              }
          
              /* Save Results. */
              stage 'Results'
              /* Archive the build artifacts */
              archive includes: 'target/*.jar,target/*.war'        
          }
      }
      
      void runTests(def args) {
          /* Request the test groupings.  Based on previous test results. */
          /* see https://wiki.jenkins-ci.org/display/JENKINS/Parallel+Test+Executor+Plugin and demo on github
          /* Using arbitrary parallelism of 4 and "generateInclusions" feature added in v1.8. */
          def splits = splitTests parallelism: [$class: 'CountDrivenParallelism', size: 8], generateInclusions: true
      
          /* Create dictionary to hold set of parallel test executions. */
          def testGroups = [:]
      
          for (int i = 0; i < splits.size(); i++) {
              def split = splits[i]
              def nodeLabel = "2times8"
              /* Loop over each record in splits to prepare the testGroups that we'll run in parallel. */
              /* Split records returned from splitTests contain { includes: boolean, list: List<String> }. */
              /*     includes = whether list specifies tests to include (true) or tests to exclude (false). */
              /*     list = list of tests for inclusion or exclusion. */
              /* The list of inclusions is constructed based on results gathered from */
              /* the previous successfully completed job. One additional record will exclude */
              /* all known tests to run any tests not seen during the previous run.  */
              testGroups["split-${i}"] = {  // example, "split3"
                  // we should restrict this to a set of nodes
                  node(nodeLabel) {
                      deleteDir()
                      dcnCheckout()
      
                      /* Clean each test node to start. */
                      mvn 'clean -f server/bdms-parent/pom.xml'
      
                      def mavenInstall = 'test -e -B -U -f server/bdms-parent/pom.xml -Plogs-off,ci ' +
                                         '-Dmaven.test.failure.ignore=true -DskipGmaven -Dspring.profiles.active="test"' +
                                         '-Dmaven.repository.base.url=??? ' +
                                         '-Dmaven.repository.repos.url=??? '
      
                      /* Write includesFile or excludesFile for tests.  Split record provided by splitTests. */
                      /* Tell Maven to read the appropriate file. */
                      sh 'mkdir -p server/bdms-parent/target'
                      if (split.includes) {
                          writeFile file: "server/bdms-parent/target/parallel-test-includes-${i}.txt", text: split.list.join("\n")
                          mavenInstall += " -Dsurefire.includesFile=../bdms-parent/target/parallel-test-includes-${i}.txt"
                      } else {
                          writeFile file: "server/bdms-parent/target/parallel-test-excludes-${i}.txt", text: split.list.join("\n")
                          mavenInstall += " -Dsurefire.excludesFile=../bdms-parent/target/parallel-test-excludes-${i}.txt"
                      }
      
                      /* Call the Maven build with tests. */
                      mvn mavenInstall
      
                      /* Archive the test results */
                      step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/TEST-*.xml'])
                  }
              }
          }
          parallel testGroups
      }
      
      /* Run maven from tool "mvn" */
      void mvn(def args) {
          /* Get the maven tool. */
          def mvnHome = tool name: 'maven339'
      
          def settings = ' -s settings.xml'
          /* Call maven tool with java envVars. */
          if (isUnix()) {
              sh "${mvnHome}/bin/mvn ${args}"+settings
          } else {
              bat "${mvnHome}\\bin\\mvn ${args}"+settings
          }
      }
      
      void dcnCheckout() {
          checkout([
                  $class: 'GitSCM', 
                  branches: [[name: '*/master']], 
                  extensions: [[
                      $class: 'PathRestriction', 
                      excludedRegions: 'server/bdms-lite/.*', 
                      includedRegions: 'server/.*'
                  ]], 
                  userRemoteConfigs: [[
                      url: '???]]])
      }
      

            Unassigned Unassigned
            ronif Roni Frantchi
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: