mirror of
https://github.com/SAP/jenkins-library.git
synced 2024-12-12 10:55:20 +02:00
146 lines
5.4 KiB
Groovy
146 lines
5.4 KiB
Groovy
@Grab('org.yaml:snakeyaml:1.17')
|
|
|
|
import org.yaml.snakeyaml.Yaml
|
|
|
|
class TestRunnerThread extends Thread {
|
|
|
|
static def workspacesRootDir
|
|
static def libraryVersionUnderTest
|
|
static def repositoryUnderTest
|
|
|
|
Process currentProcess
|
|
final StringBuilder stdOut = new StringBuilder()
|
|
final StringBuilder stdErr = new StringBuilder()
|
|
int lastPrintedStdOutLine = -1
|
|
public def returnCode = -1
|
|
public def lastCommand
|
|
def area
|
|
def testCase
|
|
def uniqueName
|
|
def testCaseRootDir
|
|
def testCaseWorkspace
|
|
def testCaseConfig
|
|
|
|
TestRunnerThread(File testCaseFile) {
|
|
this.testCaseConfig = new Yaml().load(testCaseFile.text)
|
|
if (!System.getenv(testCaseConfig.deployCredentialEnv.username) ||
|
|
!System.getenv(testCaseConfig.deployCredentialEnv.password)) {
|
|
throw new RuntimeException("Environment variables '${testCaseConfig.deployCredentialEnv.username}' and '${testCaseConfig.deployCredentialEnv.password}' need to be set.")
|
|
}
|
|
// Regex pattern expects a folder structure such as '/rootDir/areaDir/testCase.extension'
|
|
def testCaseMatches = (testCaseFile.toString() =~
|
|
/^[\w\-]+\\/([\w\-]+)\\/([\w\-]+)\..*\u0024/)
|
|
this.area = testCaseMatches[0][1]
|
|
this.testCase = testCaseMatches[0][2]
|
|
if (!area || !testCase) {
|
|
throw new RuntimeException("Expecting file structure '/rootDir/areaDir/testCase.yml' " +
|
|
"but got '${testCaseFile}'.")
|
|
}
|
|
this.uniqueName = "${area}|${testCase}"
|
|
this.testCaseRootDir = new File("${workspacesRootDir}/${area}/${testCase}")
|
|
this.testCaseWorkspace = "${testCaseRootDir}/workspace"
|
|
}
|
|
|
|
void run() {
|
|
println "[INFO] Test case '${uniqueName}' launched."
|
|
|
|
if (testCaseRootDir.exists() || !testCaseRootDir.mkdirs()) {
|
|
throw new RuntimeException("Creation of dir '${testCaseRootDir}' failed.")
|
|
}
|
|
|
|
executeShell("git clone -b ${testCaseConfig.referenceAppRepo.branch} " +
|
|
"${testCaseConfig.referenceAppRepo.url} ${testCaseWorkspace}")
|
|
|
|
addJenkinsYmlToWorkspace()
|
|
setLibraryVersionInJenkinsfile()
|
|
|
|
//Commit the changed version because artifactSetVersion expects the git repo not to be dirty
|
|
executeShell(["git", "-C", "${testCaseWorkspace}", "commit", "--all",
|
|
'--author="piper-testing-bot <piper-testing-bot@example.com>"',
|
|
'--message="Set piper lib version for test"'])
|
|
|
|
executeShell("docker run --rm -v /var/run/docker.sock:/var/run/docker.sock " +
|
|
"-v ${System.getenv('PWD')}/${testCaseWorkspace}:/workspace -v /tmp " +
|
|
"-e CASC_JENKINS_CONFIG=/workspace/jenkins.yml " +
|
|
"-e ${testCaseConfig.deployCredentialEnv.username} " +
|
|
"-e ${testCaseConfig.deployCredentialEnv.password} " +
|
|
"-e LIBRARY_VERSION_UNDER_TEST=${libraryVersionUnderTest} " +
|
|
"-e REPOSITORY_UNDER_TEST=${repositoryUnderTest} " +
|
|
"-e BRANCH_NAME=${testCaseConfig.referenceAppRepo.branch} ppiper/jenkinsfile-runner")
|
|
|
|
println "*****[INFO] Test case '${uniqueName}' finished successfully.*****"
|
|
printOutput()
|
|
}
|
|
|
|
// Configure path to library-repository under test in Jenkins config
|
|
private void addJenkinsYmlToWorkspace() {
|
|
def sourceFile = 'jenkins.yml'
|
|
def sourceText = new File(sourceFile).text.replaceAll(
|
|
'__REPO_SLUG__', repositoryUnderTest)
|
|
def target = new File("${testCaseWorkspace}/${sourceFile}")
|
|
target.write(sourceText)
|
|
}
|
|
|
|
// Force usage of library version under test by setting it in the Jenkinsfile,
|
|
// which is then the first definition and thus has the highest precedence.
|
|
private void setLibraryVersionInJenkinsfile() {
|
|
def jenkinsfile = new File("${testCaseWorkspace}/Jenkinsfile")
|
|
def manipulatedText =
|
|
"@Library(\"piper-lib-os@${libraryVersionUnderTest}\") _\n" +
|
|
jenkinsfile.text
|
|
jenkinsfile.write(manipulatedText)
|
|
}
|
|
|
|
private void executeShell(command) {
|
|
lastCommand = command
|
|
def startOfCommandString = "Shell command: '${command}'\n"
|
|
stdOut << startOfCommandString
|
|
stdErr << startOfCommandString
|
|
|
|
currentProcess = command.execute()
|
|
currentProcess.waitForProcessOutput(stdOut, stdErr)
|
|
|
|
returnCode = currentProcess.exitValue()
|
|
|
|
currentProcess = null
|
|
|
|
if (returnCode > 0) {
|
|
throw new ReturnCodeNotZeroException("Test case: [${uniqueName}]; " +
|
|
"shell command '${command} exited with return code '${returnCode}")
|
|
}
|
|
}
|
|
|
|
void printOutput() {
|
|
println "\n[INFO] stdout output from test case ${uniqueName}:"
|
|
stdOut.eachLine { line, i ->
|
|
println "${i} [${uniqueName}] ${line}"
|
|
lastPrintedStdOutLine = i
|
|
}
|
|
|
|
println "\n[INFO] stderr output from test case ${uniqueName}:"
|
|
stdErr.eachLine { line, i ->
|
|
println "${i} [${uniqueName}] ${line}"
|
|
}
|
|
}
|
|
|
|
public void printRunningStdOut() {
|
|
stdOut.eachLine { line, i ->
|
|
if (i > lastPrintedStdOutLine) {
|
|
println "${i} [${uniqueName}] ${line}"
|
|
lastPrintedStdOutLine = i
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return uniqueName
|
|
}
|
|
}
|
|
|
|
class ReturnCodeNotZeroException extends Exception {
|
|
ReturnCodeNotZeroException(message) {
|
|
super(message)
|
|
}
|
|
}
|