Jenkins Multibranch Pipeline Configuration
Overview
Purpose
Multibranch Pipelines allow Jenkins to automatically discover and build branches in a repository. This ensures that every branch with a
Jenkinsfileis automatically built and tested.
Scope
Configuration of Multibranch Pipeline jobs in Jenkins using GitLab Branch Sources.
Audience
CORE, DEV
Prerequisites
- Jenkins is installed and running (see Jenkins Installation).
- Access to the GitLab instance:
https://gitlab.quintessence.net. - A repository containing a
Jenkinsfile.
Step-by-Step Configuration
Create a New Item
- Log in to the Jenkins GUI.
- Click on New Item in the left sidebar.
- Enter a name for the job (e.g.,
quintessence-pipeline-name). - Select Multibranch Pipeline and click OK.
Branch Sources (GitLab)
- In the job configuration, scroll down to the Branch Sources section.
- Click Add source and select GitLab Project.
- Checkout Credentials: Select the appropriate credentials for GitLab access.
- Owner: Enter the group id.
- Projects: Select the specific project from the dropdown.
- Behaviors:
- Discover branches: Usually set to "All branches".
- Discover merge requests from origin: Optional, depending on workflow.
Build Configuration
- Scroll to the Build Configuration section.
- Mode: Select "by Jenkinsfile".
- Script Path: Ensure it points to the
Jenkinsfilein your repository (default isJenkinsfile).
Webhook Configuration
Since we use GitLab Branch Sources, triggers are handled via webhooks. Ensure that the GitLab project has a webhook configured pointing to your Jenkins instance to trigger builds on push or merge request events.
Example Jenkinsfile
Most projects use a declarative pipeline style. Below is the standard template used for our Maven-based projects:
pipeline {
agent any
options {
disableConcurrentBuilds()
}
tools {
maven "Maven 3.9"
jdk "Java 8"
}
parameters {
booleanParam(name: 'RELEASE', defaultValue: false, description: 'Run release build (true = direct mvn, false = withMaven)')
}
environment {
MAVEN_OPTS = "-Xms512m -Xmx1024m -Dmaven.test.failure.ignore=false -XX:+AlwaysPreTouch -XX:+UseG1GC -XX:+ExplicitGCInvokesConcurrent -XX:+ParallelRefProcEnabled -XX:+UseStringDeduplication -XX:+UnlockExperimentalVMOptions -XX:G1NewSizePercent=20 -XX:+UnlockDiagnosticVMOptions -XX:G1SummarizeRSetStatsPeriod=1"
RELEASE = "${params.RELEASE}"
}
// Build trigger configuration
triggers {
snapshotDependencies()
}
stages {
stage("Clean Workspace") {
steps {
cleanWs()
}
}
stage("Checkout") {
steps {
checkout scm
}
}
stage("Compile") {
steps {
script {
if (params.RELEASE) {
sh "mvn -U clean compile"
} else {
withMaven(maven: "Maven 3.9") {
sh "mvn -U clean compile"
}
}
}
}
}
stage("Test") {
steps {
script {
if (params.RELEASE) {
sh "mvn test"
} else {
withMaven(maven: "Maven 3.9") {
sh "mvn test"
}
}
}
}
}
stage('SonarQube Analysis') {
steps {
script {
def java17Home = tool name: 'Java 17', type: 'jdk'
withEnv(["JAVA_HOME=${java17Home}", "PATH=${java17Home}/bin:${env.PATH}"]) {
withSonarQubeEnv('sonarqube') {
if (params.RELEASE) {
sh "mvn sonar:sonar -Dsonar.login=${SONAR_AUTH_TOKEN}"
} else {
withMaven(maven: "Maven 3.9") {
sh "mvn sonar:sonar -Dsonar.login=${SONAR_AUTH_TOKEN}"
}
}
}
}
sh 'rm -rf reports'
}
}
}
stage('Quality Gate') {
steps {
timeout(time: 1, unit: 'MINUTES') {
waitForQualityGate abortPipeline: true
}
}
}
stage("Deploy") {
steps {
script {
if (params.RELEASE) {
sh "mvn deploy -DskipTests -P nexus3"
} else {
withMaven(maven: "Maven 3.9") {
sh "mvn deploy -DskipTests -P nexus3"
}
}
}
}
}
}
post {
unstable {
emailext(
subject: "Build Unstable: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
body: """See <${env.BUILD_URL}display/redirect?page=changes>
Changes:
${getChanges()}
Stacktrace:
${currentBuild.rawBuild.getLog(100).join('\n')}
""",
recipientProviders: [
[$class: 'CulpritsRecipientProvider'],
[$class: 'RequesterRecipientProvider']
]
)
}
failure {
emailext(
subject: "Build FAILED: ${env.JOB_NAME} #${env.BUILD_NUMBER}",
body: """See <${env.BUILD_URL}display/redirect?page=changes>
Changes:
${getChanges()}
Stacktrace:
${currentBuild.rawBuild.getLog(100).join('\n')}
""",
recipientProviders: [
[$class: 'CulpritsRecipientProvider'],
[$class: 'RequesterRecipientProvider']
]
)
}
}
}
def getChanges() {
def changes = ""
def changeSets = currentBuild.changeSets
if (changeSets) {
changeSets.each { changeSet ->
changeSet.items.each { item ->
changes += "[${item.author}] ${item.msg}\n"
}
}
} else {
changes = "No changes found."
}
return changes
}
Validation & Testing
- Check the Scan Multibranch Pipeline Log to ensure the repository is being scanned correctly.
- Verify that each branch is listed and has its own build history.
Troubleshooting
- No branches found: Check credentials and repository URL.
- Jenkinsfile not found: Ensure the
Jenkinsfileis in the root of the branch or theScript Pathis correct. - Webhook issues: Verify the GitLab webhook configuration pointing to
https://jenkins.quintessence.de/project-name/.
References & Links
Changelog
| Date | Author | Message |
|---|---|---|
| 2026-02-25 | aresnikowa | Merge remote-tracking branch 'origin/master' |