What Is the Parent POM in Jenkins? Understanding Maven Inheritance in jenkinsci/jenkins

The parent POM in Jenkins serves as the centralized configuration anchor for the entire multi-module Maven build, defining shared versions, plugin management, and build rules that all sub-modules automatically inherit.

Jenkins is architected as a multi-module Maven project within the jenkinsci/jenkins repository. The root pom.xml—the parent POM—acts as the single source of truth, ensuring that components such as the core library, WAR file, and CLI tool all build with identical dependency versions and consistent Maven settings.

Centralized Version Management

In pom.xml lines 75-78, the parent defines critical version properties including <revision> and <changelist>. These properties establish the baseline version for the entire project:

<revision>2.576</revision>
<changelist>-SNAPSHOT</changelist>

Every child module references these properties using ${revision} and ${changelist}, guaranteeing that a single property change propagates consistently across the entire codebase. The parent also declares the bundled Remoting version as ${remoting.version} (set to 3384.v60d89463d9e0 at lines 89-91), which modules reference without hardcoding specific version numbers.

Plugin and Dependency Version Control

The parent POM prevents "dependency drift" through centralized <pluginManagement> and <dependencyManagement> sections (lines 37-91). By pinning exact versions of Maven plugins such as maven-compiler-plugin, spotless-maven-plugin, and bridge-method-injector in one location, all modules use identical build tools without declaring versions locally.

This inheritance mechanism ensures that when the Jenkins project upgrades a plugin version, the change applies immediately to every module—core, war, cli, and others—without requiring individual POM edits.

Shared Build Configuration

Common build resources and enforcement rules are defined once in the parent (lines 124-140 and 442-458) and inherited by all children. This includes:

  • Default goals: <defaultGoal>install</defaultGoal>
  • Resource filtering: Standard resource directories and filtering rules
  • Maven Enforcer: Rules for banned dependencies and required Maven versions

Child modules automatically adopt these standards, focusing their own pom.xml files on module-specific dependencies and source code rather than repetitive build boilerplate.

Repository and SCM Declarations

Rather than duplicating repository metadata in every module, the parent POM declares the public Jenkins Maven repository and SCM connections (lines 110-118). This eliminates redundancy and ensures that mvn commands execute against the correct artifact repositories regardless of which subdirectory a developer builds from.

Module Aggregation

The <modules> section (lines 52-60) enumerates all sub-projects including core, war, cli, and others. This aggregation allows Maven to calculate the correct build order when you run commands from the repository root, ensuring that dependencies compile before the modules that require them.

Profile Management for CI/CD

CI-specific profiles such as yarn-execution, debug, and release are defined centrally (lines 274-381) and become available to every module. These profiles handle Node.js integration, GPG signing for releases, and debug flags without requiring each child POM to redefine the configuration.

How Child Modules Inherit from the Parent

Each child module declares its lineage through a <parent> block. For example, in core/pom.xml, the module identifies the parent as org.jenkins-ci.main:jenkins-parent, inheriting all managed versions and build configurations:

<parent>
    <groupId>org.jenkins-ci.main</groupId>
    <artifactId>jenkins-parent</artifactId>
    <version>${revision}${changelist}</version>
</parent>

This inheritance chain extends further: the root pom.xml itself declares a parent pointing to the jenkins BOM (Bill of Materials) at lines 28-33, establishing a hierarchical version management strategy.

Practical Examples of Parent POM Inheritance

Inheriting Compiler Configuration Without Version Declarations

Child modules do not specify plugin versions for standard build tools:

<!-- In core/pom.xml -->
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <!-- Version inherited from parent's pluginManagement -->
        </plugin>
    </plugins>
</build>

Referencing Parent-Defined Properties

Modules consume the Remoting version defined centrally:

<dependency>
    <groupId>org.jenkins-ci.main</groupId>
    <artifactId>remoting</artifactId>
    <version>${remoting.version}</version>
</dependency>

The ${remoting.version} property resolves to 3384.v60d89463d9e0 as defined in the root pom.xml.

Leveraging Plugin Management

Adding a plugin like build-helper-maven-plugin requires no version declaration:

<build>
    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>build-helper-maven-plugin</artifactId>
            <!-- Version supplied by parent POM -->
        </plugin>
    </plugins>
</build>

Key Files in the Jenkins Maven Structure

  • pom.xml (root): Defines the parent POM, shared properties, plugin versions, modules, and profiles.
  • core/pom.xml: Jenkins core module inheriting all parent settings.
  • war/pom.xml: Constructs the jenkins.war artifact using parent-defined versions.
  • cli/pom.xml: Command-line interface module leveraging parent's dependency management.
  • bom/pom.xml: Bill of Materials providing curated dependency versions for downstream projects.

Summary

  • The parent POM in jenkinsci/jenkins is the root pom.xml that centralizes version properties, plugin management, and build configuration.
  • It defines <revision> and <changelist> properties (lines 75-78) that all modules reference for consistent versioning.
  • <pluginManagement> and <dependencyManagement> sections (lines 37-91) prevent version drift across the multi-module project.
  • The <modules> section (lines 52-60) aggregates sub-projects like core, war, and cli for unified builds.
  • Child modules inherit settings via <parent> declarations, eliminating duplicate configuration in core/pom.xml, war/pom.xml, and other sub-modules.
  • CI-specific profiles and repository definitions are maintained centrally, ensuring consistent build behavior across all components.

Frequently Asked Questions

How does a child module override a plugin version defined in the parent POM?

A child module can declare a specific <version> within its <plugin> declaration, which takes precedence over the parent's <pluginManagement> configuration. However, the Jenkins project typically discourages this to maintain build consistency across the entire codebase.

What is the relationship between the root pom.xml and the bom/pom.xml?

The root pom.xml serves as the immediate parent for Jenkins modules, while bom/pom.xml (Bill of Materials) provides a curated set of dependency versions often imported as a managed dependency. The root POM may itself inherit from or import this BOM (lines 28-33 reference the grand-parent jenkins artifact), creating a layered version management strategy that benefits both internal modules and external Jenkins plugins.

Where is the Jenkins version number actually defined?

The version is defined in the <properties> section of the root pom.xml at lines 75-78, specifically through the <revision> and <changelist> properties. During the build, these concatenate to form the full version identifier (e.g., 2.576-SNAPSHOT) used throughout all modules.

Can I build a single module without building the entire Jenkins project?

Yes. While the parent POM aggregates modules for full builds, you can navigate to a specific module directory like core/ or cli/ and run mvn install. The child POM inherits sufficient configuration from the parent (accessible in your local Maven repository) to build independently, though initial builds may require the parent POM to be installed first.

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 →