#!/usr/bin/env groovy
/**
* Wrapper for running the ATH see README and runATH.txt for full documentation
*/
void stashJenkinsWar(String jenkins, String stashName = "jenkinsWar") {
def isVersionNumber = (jenkins =~ /^\d+([.]\d+)*(-rc[0-9]+[.][0-9a-f]{12})?$/).matches()
def isLocalJenkins = jenkins.startsWith("file:)
def mirror = "http:
def jenkinsURL
if (jenkins == "latest") {
jenkinsURL = mirror + "war/latest/jenkins.war"
} else if (jenkins == "latest-rc") {
jenkinsURL = mirror + "/war-rc/latest/jenkins.war"
} else if (jenkins == "lts") {
jenkinsURL = mirror + "war-stable/latest/jenkins.war"
} else if (jenkins == "lts-rc") {
jenkinsURL = mirror + "war-stable-rc/latest/jenkins.war"
}
if (isLocalJenkins) {
if (!fileExists(jenkins - "file:)) {
error "Specified Jenkins file does not exists"
}
}
if (!isVersionNumber && !isLocalJenkins) {
if (jenkinsURL == null) {
error "Not sure how to interpret $jenkins as a version, alias, or URL"
}
echo 'Checking whether Jenkins WAR is available…'
sh "curl -ILf ${jenkinsURL}"
}
if (isVersionNumber) {
List<String> downloadCommand = [
"dependency:copy",
"-Dartifact=org.jenkins-ci.main:jenkins-war:${jenkins}:war",
"-DoutputDirectory=.",
"-Dmdep.stripVersion=true"
]
dir("deps") {
runMaven(downloadCommand)
sh "cp jenkins-war.war jenkins.war"
stash includes: 'jenkins.war', name: stashName
}
} else if (isLocalJenkins) {
dir(pwd(tmp: true)) {
sh "cp ${jenkins - 'file:} jenkins.war"
stash includes: "*.war", name: "jenkinsWar"
}
} else {
sh("curl -o jenkins.war -L ${jenkinsURL}")
stash includes: '*.war', name: 'jenkinsWar'
}
}
def runATH(Map params = [:]) {
def athUrl = params.get('athUrl', 'https:)
def athRevision = params.get('athRevision', 'master')
def metadataFile = params.get('metadataFile', 'essentials.yml')
def jenkins = params.get('jenkins', 'latest')
def jdks = params.get('jdks', [8])
def athContainerImageTag = params.get("athImage", "jenkins/ath");
def configFile = params.get("configFile", null)
def defaultJavaOptions = params.get('javaOptions', ['--no-transfer-progress'])
def mirror = "http:
def defaultCategory = "org.jenkinsci.test.acceptance.junit.SmokeTest"
def metadata
def athContainerImage
def isLocalATH
def isVersionNumber
def athSourcesFolder = "athSources"
def supportedBrowsers = ["firefox"]
def supportedJdks = [8, 11]
def skipExecution = false
def localPluginsStashName = env.RUN_ATH_LOCAL_PLUGINS_STASH_NAME ?: "localPlugins"
if (!fileExists(metadataFile)) {
echo "Skipping ATH execution because the metadata file does not exist. Current value is ${metadataFile}."
skipExecution = true
return
}
stage("Getting ATH sources and Jenkins war") {
metadata = readYaml(file: metadataFile)?.ath
if (metadata == null) {
echo "Skipping ATH execution because the metadata file does not contain an ath section"
skipExecution = true
return
}
if (metadata == 'default') {
echo "Using default configuration for ATH"
metadata = [:]
} else if (metadata.browsers == null) {
echo "The provided metadata file does not include the browsers property, using firefox as default"
}
athUrl = metadata.athUrl ?: athUrl
isLocalATH = athUrl.startsWith("file:)
athRevision = metadata.athRevision ?: athRevision
athContainerImageTag = metadata.athImage ?: athContainerImageTag
jenkins = metadata.jenkins ?: jenkins
isVersionNumber = (jenkins =~ /^\d+([.]\d+)*$/).matches()
jdks = metadata.jdks ?: jdks
if (!isLocalATH) {
echo 'Checking connectivity to ATH sources…'
sh "git ls-remote --exit-code -h ${athUrl}"
}
stashJenkinsWar(jenkins)
if (isLocalATH) { athSourcesFolder = athUrl - "file:
} else {
dir(athSourcesFolder) {
checkout changelog: true, poll: false, scm: [$class : 'GitSCM', branches: [[name: athRevision]],
userRemoteConfigs: [[url: athUrl]]]
}
}
dir(athSourcesFolder) {
stash name: "athSources"
}
}
if (skipExecution) {
return
}
stage("Running ATH") {
dir("athSources") {
unstash name: "athSources"
if (athContainerImageTag == "local") {
echo "'local' ATH container image specified, building it"
def uid = sh(script: "id -u", returnStdout: true)
def gid = sh(script: "id -g", returnStdout: true)
athContainerImage = docker.build('jenkins/ath', "--build-arg=uid='$uid' --build-arg=gid='$gid' -f src/main/resources/ath-container/Dockerfile .")
} else {
echo "No building ATH docker container image. Using ${athContainerImageTag} as specified"
athContainerImage = docker.image(athContainerImageTag)
athContainerImage.pull() }
}
def testsToRun = metadata.tests?.join(",")
def categoriesToRun = metadata.categories?.join(",")
def browsers = metadata.browsers ?: ["firefox"]
def failFast = metadata.failFast ?: false
def rerunCount = metadata.rerunFailingTestsCount ?: 0
def localSnapshots = metadata.useLocalSnapshots != null ? metadata.useLocalSnapshots : true
if (testsToRun == null && categoriesToRun == null) {
categoriesToRun = defaultCategory
}
if (testsToRun == "all") {
testsToRun = categoriesToRun = null
}
def testingbranches = ["failFast": failFast]
for (jdk in jdks) {
if (supportedJdks.contains(jdk)) {
def currentJdk = jdk
def javaOptions = defaultJavaOptions.clone()
def containerArgs = "-v /var/run/docker.sock:/var/run/docker.sock -u ath-user --shm-size 2g"
if(configFile) {
containerArgs += " -e CONFIG=../${configFile}" }
if ( currentJdk > 8) {
containerArgs += " -e java_version=${currentJdk}"
}
for (browser in browsers) {
if (supportedBrowsers.contains(browser)) {
def currentBrowser = browser
def commandBase = "./run.sh ${currentBrowser} ./jenkins.war -B -ntp -Dmaven.test.failure.ignore=true -DforkCount=1 -Dsurefire.rerunFailingTestsCount=${rerunCount}"
if (testsToRun) {
testingbranches["ATH individual tests-${currentBrowser}-jdk${currentJdk}"] = {
dir("test${currentBrowser}jdk${currentJdk}") {
def discriminator = "-Dtest=${testsToRun}"
test(discriminator, commandBase, localSnapshots, localPluginsStashName, containerArgs, athContainerImage, javaOptions)
}
}
}
if (categoriesToRun) {
testingbranches["ATH categories-${currentBrowser}-jdk${currentJdk}"] = {
dir("categories${currentBrowser}jdk${currentJdk}") {
def discriminator = "-Dgroups=${categoriesToRun}"
test(discriminator, commandBase, localSnapshots, localPluginsStashName, containerArgs, athContainerImage, javaOptions)
}
}
}
if (testsToRun == null && categoriesToRun == null) {
testingbranches["ATH ${currentBrowser}-jdk${currentJdk}"] = {
dir("ath${currentBrowser}${currentJdk}") {
def discriminator = ""
test(discriminator, commandBase, localSnapshots, localPluginsStashName, containerArgs, athContainerImage, javaOptions)
}
}
}
} else {
echo "${browser} is not yet supported"
}
}
} else {
echo "${jdk} is not yet supported"
}
}
parallel testingbranches
}
}
private void test(discriminator, commandBase, localSnapshots, localPluginsStashName, containerArgs, athContainerImage, javaOptions) {
unstashResources(localSnapshots, localPluginsStashName)
athContainerImage.inside(containerArgs) {
realtimeJUnit(testResults: 'target/surefire-reports/TEST-*.xml', testDataPublishers: [[$class: 'AttachmentPublisher']]) {
/*
If you want to compile with java > 8 and have all needed, do it
If you want to compile with java > 8 and you lack the set-java script, FAILURE
If other case (java8 and lack set-java), write a message in the log
*/
def command = '''
if [ -x ./set-java.sh ] && [ -n "$java_version" ] && [ "$java_version" -gt "8" ]; then
./set-java.sh $java_version;
elif [ -n "$java_version" ] && [ "$java_version" -gt "8" ] && [ ! -x ./set-java.sh ]; then
echo "ERROR: ./set-java.sh not found because you are using old ATH sources and \\$java_version = $java_version specified. We cannot run on this JDK";
exit 1;
elif [ ! -x ./set-java.sh ]; then
echo "INFO: ./set-java.sh not found because you are using old ATH sources, please consider to update ATH sources and docker image";
fi
eval "$(./vnc.sh)" \
&& export DISPLAY=$BROWSER_DISPLAY \
&& export SHARED_DOCKER_SERVICE=true \
&& export EXERCISEDPLUGINREPORTER=textfile \
&& \
'''
command += prepareCommand(commandBase, discriminator, localSnapshots, localPluginsStashName)
if (!javaOptions.isEmpty()) {
command = """export JAVA_OPTS="${javaOptions.join(' ')}" && ${command}"""
}
sh command
}
}
}
private String prepareCommand(commandBase, discriminator, localSnapshots, localPluginsStashName ) {
def command = commandBase + " ${discriminator}"
if (localSnapshots && localPluginsStashName) {
command = "LOCAL_JARS=${getLocalPluginsList()} " + command
}
command
}
private void unstashResources(localSnapshots, localPluginsStashName) {
unstash name: "athSources"
unstash name: "jenkinsWar"
dir("localPlugins") {
if (localSnapshots && localPluginsStashName) {
unstash name: localPluginsStashName
}
}
}
private String getLocalPluginsList() {
return sh(script : "ls -p -d -1 localPlugins/*.* | tr '\n' ':'| sed 's/.\$", returnStdout: true).trim()
}
node("docker-highmem") {
deleteDir()
def fileUri
def metadataPath
dir("sources") {
git 'https:
sh 'mvn --batch-mode --show-version -ntp -Pquick-build -am -pl war package'
dir("war/target") {
fileUri = "file: + pwd() + "/jenkins.war"
}
metadataPath = pwd() + "/essentials.yml"
}
dir("ath") {
runATH jenkins: fileUri, metadataFile: metadataPath
}
}
Reproduced locally with script extracted from pipeline library,
should run on anything with maven and git installed, inline pipeline script.
Recommended plugins + pipeline utility steps