Newer
Older
/*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
Vincent Massol
committed
// It's assumed that Jenkins has been configured to implicitly load the vars/*.groovy libraries.
// Note that the version used is the one defined in Jenkins but it can be overridden as follows:
// @Library("XWiki@<branch, tag, sha1>") _
// See https://github.com/jenkinsci/workflow-cps-global-lib-plugin for details.
// Definitions of all builds
def builds = [
'Main' : {
build(
name: 'Main',
profiles: 'legacy,integration-tests,snapshot',
Vincent Massol
committed
'-Dxwiki.checkstyle.skip=true -Dxwiki.surefire.captureconsole.skip=true -Dxwiki.revapi.skip=true -DskipITs'
Vincent Massol
committed
// Can be used to manually trigger the main build with integration tests on the CI.
'Main with Integration Tests' : {
build(
Vincent Massol
committed
name: 'Main with Integration Tests',
Vincent Massol
committed
profiles: 'legacy,integration-tests,snapshot',
properties:
Vincent Massol
committed
'-Dxwiki.checkstyle.skip=true -Dxwiki.surefire.captureconsole.skip=true -Dxwiki.revapi.skip=true'
Vincent Massol
committed
)
},
'Distribution' : {
build(
name: 'Distribution',
profiles: 'legacy,integration-tests,snapshot',
pom: 'xwiki-platform-distribution/pom.xml'
)
},
'Flavor Test - POM' : {
buildFunctionalTest(
name: 'Flavor Test - POM',
pom: 'pom.xml',
properties: '-N'
)
},
'Flavor Test - PageObjects' : {
buildFunctionalTest(
name: 'Flavor Test - PageObjects',
pom: 'xwiki-platform-distribution-flavor-test-pageobjects/pom.xml'
)
},
'Flavor Test - UI' : {
buildFunctionalTest(
name: 'Flavor Test - UI',
Thomas Mortagne
committed
pom: 'xwiki-platform-distribution-flavor-test-ui/pom.xml',
)
},
'Flavor Test - Misc' : {
buildFunctionalTest(
name: 'Flavor Test - Misc',
pom: 'xwiki-platform-distribution-flavor-test-misc/pom.xml'
)
},
'Flavor Test - Storage': {
buildFunctionalTest(
name: 'Flavor Test - Storage',
pom: 'xwiki-platform-distribution-flavor-test-storage/pom.xml'
)
},
'Flavor Test - Escaping' : {
buildFunctionalTest(
name: 'Flavor Test - Escaping',
pom: 'xwiki-platform-distribution-flavor-test-escaping/pom.xml'
)
},
'Flavor Test - Upgrade' : {
buildFunctionalTest(
name: 'Flavor Test - Upgrade',
pom: 'xwiki-platform-distribution-flavor-test-upgrade/pom.xml'
)
},
'Flavor Test - Webstandards' : {
buildFunctionalTest(
name: 'Flavor Test - Webstandards',
pom: 'xwiki-platform-distribution-flavor-test-webstandards/pom.xml',
mavenOpts: '-Xmx2048m -Xms512m -XX:ThreadStackSize=2048'
Manuel Leduc
committed
'Flavor Test - Security' : {
buildFunctionalTest(
name: 'Flavor Test - Security',
Manuel Leduc
committed
pom: 'xwiki-platform-distribution-flavor-test-security/pom.xml'
Manuel Leduc
committed
)
},
'TestRelease': {
build(
name: 'TestRelease',
goals: 'clean install',
profiles: 'release,hsqldb,jetty,legacy,integration-tests,standalone,flavor-integration-tests,distribution,docker',
properties: '-DskipTests -DperformRelease=true -Dgpg.skip=true -Dxwiki.checkstyle.skip=true -Dxwiki.revapi.skip=true -Dxwiki.enforcer.skip=true -Dxwiki.spoon.skip=true -Ddoclint=all'
)
},
'Quality' : {
node() {
// Run the quality checks.
// Notes for step 1:
// - The build executes jacoco to generate a single jacoco exec file containing the results of the coverage
// for all tests from all modules. This why we need -Pcoverage and -Dxwiki.jacoco.itDestFile.
buildInsideNode(
name: 'Quality Step 1',
goals: 'clean install',
profiles: 'repository-snapshots,quality,legacy,coverage',
properties: '-Dxwiki.jacoco.itDestFile=`pwd`/target/jacoco-it.exec'
)
// Notes for step 2:
// - We generate the jacoco reports for all modules (all from the single jacoco-it.exec file)
// - We then generate the sonar analysis and upload to Sonarcloud with the sonar:sonar goal.
// - Sonar uses the jacoco report files and it's thus important that the sonar:sonar goal is executed after
// the jacoco:report one.
buildInsideNode(
name: 'Quality Step 2',
goals: 'jacoco:report sonar:sonar',
profiles: 'repository-snapshots,quality,legacy,coverage',
properties: '-Dxwiki.jacoco.itDestFile=`pwd`/target/jacoco-it.exec'
)
}
Vincent Massol
committed
// Let the user select the build to execute if manually triggered. Otherwise, build everything.
stage('Platform Builds') {
def choices = builds.collect { k,v -> "$k" }.join('\n')
// askUser() will check if the build was triggered manually or not. If not, it'll default to 'All'.
def selection = askUser(choices)
if (selection == 'All') {
buildStandardAll(builds)
} else {
buildStandardSingle(builds[selection])
private void buildStandardSingle(build)
{
build.call()
private void buildStandardAll(builds)
Vincent Massol
committed
parallel(
// Build, skipping quality checks and integration tests (but execute unit tests) so that the result of the build
// can be sent as fast as possible to the devs. Note that we skip integration tests by using the FailSafe plugin
// property "DskipITs".
// In addition, we want the generated artifacts to be deployed to our remote Maven repository so that developers
// can benefit from them even though some quality checks have not yet passed.
// In // we start a build with the quality profile that executes various quality checks, and we run all the
// integration tests just after this build.
Vincent Massol
committed
// Note: We configure the snapshot extension repository in XWiki (-Psnapshots) in the generated
// distributions to make it easy for developers to install snapshot extensions when they do manual tests.
Vincent Massol
committed
parallel(
'integration-tests' : {
// Run all integration tests, with each module in its own node to parallelize the work.
runIntegrationTests()
},
'distribution' : {
// Note: We want the following behavior:
// - if an error occurs during the previous build we don't want the subsequent builds to execute. This will
// happen since Jenkins will throw an exception and we don't catch it.
// - if the previous build has failures (e.g. test execution failures), we want subsequent builds to execute
// since failures can be test flickers for ex, and it could still be interesting to get a distribution to
// test xwiki manually.
Vincent Massol
committed
// Build the distributions
builds['Distribution'].call()
// Building the various functional tests, after the distribution has been built successfully.
// Build the Flavor Test POM, required for the pageobjects module below.
builds['Flavor Test - POM'].call()
// Build the Flavor Test PageObjects required by the functional test below that need an XWiki UI
builds['Flavor Test - PageObjects'].call()
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
// Now run all tests in parallel
parallel(
'flavor-test-ui': {
// Run the Flavor UI tests
builds['Flavor Test - UI'].call()
},
'flavor-test-misc': {
// Run the Flavor Misc tests
builds['Flavor Test - Misc'].call()
},
'flavor-test-storage': {
// Run the Flavor Storage tests
builds['Flavor Test - Storage'].call()
},
'flavor-test-escaping': {
// Run the Flavor Escaping tests
builds['Flavor Test - Escaping'].call()
},
'flavor-test-webstandards': {
// Run the Flavor Webstandards tests
// Note: -XX:ThreadStackSize=2048 is used to prevent a StackOverflowError error when using the HTML5 Nu
// Validator (see https://bitbucket.org/sideshowbarker/vnu/issues/4/stackoverflowerror-error-when-running)
builds['Flavor Test - Webstandards'].call()
},
'flavor-test-upgrade': {
// Run the Flavor Upgrade tests
builds['Flavor Test - Upgrade'].call()
Manuel Leduc
committed
},
'flavor-test-security': {
// Run the Flavor Security tests
builds['Flavor Test - Security'].call()
Vincent Massol
committed
},
'testrelease': {
// Simulate a release and verify all is fine, in preparation for the release day.
Vincent Massol
committed
},
'quality': {
// Run the quality checks
Vincent Massol
committed
}
Vincent Massol
committed
)
}
private void runIntegrationTests()
{
def itModuleList
node() {
// Checkout platform to find all IT modules so that we can then parallelize executions across Jenkins agents.
checkout skipChangeLog: true, scm: scm
}
xwikiITBuild {
modules = itModuleList
private void build(map)
node(map.node ?: '') {
buildInsideNode(map)
}
}
private void buildInsideNode(map)
// We want to get a memory dump on OOM errors.
// Make sure the memory dump directory exists (see below)
// Note that the user used to run the job on the agent must have the permission to create these directories
// Verify existence of /home/hudsonagent/jenkins_root so that we only set the oomPath if it does
def heapDumpPath = ''
def exists = fileExists '/home/hudsonagent/jenkins_root'
if (exists) {
def oomPath = "/home/hudsonagent/jenkins_root/oom/maven/${env.JOB_NAME}-${currentBuild.id}"
sh "mkdir -p \"${oomPath}\""
heapDumpPath = "-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=\"${oomPath}\""
}
xwikiBuild(map.name) {
Vincent Massol
committed
mavenOpts = map.mavenOpts ?: "-Xmx2048m -Xms512m ${heapDumpPath}"
Vincent Massol
committed
if (map.goals != null) {
goals = map.goals
}
Vincent Massol
committed
if (map.profiles != null) {
profiles = map.profiles
}
properties = map.properties
}
Vincent Massol
committed
// Keep builds for 30 days since we want to be able to see all builds if there are a lot at a given time, to be
// able to identify flickers, etc.
Vincent Massol
committed
daysToKeepStr = '30'
Thomas Mortagne
committed
// We don't need to trigger xwiki-platform monthly since it's already the case of xwiki-commons
monthlyTrigger = false
Vincent Massol
committed
if (map.pom != null) {
pom = map.pom
}
Vincent Massol
committed
if (map.mavenFlags != null) {
mavenFlags = map.mavenFlags
}
Vincent Massol
committed
if (map.sonar != null) {
sonar = map.sonar
}
Vincent Massol
committed
if (map.skipCheckout != null) {
skipCheckout = map.skipCheckout
}
Vincent Massol
committed
if (map.xvnc != null) {
xvnc = map.xvnc
}
Vincent Massol
committed
if (map.skipMail != null) {
skipMail = map.skipMail
}
// Avoid duplicate changelogs in jenkins job execution UI page
if (map.name != 'Main') {
skipChangeLog = true
}
if (map.javaTool != null) {
}
}
private void buildFunctionalTest(map)
{
def sharedPOMPrefix =
'xwiki-platform-distribution/xwiki-platform-distribution-flavor/xwiki-platform-distribution-flavor-test'
build(
name: map.name,
profiles: 'legacy,integration-tests,jetty,hsqldb,firefox',
mavenOpts: map.mavenOpts,
pom: "${sharedPOMPrefix}/${map.pom}",
properties: map.properties