Use RubyGems and Bundler with JFrog CLI
Configure and run RubyGems and Bundler with JFrog CLI and Artifactory.
Use JFrog CLI to configure RubyGems and Bundler for JFrog Artifactory, run native gem and bundle commands with Artifactory authentication, and collect build-info. The jf ruby command is available in JFrog CLI 2.121.0 and later.
This topic covers the following tasks:
- Configure RubyGems and Bundler
- Run Bundler Commands
- Install and Fetch Gems
- Collect and Publish Build-Info
When to Use
Use the Ruby commands for the following workflows:
- Run
jf setup rubyonce per user environment to persist an Artifactory source, a Bundler mirror, and credentials in native Ruby configuration. - Run
jf ruby bundle <subcommand>orjf ruby gem <subcommand>when you want JFrog CLI to discover an Artifactory RubyGems repository and provide authentication to the native tool. - Add
--build-nameand--build-numberto supported operations to save Ruby dependency or artifact build-info locally. Publish the saved build-info separately withjf rt build-publish. - Continue using
jf ruby-configfor the existing project configuration workflow.jf rubydoesn't read.jfrog/projects/ruby.yaml. It uses command arguments and native RubyGems or Bundler sources.
Prerequisites
- JFrog CLI 2.121.0 or later for
jf ruby. - RubyGems or Bundler on
PATH: JFrog CLI invokes the localgemorbundlebinary and doesn't install Ruby. - A configured JFrog server: Run
jf config addorjf c add. Use--server-idto select a non-default configuration. For more information, see Configure JFrog CLI. - Artifactory RubyGems repositories: Use a remote or virtual repository to resolve gems and a local repository to push gems. For more information, see RubyGems Repositories.
- Write access to your Ruby user configuration when using
jf setup ruby. Setup updates~/.bundle/configand~/.gemrc.
Configure RubyGems and Bundler
The recommended native setup command is jf setup ruby. It configures plain bundle and gem commands to resolve from Artifactory.
Synopsis
jf setup ruby [--server-id=<SERVER_ID>] [--repo=<REPOSITORY_KEY>] [--project=<PROJECT_KEY>]Where:
<SERVER_ID>: JFrog CLI server ID fromjf config add<REPOSITORY_KEY>: Artifactory RubyGems repository key<PROJECT_KEY>: JFrog project key used when listing repositories interactively
Setup Options
The following table lists the setup options.
| Flag | Default | Description |
|---|---|---|
--server-id | Default server | JFrog CLI server configuration to use |
--repo | Interactive selection | Artifactory RubyGems repository key. When omitted in an interactive terminal, JFrog CLI prompts for a compatible virtual repository |
--project | None | JFrog project key used when listing repositories interactively |
--url | None | JFrog Artifactory URL. Use with command-line credentials instead of --server-id |
--user | None | JFrog username for command-line authentication |
--password | None | JFrog password for command-line authentication |
--access-token | None | JFrog access token for command-line authentication |
--client-cert-path | None | Client certificate in PEM format |
--client-cert-key-path | None | Private key for the client certificate in PEM format |
--ssh-key-path | None | SSH key used for authentication |
--ssh-passphrase | None | Passphrase for the SSH key |
To configure RubyGems and Bundler persistently:
-
Run:
jf setup ruby --server-id=<SERVER_ID> --repo=<REPOSITORY_KEY>Where:
<SERVER_ID>: JFrog CLI server ID fromjf config add<REPOSITORY_KEY>: Artifactory RubyGems repository key
For example:
jf setup ruby --server-id=my-server --repo=gems-virtual -
Verify the native configuration:
gem sources --list bundle config list
After setup, Bundler uses a two-part configuration in ~/.bundle/config:
- A mirror so a Gemfile that still says
source "https://rubygems.org"resolves through Artifactory. Bundler stores credentials in the mirror URL. - Per-host credentials so a Gemfile that names the Artifactory gems API URL can authenticate without embedding a password in Gemfile.
For example, after jf setup ruby --repo=gems-virtual against https://mycompany.jfrog.io/artifactory/, ~/.bundle/config contains entries similar to:
---
BUNDLE_MIRROR__HTTPS://RUBYGEMS__ORG/: "https://<USER>:<PASSWORD>@mycompany.jfrog.io/artifactory/api/gems/gems-virtual/"
BUNDLE_MYCOMPANY__JFROG__IO: "<USER>:<PASSWORD>"Where:
<USER>: Username from the selected JFrog CLI server configuration<PASSWORD>: Password or access token from that configuration
If the Artifactory host contains a dash, setup also writes Bundler 1.x's older key spelling. For more information, see Runtime Authentication.
The ~/.gemrc file contains the Artifactory source with credentials in the source URL. Setup removes the public RubyGems source so native gem install resolves through the configured virtual repository. Other Artifactory sources are preserved, with the most recently configured source first.
JFrog CLI preserves existing unrelated settings in both files. It writes both files with owner-only permissions.
Warning
jf setup rubywrites persistent credentials to native Ruby configuration. Protect~/.bundle/configand~/.gemrc, and run setup again after the configured credential changes or expires.
Existing Ruby Configuration Workflow
jf ruby-config remains available, with alias jf rubyc, for saving project or global JFrog Ruby configuration.
jf ruby-config \
--server-id-resolve=<SERVER_ID> \
--repo-resolve=<RESOLVE_REPOSITORY>Where:
<SERVER_ID>: JFrog CLI server ID fromjf config add<RESOLVE_REPOSITORY>: Artifactory repository key used for gem resolution
For example:
jf ruby-config --server-id-resolve=my-server --repo-resolve=gems-virtualIts options are --global, --server-id-resolve, --repo-resolve, --server-id-deploy, and --repo-deploy. The command writes .jfrog/projects/ruby.yaml for a project, or the corresponding global JFrog configuration when --global is set.
This file is separate from native Ruby configuration. jf ruby doesn't read ruby.yaml. Use jf setup ruby, a Gemfile source, native source options, or gem sources to provide the repository used at runtime.
Ruby Command Syntax
jf ruby selects either RubyGems or Bundler, removes only its JFrog-specific options, and passes the remaining arguments to the selected native binary in their original order. JFrog CLI passes through standard input, output, errors, and the native exit status. jf ruby always invokes the native gem or bundle binary. For more information, see Native Mode.
Synopsis
jf ruby gem <GEM_SUBCOMMAND_OR_OPTION> [gem arguments...] [JFrog options]
jf ruby bundle <BUNDLE_SUBCOMMAND_OR_OPTION> [bundle arguments...] [JFrog options]Arguments
The following table lists the arguments.
| Argument | Required | Description |
|---|---|---|
gem or bundle | Yes | Native Ruby tool to invoke |
<GEM_SUBCOMMAND_OR_OPTION> or <BUNDLE_SUBCOMMAND_OR_OPTION> | Yes | Native subcommand such as install, fetch, build, push, update, add, or lock. Standalone native options such as --version are also valid |
| Native arguments | No | Arguments and options forwarded to the selected native tool |
JFrog CLI doesn't provide top-level jf gem or jf bundle commands. Use jf ruby gem and jf ruby bundle.
The following table lists the JFrog options.
| Flag | Default | Description |
|---|---|---|
--server-id | Default server | JFrog CLI server configuration used for repository URL construction and runtime authentication |
--repo | Discovered source | Artifactory repository key. JFrog CLI constructs https://<HOST>/artifactory/api/gems/<REPOSITORY_KEY>/ from the selected server. For gem install and gem fetch, it supplies the URL as the native source. For gem push, it supplies the URL as the native host. For Bundler, the Gemfile or configured mirror must still select the source |
--build-name | None | Build name for local build-info. Must be provided with --build-number |
--build-number | None | Build number for local build-info. Must be provided with --build-name |
--module | Derived module ID | Module name override in build-info |
--project | None | JFrog project key associated with the build-info |
JFrog options can appear among the native arguments. Other options, including native --source, -s, --host, --clear-sources, --path, -i/--install-dir, version, and group options, are passed to RubyGems or Bundler.
Runtime Authentication
JFrog CLI injects credentials into the native subprocess when it discovers an Artifactory target and the native tool doesn't already have credentials for that host.
The following table lists the environment variables JFrog CLI may set.
| Variable | Format JFrog CLI writes | Used by |
|---|---|---|
GEM_HOST_API_KEY | Basic <BASE64(user:password)> HTTP Basic value, not user:password | RubyGems for install, fetch, and push |
BUNDLE_<HOST_KEY> | user:password | Bundler |
If you set GEM_HOST_API_KEY yourself, use the same Basic format RubyGems expects: Basic followed by the Base64 encoding of user:password. A value of user:password without the Basic prefix doesn't match what JFrog CLI injects and isn't the format RubyGems uses for this variable.
For Bundler, JFrog CLI may inject two host-key spellings so Bundler 1.x and Bundler 2.x both authenticate:
- Bundler 2.x and later: uppercase host,
.becomes__,-becomes___. For example,my-company.jfrog.iobecomesBUNDLE_MY___COMPANY__JFROG__IO. - Bundler 1.x: uppercase host,
.becomes__, and dashes stay in the key. JFrog CLI adds this spelling only when it differs from the Bundler 2.x key.
JFrog CLI doesn't overwrite a variable that is already set in the environment.
Repository Discovery and Authentication
JFrog CLI discovers the Artifactory gems URL in this order:
--repo. JFrog CLI constructshttps://<HOST>/artifactory/api/gems/<REPOSITORY_KEY>/from the selected server configuration- A native
--source,-s, or--hostURL in the command - An Artifactory
sourceURL in the activeGemfile, including Bundler'sBUNDLE_GEMFILEand parent-directory lookup - The first Artifactory source returned by
gem sources --list
Native --clear-sources is forwarded to RubyGems. It doesn't supply a URL for this discovery sequence. This discovery doesn't use .jfrog/projects/ruby.yaml.
For a matching Artifactory target, JFrog CLI passes authentication to the native subprocess while respecting credentials already configured by the native tool. For gem push, it also adds a temporary entry for the target host to ~/.gem/credentials, then restores the previous file or removes the temporary entry after the command. Cleanup also runs when the process receives an interrupt or termination signal.
If a discovered target host differs from the configured Artifactory host, JFrog CLI doesn't inject that server's credentials by default. Select the intended configuration explicitly with --server-id, or configure the target in Bundler or RubyGems.
Run Bundler Commands
Use jf ruby bundle with native Bundler subcommands. install, update, and add can collect dependencies from Gemfile.lock. JFrog CLI passes lock through but doesn't collect build-info.
To install dependencies and collect build-info:
-
From the directory containing the
Gemfile, run:jf ruby bundle install \ --build-name=<BUILD_NAME> \ --build-number=<BUILD_NUMBER>Where:
<BUILD_NAME>: Build name for local build-info<BUILD_NUMBER>: Build number for local build-info
For example:
jf ruby bundle install --build-name=my-app --build-number=1 -
Publish the saved build-info:
jf rt build-publish <BUILD_NAME> <BUILD_NUMBER>For example:
jf rt build-publish my-app 1
Bundler resolves and installs the project dependencies, and JFrog CLI saves dependency build-info from Gemfile.lock. Native Bundler output varies by project and installed Bundler version.
The same dependency collection applies to:
jf ruby bundle update <GEM> --build-name=<BUILD_NAME> --build-number=<BUILD_NUMBER>
jf ruby bundle add <GEM> --build-name=<BUILD_NAME> --build-number=<BUILD_NUMBER>Where:
<GEM>: Gem name passed to Bundler<BUILD_NAME>: Build name for local build-info<BUILD_NUMBER>: Build number for local build-info
For example:
jf ruby bundle update rake --build-name=my-app --build-number=1jf ruby bundle lock can update Gemfile.lock. It doesn't collect build-info, even if you pass --build-name and --build-number. The operation only resolves and writes the lockfile.
Bundler honors --without and --with during bundle install. Build-info includes only the gems that are actually installed after those filters.
Install and Fetch Gems
Use --repo to select an Artifactory repository without supplying a full native source URL.
To install a gem and collect dependency build-info:
-
Run:
jf ruby gem install <GEM_NAME> \ --repo=<RESOLVE_REPOSITORY> \ --build-name=<BUILD_NAME> \ --build-number=<BUILD_NUMBER>Where:
<GEM_NAME>: Gem to install<RESOLVE_REPOSITORY>: Artifactory RubyGems repository key used for resolution<BUILD_NAME>: Build name for local build-info<BUILD_NUMBER>: Build number for local build-info
For example:
jf ruby gem install rake --repo=gems-virtual --build-name=my-app --build-number=1
To fetch a gem and collect dependency build-info:
-
Run:
jf ruby gem fetch <GEM_NAME> \ --repo=<RESOLVE_REPOSITORY> \ --build-name=<BUILD_NAME> \ --build-number=<BUILD_NUMBER>Where:
<GEM_NAME>: Gem to fetch<RESOLVE_REPOSITORY>: Artifactory RubyGems repository key used for resolution<BUILD_NAME>: Build name for local build-info<BUILD_NUMBER>: Build number for local build-info
For example:
jf ruby gem fetch rake --repo=gems-virtual --build-name=my-app --build-number=1
JFrog CLI constructs the repository URL, RubyGems installs or downloads the requested gem, and JFrog CLI records the gems changed by that invocation as dependencies.
gem install -i <DIR> and gem install --install-dir <DIR> are supported. JFrog CLI scopes the before-and-after gem snapshot to that directory so you can install into a custom location and still collect build-info.
Build and Push Gems
gem build is a local operation. JFrog CLI doesn't inject repository authentication for it. With build flags, it records dependencies only when a Gemfile.lock is available. It doesn't record the locally built .gem file as an artifact.
To record lockfile dependencies while building a gem:
-
Run:
jf ruby gem build <GEMSPEC> \ --build-name=<BUILD_NAME> \ --build-number=<BUILD_NUMBER>Where:
<GEMSPEC>: Path to the gemspec file<BUILD_NAME>: Build name for local build-info<BUILD_NUMBER>: Build number for local build-info
For example:
jf ruby gem build my-gem.gemspec --build-name=my-app --build-number=1
To push a gem and collect artifact build-info:
-
Run:
jf ruby gem push <GEM_FILE> \ --repo=<LOCAL_REPOSITORY> \ --build-name=<BUILD_NAME> \ --build-number=<BUILD_NUMBER>Where:
<GEM_FILE>: Local.gemfile to upload<LOCAL_REPOSITORY>: Artifactory local RubyGems repository key<BUILD_NAME>: Build name for local build-info<BUILD_NUMBER>: Build number for local build-info
For example:
jf ruby gem push my-gem-1.0.0.gem --repo=gems-local --build-name=my-app --build-number=1 -
Publish the saved build-info:
jf rt build-publish <BUILD_NAME> <BUILD_NUMBER>For example:
jf rt build-publish my-app 1
RubyGems uploads the gem to the selected Artifactory repository, and JFrog CLI records the uploaded .gem as a build artifact.
JFrog CLI strips a trailing slash from --host before gem push. RubyGems builds the upload URL as #{host}/api/v1/gems. A trailing slash on the host would produce a double slash, and Artifactory rejects that request.
Collect and Publish Build-Info
Build-info collection occurs only when both --build-name and --build-number are set.
The following table lists build-info collection by native operation.
| Native operation | Dependencies | Artifacts | Notes |
|---|---|---|---|
bundle install | Yes | No | Reads gems that Bundler actually installed from Gemfile.lock, including --without and --with filters |
bundle update | Yes | No | Reads resolved dependencies from Gemfile.lock |
bundle add | Yes | No | Reads resolved dependencies from Gemfile.lock |
bundle lock | No | No | Native passthrough only. --build-name and --build-number don't collect build-info |
gem install | Yes | No | Records gems installed by this invocation |
gem fetch | Yes | No | Records gems fetched by this invocation |
gem build | Only when Gemfile.lock exists | No | The local .gem isn't an Artifactory artifact |
gem push | No | Yes | Records the uploaded .gem artifact |
Other gem or bundle subcommands | No | No | Native passthrough |
GIT and PATH dependencies appear in build-info when Bundler resolved them, but JFrog CLI skips Artifactory checksum enrichment for those gems. They aren't stored in the RubyGems repository, so AQL can't look them up.
If checksum enrichment fails, JFrog CLI still saves the build-info. You can still publish it. Dependencies are recorded without checksums, and the CLI logs a warning. A common cause is passing a virtual repository to AQL. Use --repo with a local or remote repository when you need checksums.
jf ruby saves build-info locally. It doesn't publish it automatically.
To publish saved Ruby build-info:
-
Run:
jf rt build-publish <BUILD_NAME> <BUILD_NUMBER> [--project=<PROJECT_KEY>]Where:
<BUILD_NAME>: Build name used when collecting build-info<BUILD_NUMBER>: Build number used when collecting build-info<PROJECT_KEY>: Optional JFrog project key associated with the build-info
For example:
jf rt build-publish my-app 1
Note
Providing only
--build-nameor only--build-numberfails withthe build-name and build-number options cannot be provided separately.
Package Alias
Package Alias can intercept the native gem and bundle executable names. When either tool is configured in jf mode, routing is:
gem <args>→jf ruby gem <args>bundle <args>→jf ruby bundle <args>
The aliases don't route to top-level jf gem or jf bundle commands. gem and bundle default to pass mode unless you explicitly set their Package Alias mode to jf. For more information, see Use JFrog CLI Package Alias.
Ruby Command Behavior
jf rubyrequiresgemorbundleas the first argument, then at least one native argument.jf ruby pipfails withunsupported ruby tool "pip": expected 'gem' or 'bundle'.jf ruby gemwith no subcommand fails withno subcommand provided for 'gem'. For example, usejf ruby gem install rakeorjf ruby gem --version.- JFrog CLI passes help requests to the native tool without injecting authentication.
--repois a repository key, not a URL. Use native--sourceor--hostwhen you need to provide a complete URL.jf rubydoesn't change native configuration. Onlyjf setup rubychanges~/.bundle/configand~/.gemrc.gem pushmay temporarily update~/.gem/credentialsfor the duration of the command.- Native output varies by Ruby, RubyGems, Bundler, project, and Artifactory configuration.
Troubleshooting
The following table lists common errors and how to resolve them.
| Error or symptom | Cause | Resolution |
|---|---|---|
unsupported ruby tool "<tool>": expected 'gem' or 'bundle' | The first argument after jf ruby isn't supported | Use jf ruby gem <subcommand> or jf ruby bundle <subcommand> |
no subcommand provided for 'gem' or no subcommand provided for 'bundle' | The native subcommand is missing | Add a subcommand such as install, fetch, build, push, update, or add |
the build-name and build-number options cannot be provided separately | Only one build identifier was provided | Pass both build options, or omit both |
| Authentication is skipped for a target host | The discovered source host differs from the configured Artifactory host | Pass the correct --server-id, or configure credentials in the native tool |
| Bundler still resolves from the public registry | The Gemfile source or native mirror doesn't select Artifactory | Run jf setup ruby, or update the Gemfile to use the Artifactory gems API URL |
| Build-info is saved without dependency checksums | AQL enrichment failed, often because the repo is virtual, or the gems are GIT or PATH sources | Publish still succeeds. Pass --repo with a local or remote repository for Artifactory gems. GIT and PATH gems stay in the record without checksums |
gem push targets an unintended host | No Artifactory repository or native host was selected | Pass --repo=<LOCAL_REPOSITORY> or native --host=<ARTIFACTORY_GEMS_URL> |
No build-info is saved for bundle lock | The operation only resolves and writes the lockfile. Build flags don't change that | Run bundle install, bundle update, or bundle add with both build options |
No artifact is recorded for gem build | The built gem hasn't entered Artifactory | Push it with jf ruby gem push using the same build name and number |
Frequently Asked Questions
This section provides answers to frequently asked questions.
FAQs
Q: Does jf ruby use the configuration written by jf ruby-config?
jf ruby use the configuration written by jf ruby-config?A: No. jf ruby doesn't read .jfrog/projects/ruby.yaml. It discovers repositories from --repo first, then native source or host arguments, the active Gemfile, or gem sources. See Repository Discovery and Authentication.
Q: What is the difference between jf setup ruby and jf ruby-config?
jf setup ruby and jf ruby-config?A: jf setup ruby writes native user configuration for RubyGems and Bundler. jf ruby-config writes JFrog project configuration to ruby.yaml. See Configure RubyGems and Bundler.
Q: Does jf ruby publish build-info automatically?
jf ruby publish build-info automatically?A: No. It saves supported dependency or artifact build-info locally. Run jf rt build-publish <BUILD_NAME> <BUILD_NUMBER> to publish it. See Collect and Publish Build-Info.
Q: Can I pass normal RubyGems and Bundler options?
A: Yes. JFrog CLI removes only --server-id, --repo, --build-name, --build-number, --module, and --project. It forwards the remaining arguments to the selected native tool, including --clear-sources, -i/--install-dir, --without, and --with.
Q: Does jf ruby bundle lock --build-name record build-info?
jf ruby bundle lock --build-name record build-info?A: No. bundle lock is native passthrough only. Add --build-name and --build-number to bundle install, bundle update, or bundle add instead. See Collect and Publish Build-Info.
Related Topics
Updated 8 days ago
