0

I'm trying to run a pipeline that does some Pester Testing and publish the NUnit results.

New tests were introduced and for whatever the reason, Jenkins no longer publishes the test results and errors out immediately after the powershell script. Hence, it doesn't get to the nunit publish piece. I receive this:

ERROR: script returned exit code 128 Finished: FAILURE

I've been trying to include the publish in the always section of the post section of the Jenkinsfile, however, I'm running into problems on how to make that NUnit test file available.

I've tried establishing an agent and unstash the file (even though it probably won't stash if the powershell script cancels the whole pipeline). When I use agent I get the following exception:

java.lang.NoSuchMethodError: No such DSL method 'agent' found among steps

Here is the Jenkinsfile:

pipeline {
    agent none

    environment {
        svcpath = 'D:\\svc\\'
        unitTestFile = 'UnitTests.xml'
    }
    stages {
        stage ('Checkout and Stash') {
            agent {label 'Agent1'}
            steps {
                stash name: 'Modules', includes: 'Modules/*/**'
                stash name: 'Tests', includes: 'Tests/*/**'
            }
        }
        stage ('Unit Tests') {
            agent {label 'Agent1'}
            steps {
                dir(svcpath + 'Modules\\'){deleteDir()}
                dir(svcpath + 'Tests\\'){deleteDir()}
                dir(svcpath){
                unstash name: 'Modules'
                unstash name: 'Tests'
            }
            dir(svcpath + 'Tests\\'){
            powershell """

            \$requiredCoverageThreshold = 0.90

            \$modules = Get-ChildItem ../Modules/ -File -Recurse -Include *.psm1

            \$result = Invoke-Pester -CodeCoverage \$modules -PassThru -OutputFile ${unitTestFile} -OutputFormat NUnitXml

            \$codeCoverage = \$result.CodeCoverage.NumberOfCommandsExecuted / \$result.CodeCoverage.NumberOfCommandsAnalyzed

            Write-Output \$codeCoverage

            if (\$codeCoverage -lt \$requiredCoverageThreshold) {
                Write-Output "Build failed: required code coverage threshold of \$(\$requiredCoverageThreshold * 100)% not met. Current coverage: \$(\$codeCoverage * 100)%."
                exit 1
            } else {
                write-output "Required code coverage threshold of \$(\$requiredCoverageThreshold * 100)% met. Current coverage: \$(\$codeCoverage * 100)%."
            }
            """
            stash name: 'TestResults', includes: unitTestFile
            nunit testResultsPattern: unitTestFile
        }
    }
    post {
        always {
            echo 'This will always run'
            agent {label 'Agent1'}
            unstash name: 'TestResults'
            nunit testResultsPattern: unitTestFile
        }
        success {
            echo 'This will run only if successful'
        }
        failure {
            echo 'This will run only if failed'
        }
        unstable {
            echo 'This will run only if the run was marked as unstable'
        }
        changed {
            echo 'This will run only if the state of the Pipeline has changed'
            echo 'For example, if the Pipeline was previously failing but is now successful'
       }
    }
}

Any and all input is welcome! Thanks!

Andrew Gray
  • 3,593
  • 3
  • 35
  • 62
DanOpi
  • 133
  • 2
  • 12

2 Answers2

0

The exception you are getting is due to Jenkins' strict pipeline DSL. Documentation of allowable uses of agent are here.

Currently agent {...} is not allowed to be used in the post section. Maybe this will change in the future. If you require the whole job to run on the node that services label 'Agent1' the only way to currently do that is to

  1. Put agent {label 'Agent1'} immediately under pipeline { to make it global
  2. Remove all instances of agent {label 'Agent1'} in each stage
  3. Remove the agent {label 'Agent1'} from the post section.
Andrew Gray
  • 3,593
  • 3
  • 35
  • 62
  • I don't want a global agent. I use different agents throughout the pipeline that are removed from my snippet. I also use a Shared Library that has a few methods that require ```agent none```. – DanOpi Aug 27 '18 at 15:26
  • Ok but I've told you why you are getting that exception (based on what you have shared) and how to fix it. – Andrew Gray Aug 27 '18 at 22:55
0

The post section acts more like traditional scripted DSL than the pipeline declarative DSL. So you have to use node() instead of agent.

I believe I've had this same question myself, and this SO post has the answer and some good context.

This Jenkins issue isn't exactly the same thing but shows the node syntax in the post stage.

Max Cascone
  • 648
  • 9
  • 25