Jenkins Artifact Management with Maven: How the ArtifactManager Framework Handles Build Outputs

Jenkins delegates all artifact storage to the ArtifactManager API, where StandardArtifactManager writes files to $JENKINS_HOME by default, while the Maven builder (hudson.tasks.Maven) produces the build outputs that ArtifactArchiver later collects and stores.

The jenkinsci/jenkins repository separates the concerns of how Maven runs from where its outputs are stored. When you configure Jenkins artifact management with Maven, the build proceeds through distinct phases: the Maven builder executes goals and places files in the workspace, then the artifact manager handles persistence via a pluggable backend architecture.

How the Maven Builder Configures the Build Environment

The Maven builder, implemented in core/src/main/java/hudson/tasks/Maven.java, is a standard Builder that prepares the Maven execution context before any artifacts are produced. Its constructor captures the build configuration:

public Maven(String targets,
             String name,
             String pom,
             String properties,
             String jvmOptions,
             boolean usePrivateRepository,
             SettingsProvider settings,
             GlobalSettingsProvider globalSettings,
             boolean injectBuildVariables) { … }

Key fields determine how Maven interacts with the workspace:

  • targets – Maven goals such as clean install that produce JARs and WARs.
  • usePrivateRepository – Enables -Dmaven.repo.local=<workspace>/.repository to isolate dependencies per build.
  • settings / globalSettings – References to SettingsProvider implementations that supply settings.xml; fall back to GlobalMavenConfig when null.
  • injectBuildVariables – When true, Jenkins automatically passes build variables as Maven properties (-Dkey=value).

During execution, the builder resolves the MavenInstallation via getMaven() and launches the process through a Launcher. Once Maven completes, control passes to post-build steps, typically beginning with ArtifactArchiver.

The Artifact Archiving Pipeline

When a job includes the "Archive the artifacts" post-build action, Jenkins instantiates ArtifactArchiver from core/src/main/java/hudson/tasks/ArtifactArchiver.java. Its perform method delegates to the active artifact manager:

build.pickArtifactManager().archive(
        ws,
        launcher,
        BuildListenerAdapter.wrap(listener),
        files);

The files parameter is a Map<String,String> mapping workspace-relative paths to archive-relative destinations. The manager selection occurs at runtime through Run.pickArtifactManager() in core/src/main/java/hudson/model/Run.java.

StandardArtifactManager: The Default On-Disk Implementation

If no custom manager claims the build, pickArtifactManager() returns a StandardArtifactManager instance:

return new StandardArtifactManager(this);

Located in core/src/main/java/jenkins/model/StandardArtifactManager.java, this implementation writes artifacts to $JENKINS_HOME/jobs/<job>/builds/<buildNumber>/archive. It exposes three core operations:

  • archive(FilePath workspace, …) – Copies files from the workspace to the build-specific archive directory.
  • delete() – Removes the entire archive directory for the build.
  • root() – Returns a VirtualFile representing the archive root for UI browsing and API access.

Compression behavior is controlled by the StandardArtifactManager.TAR_COMPRESSION setting.

Custom Artifact Managers via Factory Pattern

Plugins can replace the default storage backend by implementing ArtifactManagerFactory from core/src/main/java/jenkins/model/ArtifactManagerFactory.java. The system iterates through registered factories in ArtifactManagerConfiguration (located in core/src/main/java/jenkins/model/ArtifactManagerConfiguration.java) to select the first compatible manager:

for (ArtifactManagerFactory f : ArtifactManagerConfiguration.get().getArtifactManagerFactories()) {
    ArtifactManager mgr = f.managerFor(this);
    if (mgr != null) return mgr;
}

This pattern enables external storage such as S3, Artifactory, or Azure Blob without modifying the Maven build configuration.

Maven-Specific Artifact Flow

Maven builds follow a predictable path through the artifact management system:

  1. Production Phase – The Maven builder executes mvn clean install, generating JARs, WARs, and POMs inside target/ directories within the workspace.
  2. Collection Phase – ArtifactArchiver evaluates patterns like **/target/*.jar against the workspace and constructs the file map.
  3. Storage Phase – The selected ArtifactManager persists files to the configured backend, whether local disk or remote storage.
  4. Retrieval Phase – The Jenkins UI renders the artifact tree via Run.getArtifactManager().root(), allowing direct downloads of specific files.

Because the ArtifactManager interface is agnostic to the build tool, the same archiving infrastructure handles Maven, Gradle, and shell script outputs uniformly.

Configuration Examples

Freestyle Job XML Configuration

The following configuration uses the Maven builder with a private repository and archives all JAR files produced in target/ directories:

<project>
  <builders>
    <hudson.tasks.Maven>
      <targets>clean install</targets>
      <mavenName>DefaultMaven</mavenName>
      <pom>pom.xml</pom>
      <properties></properties>
      <usePrivateRepository>true</usePrivateRepository>
    </hudson.tasks.Maven>
  </builders>

  <publishers>
    <hudson.tasks.ArtifactArchiver>
      <artifacts>**/target/*.jar</artifacts>
      <allowEmptyArchive>false</allowEmptyArchive>
      <onlyIfSuccessful>true</onlyIfSuccessful>
      <fingerprint>false</fingerprint>
      <defaultExcludes>true</defaultExcludes>
      <caseSensitive>true</caseSensitive>
    </hudson.tasks.ArtifactArchiver>
  </publishers>
</project>

The usePrivateRepository element ensures each build uses an isolated local Maven repository under the workspace.

Declarative Pipeline Configuration

In a Jenkins Pipeline, the archiveArtifacts step wraps the ArtifactArchiver functionality and automatically uses the currently configured ArtifactManager:

pipeline {
    agent any
    tools {
        maven 'DefaultMaven'
    }
    stages {
        stage('Build') {
            steps {
                sh 'mvn clean install -Dmaven.repo.local=$WORKSPACE/.m2/repository'
            }
        }
    }
    post {
        success {
            archiveArtifacts artifacts: '**/target/*.jar', fingerprint: true
        }
    }
}

The tools directive references a Maven installation defined in Global Tool Configuration, while the post section ensures artifacts are only archived for successful builds.

Summary

Frequently Asked Questions

Where does Jenkins store Maven artifacts by default?

By default, Jenkins stores Maven artifacts in the local file system under $JENKINS_HOME/jobs/<job-name>/builds/<build-number>/archive using StandardArtifactManager. This location is accessible through the build's Artifacts page in the web UI and via the REST API through Run.getArtifactManager().root().

How do I configure a custom artifact manager for Maven builds?

Install a plugin that provides an ArtifactManagerFactory implementation (such as the S3 Artifact Manager). Navigate to Manage Jenkins > Configure System, locate the Artifact Management for Builds section, and select your custom manager. When Run.pickArtifactManager() executes, it will select your factory instead of the default StandardArtifactManager, redirecting all Maven build artifacts to the external storage backend.

What is the difference between the Maven builder and the ArtifactArchiver?

The Maven builder (hudson.tasks.Maven) is a build step that executes Maven goals and populates the workspace with compiled outputs. The ArtifactArchiver (hudson.tasks.ArtifactArchiver) is a post-build step that collects files matching specified patterns and delegates them to the active ArtifactManager for persistent storage. The builder produces artifacts; the archiver persists them.

How does Jenkins handle Maven settings.xml during artifact archiving?

While ArtifactArchiver does not directly interact with settings.xml, the Maven builder uses the SettingsProvider interface (configured in the job or inherited from GlobalMavenConfig in core/src/main/java/jenkins/mvn/GlobalMavenConfig.java) to determine repository authentication and deployment settings during the build phase. These settings influence which artifacts Maven produces in the workspace, but the archiving phase itself is settings-agnostic and simply stores whatever files Maven leaves in target/ directories.

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 →