ARTIFACTORY: Integrate Artifactory with Bazel

AuthorFullName__c
Michael Akushky
articleNumber
000005942
FirstPublishedDate
2023-12-25T13:59:44Z
lastModifiedDate
2025-05-14

ARTIFACTORY: Integrate Artifactory with Bazel

Bazel is a popular build tool within the DevOps community due to its high performance, scale, and reliability. Bazel supports remote caching, making it a perfect pairing for JFrog Artifactory as a solution for storing build artifacts, build metadata and dependency resolution. Use the Bazel integration with Artifactory to streamline software development, and ensure swift, consistent builds and robust artifact management. 

This article provides a guide for integrating Bazel with Artifactory, empowering you to create efficient, reliable software workflows. Whether you are new to these tools or looking to enhance your existing setup, use the best practices in this document to harness the full potential of these tools in unison. 

Integration Points with Artifactory

JFrog Artifactory has two main integration points with Bazel that can be used either together or separately:


User-added image 
 

Prerequisites for Integrating Bazel with Artifactory

To integrate Bazel with Artifactory, you need first to configure the following: 

  • Bazel  - a running environment.
  • Artifactory - Access to your JFrog Artifactory with permissions to create repositories.
Bazel 

Make sure you have access to a running Bazel environment: It is recommended to use Bazelisk. This utility makes it easier for developers to work with different Bazel releases across projects and switch between Bazel versions seamlessly. Bazelisk automatically downloads and installs the specified version of Bazel, ensuring compatibility with your project's requirements and enhancing the flexibility and efficiency of your development environment. 

Artifactory

Make sure you have access to your JFrog Artifactory instance either in Self-Hosted or Cloud subscriptions: creating repositories in Artifactory is the main capability you need permissions for and of course a user credentials for you Bazel build to push & pull artifacts. If you are interested in simply testing this setup, we invite you to sign up for a Free Trial .

Set Up Artifactory as a Bazel Remote Cache Storage

Setting up your Bazel project to publish build artifacts to JFrog Artifactory requires that you create a Generic local repository that will serve as your Bazel remote cache. 

Please note that this setup involves security and access control considerations so we recommend that you only authorize specific users/build users to access and modify the cached artifacts.

To set up Artifactory as a Bazel remote cache storage using a generic local repository, perform the following stages
1. Create a Generic Repository
2. Configure Artifactory as your Bazel Remote Cache
3. Optional: Validate the Connection
 

Stage 1: Create a Generic Repository

To create a generic repository: 

  1. Click your username in the top right and select New Local Repository from the drop-down menu
  2. Select Generic as the package type
  3. Enter a repository key and any other settings and click Create Local Repository 

User-added image

Stage 2: Configure Artifactory as your Bazel Remote Cache

To configure the generic repository you just created as your Bazel remote cache, run the bazel build command with the --remote_cache parameter pointing to your local repository. Go to the Generic repository Set-Me-Up menu to find your username, token, and JFrog host domain. 

User-added image

Make sure to replace the placeholders in ​bold​​ with your own username, password, JFrog host domain, and repository path.
 

bazel build --remote_cache=http://<USERNAME>:<TOKEN>@<JFROG_HOST_DOMAIN>/<GENERIC_REPOSITORY_PATH>


During the build process, action result metadata is stored under the path /ac/, and output files are stored under the path /сas/, to be reused during the next build executions.
 

User-added image

Stage 3: Validate the Connection

Verify that the integration was successful by finding the PUT and GET requests from the HTTP caching protocol in your Artifactory logs.

Bazel supports remote caching via the HTTP/1.1. protocol which uploads binary data (BLOB) via PUT requests, and downloads it via GET requests. 

For example, for an environment with a Bazel remote cache where: 

  • Generic repository name = cache-bazel
  • JFrog Host Domain = http://localhost:8082/artifactory/cache-bazel
  • SHA256 value of the action to upload/ download= 01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b


The PUT request will appear in the logs like this: 
 

PUT /artifactory/cache-bazel/cas/15e2b0d3c33891ebb0f1ef609ec419420c20e320ce94c65fbc8c3312448eb225 HTTP/1.1
Host: localhost:8082
Accept: */*
Content-Length: 9
Connection: Keep-Alive

0x310x320x330x340x350x360x370x380x39


The GET request will appear in the logs like this: 
 

GET /artifactory/cache-bazel/ac/01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b HTTP/1.1
Host: localhost:8082
Accept: */*
Connection: Keep-Alive
Set Up Artifactory as a Bazel Dependencies Cache

You can configure an Artifactory Maven repository to act as a Bazel dependencies cache using the rules_jvm_external Bazel ruleset. This ruleset simplifies the management of external Java dependencies and integrates them seamlessly into your Bazel builds, so you can declare and manage dependencies from popular sources like Artifactory. 

This section contains the following examples: 
Set Up Artifactory to Resolve Bazel Dependencies

See the following example of how to configure the rules_jvm_external ruleset in a BUILD file to define and use external Java dependencies in a Bazel project: 

Make sure to replace the placeholders in bold with your rule name, artifact name and versions for the artifacts you’d like to resolve, app name, and app class. See the example below for more details.  
 

load("@rules_jvm_external//:defs.bzl", "maven_install")

maven_install(
    name = "<RULE_NAME>",
    artifacts = [
        "<ARTIFACT_NAME>:<ARTIFACT_VERSION>",
        "<ARTIFACT_NAME>:<ARTIFACT_VERSION>"
        # Add more dependencies as needed
    ],
    repositories = [
      # Private repositories are supported through HTTP Basic auth   
      "<JFROG_HOST_DOMAIN>/artifactory/<REPOSITORY_NAME>",
    ],
)

java_binary(
    name = "<APP_NAME>",
    main_class = "<APP_CLASS>",
    runtime_deps = [":<RULE_NAME>"],
    # Add other configuration as needed
)


For example:
 

load("@rules_jvm_external//:defs.bzl", "maven_install")

maven_install(
    name = "my_dependencies",
    artifacts = [
        "com.google.guava:guava:28.2-jre",
        "org.slf4j:slf4j-api:1.7.30",
        "junit:junit:4.13.2",
    ],
    repositories = [
      # Private repositories are supported through HTTP Basic auth   
      "http://username:password@localhost:8081/artifactory/maven-remote",
    ],
)

java_binary(
    name = "my_app",
    main_class = "com.example.MyApp",
    runtime_deps = [":my_dependencies"],
    # Add other configuration as needed
)


This example ruleset will do the following: 

1. Load the maven_install rule from the rules_jvm_external package.
load("@rules_jvm_external//:defs.bzl", "maven_install")
2. Define a maven_install rule named my_dependencies which specifies the external Java dependencies you want to use. You can list the artifacts you need, along with their group, name, and version. In this example, we've included dependencies like Guava, SLF4J, and JUnit.
maven_install(
    name = "my_dependencies",
    artifacts = [
        "com.google.guava:guava:28.2-jre",
        "org.slf4j:slf4j-api:1.7.30",
        "junit:junit:4.13.2",
        # Add more dependencies as needed
    ],

3. Set the repositories attribute to specify the remote repositories from which Bazel should fetch these dependencies. In this case, we've included the Artifactory Maven repository.
repositories = [
      # Private repositories are supported through HTTP Basic auth   
      "http://username:password@localhost:8081/artifactory/maven-remote",
    ],

4. Define a java_binary target called my_app that depends on the my_dependencies rule. This target represents your Java application and can be configured with additional settings, such as the main class and any runtime dependencies.
java_binary(
    name = "my_app",
    main_class = "com.example.MyApp",
    runtime_deps = [":my_dependencies"],
    # Add other configuration as needed
)
 
Set Up Artifactory to Publish Bazel Artifacts

See the following example of how to configure the rules_jvm_external ruleset in a BUILD file to publish Java dependencies to a Bazel project: 

Make sure to replace the placeholders in bold with your rule name, artifact name and versions for the artifacts you’d like to resolve, app name, and app class. See the example below for more details.  
 

# user_project/BUILD
load("@rules_jvm_external//:defs.bzl", "java_export")

java_export(
  name = "<APP_NAME>",
  maven_coordinates = "com.example:project:0.0.1",
  pom_template = "pom.tmpl",  # You can omit this
  srcs = glob(["*.java"]),
  deps = [
    "//user_project/utils",
    "@maven//:com_google_guava_guava",
  ],
)


For example:
 

# user_project/BUILD
load("@rules_jvm_external//:defs.bzl", "java_export")

java_export(
  name = "exported_lib",
  maven_coordinates = "com.example:project:0.0.1",
  pom_template = "pom.tmpl",  # You can omit this
  srcs = glob(["*.java"]),
  deps = [
    "//user_project/utils",
    "@maven//:com_google_guava_guava",
  ],
)


This example ruleset will:

1. Load the java_export rule from the rules_jvm_external package.
load("@rules_jvm_external//:defs.bzl", "java-export")

2. Create a java_export target called exported-lib. This is similar to a regular java_library parameter, but it allows two additional parameters to set Maven coordinates and add an optional template for the pom.xml file.
java_export(
  name = "exported_lib",

3. Set the target Maven coordinates.
Maven_coordinates = "com.example:project:0.0.1",
4. (Optional) Add a template file to use for the pom.xml file.
pom_template = "pom.tmpl",  # You can omit this
5. Finally, set the sources and dependencies for the build process. In this case, we set the ruleset to use files ending with .java as sources, and to use a dependency called guava from Google to publish the build results: 
srcs = glob(["*.java"]),
  deps = [
    "//user_project/utils",
    "@maven//:com_google_guava_guava",
  ],
)

After setting the java_export rule, run the following command to publish the artifact to Artifactory local Maven repository:

When setting gpg-sign to true, the current default key will be used for signing: make sure that the gpg binary is installed on your machine before running this command.  

Make sure to replace the placeholders in bold with your Maven username and password, your local repository path, and export rule name. 
 

MAVEN_USER=<USERNAME> MAVEN_PASSWORD=<TOKEN> bazel run --stamp \
  --define "maven_repo=<JFROG_HOST_DOMAIN>/artifactory/<REPOSITORY_NAME>" \
  --define gpg_sign=true \
  //user_project:<EXPORT_RULE_NAME>.publish`


For example:
 

MAVEN_USER=admin MAVEN_PASSWORD=password bazel run --stamp \
  --define "maven_repo=https://acme.jfrog.io/artifactory/maven_local" \
  --define gpg_sign=true \
  //user_project:exported_lib.publish`
 Set Up Bazel Modules Repositories in Artifactory for Module Dependency Management

Artifactory supports using Bazel Modules remote repositories to proxy the Bazel Central Repository (BCR) for module dependency management. This enables you to complete end-to-end Bazel workflows in Artifactory that adhere to the Bazel 9 deprecation of the WORKSPACE system. For more information, see Bazel Modules Repositories.