How to Integrate Jenkins with Artifactory

How to Integrate Jenkins with Artifactory

Every CI/CD pipeline eventually produces something — a JAR, a Docker image, an npm package, a compiled binary — and that “something” needs a proper home. Dumping build artifacts into random S3 buckets or leaving them scattered across Jenkins workspace directories doesn’t scale. JFrog Artifactory solves this by acting as a universal artifact repository, and its integration with Jenkins is deep enough that you get build traceability, dependency resolution, and promotion workflows practically for free.

This guide covers connecting Jenkins to Artifactory, publishing and resolving artifacts, and building full promotion pipelines.

Why Jenkins + Artifactory?

Artifactory isn’t just storage — it’s a repository manager that understands package formats natively (Maven, npm, Docker, PyPI, NuGet, Go modules, and more), enforces access control, and tracks metadata about exactly which build produced which artifact. When paired with Jenkins, every artifact gets linked back to the build number, commit, and pipeline that created it, which becomes invaluable when you need to answer “which build is running in production right now, and what went into it?”

Jenkins Architecture Context

Artifactory sits downstream of your build stage — Jenkins agents compile and package your code locally, then push (deploy) the resulting artifacts to Artifactory over HTTP(S). On the flip side, Artifactory also acts as a proxy/cache for external repositories (Maven Central, npm registry, Docker Hub), so your builds can pull dependencies through Artifactory instead of directly from the public internet, giving you caching and a layer of supply-chain control.

Prerequisites

Step 1: Install the Artifactory Plugin in Jenkins

  1. Go to Manage Jenkins > Plugins > Available Plugins
  2. Search for Artifactory
  3. Install and restart Jenkins

Step 2: Configure the Artifactory Server Connection

  1. Go to Manage Jenkins > System
  2. Scroll to JFrog Platform Instances (or “Artifactory” depending on plugin version)
  3. Click Add JFrog Platform Instance
  4. Enter:
    • Instance ID: artifactory-server (you’ll reference this in pipelines)
    • URL: https://your-artifactory-instance.jfrog.io or your self-hosted URL
    • Credentials: create/select a Jenkins credential containing your Artifactory API key or access token

Test the connection before saving to confirm Jenkins can actually reach Artifactory.

Step 3: Generate an Artifactory Access Token

  1. Log in to Artifactory
  2. Go to User Profile > Generate Access Token (or Identity and Access > Access Tokens on newer versions)
  3. Scope it appropriately (read/write to specific repositories rather than admin-wide)
  4. Copy the token and store it in Jenkins as a Secret text credential

Step 4: Publishing Maven Artifacts

For Maven projects, Artifactory’s plugin can wrap your Maven build to automatically capture and publish build info alongside the artifact:

pipeline {
    agent any

    tools {
        maven 'Maven-3.9'
        jdk 'JDK-17'
    }

    stages {
        stage('Checkout') {
            steps {
                git branch: 'main', url: 'https://github.com/yourorg/java-app.git'
            }
        }

        stage('Artifactory Configure') {
            steps {
                script {
                    server = Artifactory.server 'artifactory-server'
                    rtMaven = Artifactory.newMavenBuild()
                    rtMaven.tool = 'Maven-3.9'
                    rtMaven.deployer releaseRepo: 'libs-release-local', snapshotRepo: 'libs-snapshot-local', server: server
                    rtMaven.resolver releaseRepo: 'libs-release', snapshotRepo: 'libs-snapshot', server: server
                }
            }
        }

        stage('Build and Deploy to Artifactory') {
            steps {
                script {
                    def buildInfo = rtMaven.run pom: 'pom.xml', goals: 'clean install'
                    server.publishBuildInfo buildInfo
                }
            }
        }
    }
}

This pattern deploys the artifact and pushes build metadata (source commit, dependencies used, environment) to Artifactory, giving you full traceability.

Step 5: Publishing Generic Artifacts (Any File Type)

For projects that don’t map to Maven/npm/Docker directly, use the generic upload spec approach:

stage('Package') {
    steps {
        sh 'zip -r myapp-${BUILD_NUMBER}.zip ./dist'
    }
}

stage('Upload to Artifactory') {
    steps {
        script {
            def server = Artifactory.server 'artifactory-server'
            def uploadSpec = """{
                "files": [
                    {
                        "pattern": "myapp-${BUILD_NUMBER}.zip",
                        "target": "generic-releases-local/myapp/${BUILD_NUMBER}/"
                    }
                ]
            }"""
            def buildInfo = server.upload spec: uploadSpec
            server.publishBuildInfo buildInfo
        }
    }
}

Step 6: Publishing Docker Images to Artifactory

Artifactory can act as a private Docker registry:

stage('Build Docker Image') {
    steps {
        sh "docker build -t your-artifactory-instance.jfrog.io/docker-local/myapp:${BUILD_NUMBER} ."
    }
}

stage('Push to Artifactory Docker Registry') {
    steps {
        script {
            def server = Artifactory.server 'artifactory-server'
            def rtDocker = Artifactory.docker server: server
            rtDocker.push "your-artifactory-instance.jfrog.io/docker-local/myapp:${BUILD_NUMBER}", 'docker-local'
        }
    }
}

Step 7: Publishing npm Packages

stage('Artifactory Configure') {
    steps {
        script {
            server = Artifactory.server 'artifactory-server'
            rtNpm = Artifactory.newNpmBuild()
            rtNpm.deployer server: server, repo: 'npm-local'
            rtNpm.resolver server: server, repo: 'npm-remote'
        }
    }
}

stage('npm Install and Publish') {
    steps {
        script {
            rtNpm.install()
            def buildInfo = rtNpm.publish()
            server.publishBuildInfo buildInfo
        }
    }
}

Using Artifactory as the npm resolver too (not just publish target) means your builds pull dependencies through Artifactory’s cache rather than hitting the public npm registry directly on every build.

Step 8: Artifact Promotion Workflows

One of Artifactory’s most valuable features is promotion — moving an artifact from a “candidate” repository to a “release” repository once it’s passed further validation, without rebuilding it. This guarantees the exact bits that were tested are the exact bits that ship.

stage('Promote Build') {
    when {
        branch 'main'
    }
    steps {
        script {
            def server = Artifactory.server 'artifactory-server'
            def promotionConfig = [
                'buildName'    : env.JOB_NAME,
                'buildNumber'  : env.BUILD_NUMBER,
                'targetRepo'   : 'libs-release-local',
                'sourceRepo'   : 'libs-snapshot-local',
                'comment'      : 'Promoted after passing QA',
                'status'       : 'Released',
                'copy'         : true
            ]
            server.promote promotionConfig
        }
    }
}

This is often gated behind a manual approval or a downstream QA pipeline succeeding, so promotion only happens for artifacts that have genuinely proven themselves.

Step 9: Using Artifactory as a Dependency Proxy

Beyond publishing, configure your build tools to resolve dependencies through Artifactory rather than directly from public repositories. For Maven, this means updating settings.xml:

<mirrors>
  <mirror>
    <id>artifactory</id>
    <mirrorOf>*</mirrorOf>
    <url>https://your-artifactory-instance.jfrog.io/artifactory/libs-remote</url>
  </mirror>
</mirrors>

This gives you caching (faster, more reliable builds not dependent on Maven Central’s uptime) and lets you enforce policies about which external packages are allowed.

Troubleshooting

“401 Unauthorized” when deploying: The Artifactory credential in Jenkins is either expired or doesn’t have deploy permission on the target repository — verify scope in Artifactory’s Access Tokens admin page.

Build info doesn’t appear in Artifactory: Confirm you’re calling server.publishBuildInfo buildInfo after the build/upload step — it’s a separate call from the actual artifact upload.

Docker push fails with “repository does not exist”: The target Docker repository must be created in Artifactory first (as a Docker-type local repository) before you can push to it.

Slow builds due to dependency resolution: Check that your build tool is actually configured to resolve through Artifactory’s remote/virtual repository, not falling back to the public internet.

Security Best Practices

FAQs

What’s the difference between Artifactory and a plain S3 bucket for artifact storage? Artifactory understands package formats natively (dependency resolution, metadata, versioning rules) and provides build traceability, access control, and promotion workflows that a plain object store doesn’t offer out of the box.

Can Artifactory replace Docker Hub for my private images? Yes, Artifactory can function as a full private Docker registry, and also proxy/cache public Docker Hub images to reduce external pull rate limits.

Do I need JFrog Xray for security scanning, or is that separate from Artifactory? Xray is a separate JFrog product that integrates with Artifactory for vulnerability and license scanning — Artifactory alone handles storage and metadata but not deep security analysis.

How does artifact promotion differ from just rebuilding for production? Promotion moves the exact same tested binary/artifact between repositories without rebuilding, which avoids the risk of a rebuild producing subtly different bits due to dependency drift or environment differences.

Can I use both Artifactory and a plain Maven/npm public registry in the same project? Yes, though it’s generally cleaner to route everything through Artifactory as a virtual repository that itself proxies the public registries, giving you one consistent resolution path.

What happens if Artifactory is temporarily unreachable during a build? Builds that depend on Artifactory for dependency resolution will fail or stall until connectivity is restored, which is why production Artifactory instances are usually deployed with high availability in mind. For smaller teams, monitoring Artifactory’s uptime the same way you’d monitor any other critical infrastructure component is worth the effort.

Does Artifactory retain every single build artifact forever? Not by default — configure retention policies per repository to automatically clean up old snapshot or candidate builds while keeping release artifacts indefinitely, which keeps storage costs under control without risking accidental deletion of anything that matters.

Summary

Integrating Jenkins with Artifactory turns your build artifacts from scattered files into properly versioned, traceable, access-controlled assets. The Artifactory plugin handles the heavy lifting of publishing build info alongside artifacts across Maven, npm, Docker, and generic file types, and promotion workflows let you move validated artifacts toward release without rebuilding. Once configured, you get a complete, auditable trail from source commit to deployed artifact — exactly the kind of traceability that matters when something breaks in production and you need to know precisely what’s running.

References

Exit mobile version