| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252 |
- #!/usr/bin/env groovy
- /*
- * This Jenkinsfile is intended to run on https://ci.jenkins.io and may fail anywhere else.
- * It makes assumptions about plugins being installed, labels mapping to nodes that can build what is needed, etc.
- */
- def failFast = false
- def numBuildToKeep = env.CHANGE_ID ? '10' : '50'
- properties([
- buildDiscarder(logRotator(numToKeepStr: numBuildToKeep, artifactNumToKeepStr: '3')),
- disableConcurrentBuilds(abortPrevious: true)
- ])
- def axes = [
- platforms: ['linux', 'windows'],
- jdks: [21, 25],
- ]
- stage('Record build') {
- retry(conditions: [kubernetesAgent(handleNonKubernetes: true), nonresumable()], count: 2) {
- node('maven-21-nonspot') {
- infra.checkoutSCM()
- /*
- * Record the primary build for this CI job.
- */
- withCredentials([string(credentialsId: 'launchable-jenkins-jenkins', variable: 'LAUNCHABLE_TOKEN')]) {
- /*
- * TODO Add the commits of the transitive closure of the Jenkins WAR under test to this build.
- */
- // Replace URL encoded characters with '-' because Launchable rejects '%2F' in build name
- def launchableName = env.BUILD_TAG.replaceAll('(%[0-9A-Fa-f]{2})+', '-')
- sh "launchable verify && launchable record build --name ${launchableName} --source jenkinsci/jenkins=."
- axes.values().combinations {
- def (platform, jdk) = it
- if (platform == 'windows' && jdk != axes.jdks.last()) {
- return // unnecessary use of hardware
- }
- def sessionFile = "launchable-session-${platform}-jdk${jdk}.txt"
- sh "launchable record session --build ${launchableName} --flavor platform=${platform} --flavor jdk=${jdk} >${sessionFile}"
- stash name: sessionFile, includes: sessionFile
- }
- }
- /*
- * Record commits for use in downstream CI jobs that may consume this artifact.
- */
- withCredentials([string(credentialsId: 'launchable-jenkins-acceptance-test-harness', variable: 'LAUNCHABLE_TOKEN')]) {
- sh 'launchable verify && launchable record commit'
- }
- withCredentials([string(credentialsId: 'launchable-jenkins-bom', variable: 'LAUNCHABLE_TOKEN')]) {
- sh 'launchable verify && launchable record commit'
- }
- }
- }
- }
- def builds = [:]
- axes.values().combinations {
- def (platform, jdk) = it
- if (platform == 'windows' && jdk != axes.jdks.last()) {
- return // unnecessary use of hardware
- }
- builds["${platform}-jdk${jdk}"] = {
- // see https://github.com/jenkins-infra/documentation/blob/master/ci.adoc#node-labels for information on what node types are available
- def agentContainerLabel = 'maven-' + jdk
- if (platform == 'windows') {
- agentContainerLabel += '-windows'
- }
- agentContainerLabel += '-nonspot'
- retry(conditions: [kubernetesAgent(handleNonKubernetes: true), nonresumable()], count: 2) {
- node(agentContainerLabel) {
- // First stage is actually checking out the source. Since we're using Multibranch
- // currently, we can use "checkout scm".
- stage("${platform.capitalize()} - JDK ${jdk} - Checkout") {
- infra.checkoutSCM()
- }
- def tmpDir = pwd(tmp: true)
- def changelistF = "${tmpDir}/changelist"
- def m2repo = "${tmpDir}/m2repo"
- def session
- // Now run the actual build.
- stage("${platform.capitalize()} - JDK ${jdk} - Build / Test") {
- timeout(time: 6, unit: 'HOURS') {
- dir(tmpDir) {
- def sessionFile = "launchable-session-${platform}-jdk${jdk}.txt"
- unstash sessionFile
- session = readFile(sessionFile).trim()
- }
- def mavenOptions = [
- '-Pdebug',
- '-Penable-jacoco',
- '--update-snapshots',
- "-Dmaven.repo.local=$m2repo",
- '-Dmaven.test.failure.ignore',
- '-DforkCount=2',
- '-Dspotbugs.failOnError=false',
- '-Dcheckstyle.failOnViolation=false',
- '-Dset.changelist',
- 'help:evaluate',
- '-Dexpression=changelist',
- "-Doutput=$changelistF",
- 'clean',
- 'install',
- ]
- if (env.CHANGE_ID && !pullRequest.labels.contains('full-test')) {
- def excludesFile
- def target = platform == 'windows' ? '30%' : '100%'
- withCredentials([string(credentialsId: 'launchable-jenkins-jenkins', variable: 'LAUNCHABLE_TOKEN')]) {
- if (isUnix()) {
- excludesFile = "${tmpDir}/excludes.txt"
- sh "launchable verify && launchable subset --session ${session} --target ${target} --get-tests-from-previous-sessions --output-exclusion-rules maven >${excludesFile}"
- } else {
- excludesFile = "${tmpDir}\\excludes.txt"
- bat "launchable verify && launchable subset --session ${session} --target ${target}% --get-tests-from-previous-sessions --output-exclusion-rules maven >${excludesFile}"
- }
- }
- mavenOptions.add(0, "-Dsurefire.excludesFile=${excludesFile}")
- }
- withChecks(name: 'Tests', includeStage: true) {
- realtimeJUnit(healthScaleFactor: 20.0, testResults: '*/target/surefire-reports/*.xml,target/vitest-reports/*.xml') {
- infra.runMaven(mavenOptions, jdk)
- if (isUnix()) {
- sh 'git add . && git diff --exit-code HEAD'
- }
- }
- }
- }
- }
- // Once we've built, archive the artifacts and the test results.
- stage("${platform.capitalize()} - JDK ${jdk} - Publish") {
- archiveArtifacts allowEmptyArchive: true, artifacts: '**/target/surefire-reports/*.dumpstream'
- // cli and war have been migrated to JUnit 5
- if (failFast && currentBuild.result == 'UNSTABLE') {
- error 'There were test failures; halting early'
- }
- if (platform == 'linux' && jdk == axes['jdks'][0]) {
- def folders = env.JOB_NAME.split('/')
- if (folders.length > 1) {
- discoverGitReferenceBuild(scm: folders[1])
- }
- recordCoverage(tools: [[parser: 'JACOCO', pattern: 'coverage/target/site/jacoco-aggregate/jacoco.xml']],
- sourceCodeRetention: 'MODIFIED', sourceDirectories: [[path: 'core/src/main/java']])
- echo "Recording static analysis results for '${platform.capitalize()}'"
- recordIssues(
- enabledForFailure: true,
- tools: [java()],
- filters: [excludeFile('.*Assert.java')],
- sourceCodeEncoding: 'UTF-8',
- skipBlames: true,
- trendChartType: 'TOOLS_ONLY'
- )
- recordIssues(
- enabledForFailure: true,
- tools: [javaDoc()],
- filters: [excludeFile('.*Assert.java')],
- sourceCodeEncoding: 'UTF-8',
- skipBlames: true,
- trendChartType: 'TOOLS_ONLY',
- qualityGates: [[threshold: 1, type: 'TOTAL', unstable: true]]
- )
- recordIssues([tool: spotBugs(pattern: '**/target/spotbugsXml.xml'),
- sourceCodeEncoding: 'UTF-8',
- skipBlames: true,
- trendChartType: 'TOOLS_ONLY',
- qualityGates: [[threshold: 1, type: 'NEW', unstable: true]]])
- recordIssues([tool: checkStyle(pattern: '**/target/checkstyle-result.xml'),
- sourceCodeEncoding: 'UTF-8',
- skipBlames: true,
- trendChartType: 'TOOLS_ONLY',
- qualityGates: [[threshold: 1, type: 'TOTAL', unstable: true]]])
- recordIssues([tool: esLint(pattern: '**/target/eslint-warnings.xml'),
- sourceCodeEncoding: 'UTF-8',
- skipBlames: true,
- trendChartType: 'TOOLS_ONLY',
- qualityGates: [[threshold: 1, type: 'TOTAL', unstable: true]]])
- recordIssues([tool: styleLint(pattern: '**/target/stylelint-warnings.xml'),
- sourceCodeEncoding: 'UTF-8',
- skipBlames: true,
- trendChartType: 'TOOLS_ONLY',
- qualityGates: [[threshold: 1, type: 'TOTAL', unstable: true]]])
- if (failFast && currentBuild.result == 'UNSTABLE') {
- error 'Static analysis quality gates not passed; halting early'
- }
- def changelist = readFile(changelistF)
- dir(m2repo) {
- archiveArtifacts(
- artifacts: "**/*$changelist/*$changelist*",
- excludes: '**/*.lastUpdated,**/jenkins-coverage*/,**/jenkins-test*/',
- allowEmptyArchive: true, // in case we forgot to reincrementalify
- fingerprint: true
- )
- }
- }
- withCredentials([string(credentialsId: 'launchable-jenkins-jenkins', variable: 'LAUNCHABLE_TOKEN')]) {
- if (isUnix()) {
- sh "launchable verify && launchable record tests --session ${session} --flavor platform=${platform} --flavor jdk=${jdk} maven './**/target/surefire-reports'"
- } else {
- bat "launchable verify && launchable record tests --session ${session} --flavor platform=${platform} --flavor jdk=${jdk} maven ./**/target/surefire-reports"
- }
- }
- }
- }
- }
- }
- }
- def athAxes = [
- platforms: ['linux'],
- jdks: [25],
- browsers: ['firefox'],
- ]
- athAxes.values().combinations {
- def (platform, jdk, browser) = it
- builds["ath-${platform}-jdk${jdk}-${browser}"] = {
- retry(conditions: [agent(), nonresumable()], count: 2) {
- node('docker-highmem') {
- // Just to be safe
- deleteDir()
- checkout scm
- withChecks(name: 'Tests', includeStage: true) {
- infra.withArtifactCachingProxy {
- sh "bash ath.sh ${jdk} ${browser}"
- }
- junit testResults: 'target/ath-reports/TEST-*.xml', testDataPublishers: [[$class: 'AttachmentPublisher']]
- }
- /*
- * Currently disabled, as the fact that this is a manually created subset will confuse Launchable,
- * which expects this to be a full build. When we implement subsetting, this can be re-enabled using
- * Launchable's subset rather than our own.
- */
- /*
- withCredentials([string(credentialsId: 'launchable-jenkins-acceptance-test-harness', variable: 'LAUNCHABLE_TOKEN')]) {
- sh "launchable verify && launchable record tests --no-build --flavor platform=${platform} --flavor jdk=${jdk} --flavor browser=${browser} maven './target/ath-reports'"
- }
- */
- }
- }
- }
- }
- builds.failFast = failFast
- parallel builds
- infra.maybePublishIncrementals()
|