How to Customize the Jenkins Build Process with Maven: A Complete Guide

Jenkins provides a dedicated Maven builder (hudson.tasks.Maven) that lets you customize builds through executable selection, JVM options, settings files, and automatic environment variable injection.

Customizing the Jenkins build process with Maven is essential for teams requiring fine-grained control over their CI/CD pipelines. According to the jenkinsci/jenkins source code, the hudson.tasks.Maven class implements a flexible builder that manages everything from tool resolution to argument construction. Understanding these internals allows you to optimize builds for performance, isolation, and reproducibility.

Core Components of the Maven Build System

The Maven integration relies on three primary classes working together:

Component Source File Purpose
Maven Builder core/src/main/java/hudson/tasks/Maven.java The build step that launches Maven, parses targets, and assembles command lines.
MavenInstallation Inner class of Maven.java Represents a Maven installation, resolves the executable path, and configures environment variables like M2_HOME and PATH+MAVEN.
GlobalMavenConfig core/src/main/java/jenkins/mvn/GlobalMavenConfig.java Supplies default settings.xml and global-settings.xml paths that can be overridden per-job.

How the Maven Builder Executes Your Build

The perform method in hudson/tasks/Maven.java orchestrates execution through six distinct phases:

  1. Target Parsing – The targets field splits on the pipe character (|), allowing multiple Maven invocations in a single build step (e.g., "clean install | site").

  2. Executable Resolution – If mavenName references a MavenInstallation, Jenkins calls MavenInstallation.getExecutable to locate the binary. If unconfigured, DecideDefaultMavenCommand inspects the workspace for pom.xml to choose between mvn or maven.

  3. Settings Handling – Unless the user passes -s or -gs arguments, the builder injects paths from SettingsProvider.getSettingsRemotePath and GlobalSettingsProvider.getSettingsRemotePath.

  4. Environment Injection – When injectBuildVariables is true (default), Jenkins automatically adds -D arguments for all build variables before appending custom properties from the properties field.

  5. Private Repository Isolation – Setting usePrivateRepository to true adds -Dmaven.repo.local=$WORKSPACE/.repository to isolate dependencies per build.

  6. Process Launch – The assembled ArgumentListBuilder is passed to Launcher.launch(). On Unix, the command executes directly; on Windows, it converts to a batch command.

Customization Points and Configuration Fields

You can configure these fields in the job UI or through Pipeline steps:

Field Control Example
targets Maven goals and CLI options "clean package -DskipTests"
mavenName Reference to a MavenInstallation "Maven-3.9"
pom Relative path to POM file "submodule/pom.xml"
properties Additional -D properties (newline-separated) "env=prod\nopt=true"
jvmOptions Memory and JVM settings (MAVEN_OPTS) "-Xmx2g -XX:+UseG1GC"
usePrivateRepository Boolean for isolated local repos true
settings / globalSettings Custom XML configuration files FilePathSettingsProvider instance
injectBuildVariables Automatic -D variable injection true (default)

Configuring Maven Installations Globally

Before customizing individual jobs, define your Maven tools:

  1. Navigate to Manage Jenkins → Global Tool Configuration → Maven.
  2. Add a MavenInstallation specifying the name and MAVEN_HOME directory, or enable the automatic installer (implemented in the inner class MavenInstaller).
  3. The Maven.DescriptorImpl class persists these configurations via the setInstallations method.

Jenkins stores this metadata to resolve executables via MavenInstallation.getExecutable at runtime.

Using Maven in Jenkins Pipelines

For Pipeline projects, use the tools directive to expose the installation, then invoke Maven directly or through the builder:

pipeline {
    agent any
    tools {
        maven 'Maven-3.9'  // Must match a configured MavenInstallation name
    }
    environment {
        APP_ENV = 'production'
    }
    stages {
        stage('Build') {
            steps {
                sh '''
                    mvn clean install \
                        -Dmaven.repo.local=$WORKSPACE/.repository \
                        -Dapp.env=$APP_ENV
                '''
            }
        }
    }
}

Alternatively, the withMaven step wraps the same hudson.tasks.Maven logic and accepts parameters like mavenSettingsConfig and injectBuildVariables: false for advanced customization.

Advanced Customization Scenarios

Scenario Implementation
Version-per-branch builds Define separate MavenInstallation entries (e.g., Maven-3.8, Maven-3.9) and parameterize the mavenName field.
Custom settings.xml per job Configure the Settings file option to use a FilePathSettingsProvider, which overrides GlobalMavenConfig defaults for that specific build.
Disable variable injection Set injectBuildVariables to false in the UI or Pipeline to prevent automatic -D argument generation.
Chained Maven commands Use pipe syntax in targets: `"clean deploy

Summary

  • The hudson.tasks.Maven class is the core engine for Maven integration, handling command assembly in its perform method.
  • Configure MavenInstallation instances globally to manage multiple Maven versions and automatic downloads.
  • Use injectBuildVariables to automatically pass Jenkins environment variables as Maven properties, or disable it for stricter control.
  • Enable usePrivateRepository to ensure build isolation through per-workspace local repositories.
  • Override global settings via GlobalMavenConfig or per-job providers like FilePathSettingsProvider.

Frequently Asked Questions

How do I specify a custom Maven version for a specific job?

Define multiple MavenInstallation entries in Global Tool Configuration, then reference the specific installation name in your job configuration via the mavenName field. In Pipeline, use the tools { maven 'InstallationName' } block.

Where does Jenkins find the settings.xml file?

By default, Jenkins reads paths from GlobalMavenConfig.java. You can override this per-job by selecting a custom provider (such as FilePathSettingsProvider) in the build step configuration, or by passing explicit -s and -gs arguments in your targets.

Can I run multiple Maven commands in a single build step?

Yes. Enter multiple commands separated by the pipe character (|) in the Goals and options field. Jenkins executes them sequentially while maintaining the same environment variables and working directory.

How do I disable automatic injection of Jenkins variables?

Set the injectBuildVariables field to false in the Maven build step configuration. In Pipeline syntax using the withMaven step, specify injectBuildVariables: false to prevent the builder from automatically passing build parameters as system properties.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →