Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
ceb8456
Register jf ruby command with flags, docs, Ghost Frog routing, and tests
agrasth Jun 29, 2026
f988213
feat: add --repo flag to jf ruby command
agrasth Jun 29, 2026
c21fde8
feat: add Ruby integration tests (gated behind -test.ruby flag)
agrasth Jul 14, 2026
852dead
ci: add Ruby integration test workflow to build gate
agrasth Jul 15, 2026
7834fb4
Merge remote-tracking branch 'origin/master' into feature/rubygems-na…
agrasth Jul 15, 2026
5f4596c
chore: update replace directives to remote commits for CI
agrasth Jul 15, 2026
ae1a7f7
fix: resolve static analysis failures (gosec G703, gocritic ifElseChain)
agrasth Jul 15, 2026
c8c8b45
fix: add GetAIDescription to jf ruby command for AI help coverage check
agrasth Jul 15, 2026
9f8982d
ci: trigger Ruby tests against feature branch
agrasth Jul 15, 2026
06f6ec0
ci: add push-triggered Ruby test workflow for branch validation
agrasth Jul 15, 2026
3057fac
fix: add prepareHomeDir to Ruby tests + update go.mod
agrasth Jul 15, 2026
a7c3008
fix: add prepareHomeDir to Ruby tests + update go.mod
agrasth Jul 15, 2026
d35c497
fix: remove Gemfile.lock fixtures + update dep for server-id error
agrasth Jul 15, 2026
4ba3797
fix: remove Gemfile.lock fixtures + update dep for server-id error
agrasth Jul 15, 2026
7db8e24
fix: update jfrog-cli-artifactory dep for bundle auth hostname fix
agrasth Jul 15, 2026
69568e3
fix: update jfrog-cli-artifactory dep for bundle auth hostname fix
agrasth Jul 15, 2026
3c9fe20
fix: embed credentials in Gemfile source URL for bundle tests
agrasth Jul 15, 2026
8709940
fix: embed credentials in Gemfile source URL for bundle tests
agrasth Jul 15, 2026
d8be9c1
fix: use JfrogUser as fallback username in Gemfile URL for CI
agrasth Jul 16, 2026
8e2eebb
fix: use JfrogUser as fallback username in Gemfile URL for CI
agrasth Jul 16, 2026
d94e3e0
fix: warm up virtual repo before bundle tests
agrasth Jul 16, 2026
b785b08
fix: warm up virtual repo before bundle tests
agrasth Jul 16, 2026
34f1519
fix: warm up virtual repo by deploying gem to local repo
agrasth Jul 16, 2026
f676450
fix: warm up virtual repo by deploying gem to local repo
agrasth Jul 16, 2026
d326b32
fix: use gem push API for warm-up instead of generic upload
agrasth Jul 16, 2026
a4f059d
fix: use gem push API for warm-up instead of generic upload
agrasth Jul 16, 2026
dcec4c7
fix: add 10s sleep after gem push for async index generation
agrasth Jul 16, 2026
9a23e5f
fix: poll specs.4.8.gz availability instead of fixed sleep
agrasth Jul 16, 2026
085ffe7
fix: use sync.Once for warm-up + fix BuildFlags test expectations
agrasth Jul 16, 2026
862450e
fix: use local repo for bundle tests instead of virtual
agrasth Jul 16, 2026
3697183
Merge branch 'feature/rubygems-test-trigger' into feature/rubygems-na…
agrasth Jul 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/build-gate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@ jobs:
needs: gate
uses: ./.github/workflows/pythonTests.yml
secrets: inherit
ruby:
needs: gate
uses: ./.github/workflows/rubyTests.yml
secrets: inherit
script:
needs: gate
uses: ./.github/workflows/scriptTests.yml
Expand Down Expand Up @@ -196,6 +200,7 @@ jobs:
- podman
- poetry
- python
- ruby
- script
- transfer
- uv
Expand Down
73 changes: 73 additions & 0 deletions .github/workflows/rubyTests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: Ruby Tests
on:
workflow_call:
workflow_dispatch:
inputs:
jfrog_url:
description: "External JFrog Platform URL. Leave empty for local Artifactory."
type: string
required: false
default: ""
jfrog_admin_token:
description: "Admin token for external JFrog Platform."
type: string
required: false
default: ""

jobs:
Ruby-Tests:
name: Ruby tests (${{ matrix.os.name }})
strategy:
fail-fast: false
matrix:
os:
- name: ubuntu
version: 24.04
- name: macos
version: 14
runs-on: ${{ matrix.os.name }}-${{ matrix.os.version }}
steps:
- name: Skip macOS - JGC-413
if: matrix.os.name == 'macos'
run: |
echo "::warning::JGC-413 - Skip until artifactory bootstrap in osx is fixed"
exit 0

- name: Checkout code
if: matrix.os.name != 'macos'
uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha || github.ref }}

- name: Setup FastCI
if: matrix.os.name != 'macos'
uses: jfrog-fastci/fastci@v1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
fastci_otel_token: ${{ secrets.FASTCI_TOKEN }}

- name: Setup Go with cache
if: matrix.os.name != 'macos'
uses: jfrog/.github/actions/install-go-with-cache@main

- name: Setup Ruby
if: matrix.os.name != 'macos'
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.2"
bundler-cache: false

- name: Install local Artifactory
if: matrix.os.name != 'macos'
uses: jfrog/.github/actions/install-local-artifactory@main
with:
RTLIC: ${{ secrets.RTLIC }}
JFROG_URL: ${{ inputs.jfrog_url }}
JFROG_ADMIN_TOKEN: ${{ inputs.jfrog_admin_token }}
RT_CONNECTION_TIMEOUT_SECONDS: '1200'

- name: Run Ruby tests
if: matrix.os.name != 'macos'
run: >-
go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.ruby
${{ env.JFROG_TESTS_IS_EXTERNAL == 'true' && format('--jfrog.url={0} --jfrog.adminToken={1}', env.JFROG_TESTS_URL, env.JFROG_TESTS_LOCAL_ACCESS_TOKEN) || '' }}
31 changes: 31 additions & 0 deletions .github/workflows/rubyTestsTrigger.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Ruby Tests (Branch Trigger)
on:
push:
branches:
- "feature/rubygems-test-trigger"

jobs:
Ruby-Tests:
name: Ruby tests (ubuntu)
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v6

- name: Setup Go with cache
uses: jfrog/.github/actions/install-go-with-cache@main

- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.2"
bundler-cache: false

- name: Install local Artifactory
uses: jfrog/.github/actions/install-local-artifactory@main
with:
RTLIC: ${{ secrets.RTLIC }}
RT_CONNECTION_TIMEOUT_SECONDS: '1200'

- name: Run Ruby tests
run: go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.ruby
76 changes: 76 additions & 0 deletions buildtools/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
conancommand "github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/conan"
nixcommand "github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/nix"
rubycommandexec "github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/ruby"
"io/fs"
"os"
"os/exec"
Expand Down Expand Up @@ -81,6 +82,7 @@ import (
"github.com/jfrog/jfrog-cli/docs/buildtools/pnpmconfig"
"github.com/jfrog/jfrog-cli/docs/buildtools/poetry"
"github.com/jfrog/jfrog-cli/docs/buildtools/poetryconfig"
"github.com/jfrog/jfrog-cli/docs/buildtools/rubycommand"
uvcommand "github.com/jfrog/jfrog-cli/docs/buildtools/uvcommand"
yarndocs "github.com/jfrog/jfrog-cli/docs/buildtools/yarn"
"github.com/jfrog/jfrog-cli/docs/buildtools/yarnconfig"
Expand Down Expand Up @@ -443,6 +445,19 @@ func GetCommands() []cli.Command {
return cliutils.CreateConfigCmd(c, project.Ruby)
},
},
{
Name: "ruby",
Hidden: false,
Flags: cliutils.GetCommandFlags(cliutils.Ruby),
Usage: corecommon.ResolveDescription(rubycommand.GetDescription(), rubycommand.GetAIDescription()),
HelpName: corecommon.CreateUsage("ruby", corecommon.ResolveDescription(rubycommand.GetDescription(), rubycommand.GetAIDescription()), rubycommand.Usage),
UsageText: rubycommand.GetArguments(),
ArgsUsage: common.CreateEnvVars(),
SkipFlagParsing: true,
BashComplete: corecommon.CreateBashCompletionFunc(),
Category: buildToolsCategory,
Action: RubyCmd,
},
{
Name: "npm-config",
Flags: cliutils.GetCommandFlags(cliutils.NpmConfig),
Expand Down Expand Up @@ -2118,6 +2133,67 @@ func NixCmd(c *cli.Context) error {
return commands.ExecWithPackageManager(cmd, "nix")
}

// RubyCmd wraps the native 'gem' and 'bundle' tools with Artifactory auth and
// build-info support. The first argument selects the native tool (gem/bundle);
// the remainder is passed through. Only --server-id and the build flags are
// interpreted by jf (config-less native flow, like 'jf uv').
func RubyCmd(c *cli.Context) error {
if show, err := cliutils.ShowCmdHelpIfNeeded(c, c.Args()); show || err != nil {
return err
}
if c.NArg() < 1 {
return cliutils.WrongNumberOfArgumentsHandler(c)
}

args := cliutils.ExtractCommand(c)

// First arg selects the native tool: "gem" or "bundle".
nativeTool, remainingArgs := getCommandName(args)

// Extract --server-id before passing args to the native tool.
var serverID string
var err error
remainingArgs, serverID, err = coreutils.ExtractServerIdFromCommand(remainingArgs)
if err != nil {
return fmt.Errorf("failed to extract server ID: %w", err)
}

// Extract --repo (Artifactory repository name for URL construction).
var repo string
remainingArgs, repo = extractRubyRepoFromArgs(remainingArgs)

// Extract build flags (--build-name, --build-number, --module, --project).
filteredArgs, buildConfiguration, err := build.ExtractBuildDetailsFromArgs(remainingArgs)
if err != nil {
return err
}

cmd := rubycommandexec.NewRubyCommand().
SetNativeTool(nativeTool).
SetArgs(filteredArgs).
SetServerID(serverID).
SetRepo(repo).
SetBuildConfiguration(buildConfiguration)

return commands.ExecWithPackageManager(cmd, project.Ruby.String())
}

// extractRubyRepoFromArgs extracts and consumes --repo <name> from the args slice.
func extractRubyRepoFromArgs(args []string) (cleanArgs []string, repo string) {
for i := 0; i < len(args); i++ {
switch {
case args[i] == "--repo" && i+1 < len(args):
repo = args[i+1]
i++
case strings.HasPrefix(args[i], "--repo="):
repo = strings.TrimPrefix(args[i], "--repo=")
default:
cleanArgs = append(cleanArgs, args[i])
}
}
return cleanArgs, repo
}

func pythonCmd(c *cli.Context, projectType project.ProjectType) error {
if show, err := cliutils.ShowCmdHelpIfNeeded(c, c.Args()); show || err != nil {
return err
Expand Down
59 changes: 59 additions & 0 deletions docs/buildtools/rubycommand/help.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package rubycommand

var Usage = []string{"ruby <gem|bundle> <args> [command options]"}

func GetDescription() string {
return "Run native RubyGems (gem) and Bundler (bundle) commands with Artifactory authentication and build-info support."
}

func GetAIDescription() string {
return `Run a native gem or bundle command through JFrog CLI so dependencies resolve against Artifactory and build-info can be recorded. Arguments are forwarded to the native tool unchanged; only --build-name, --build-number, --module, --project, --server-id, and --repo are interpreted by jf.

When to use:
- Installing gems from an Artifactory-backed RubyGems repository (gem install, bundle install).
- Pushing gems to Artifactory (gem push).
- Capturing build-info for a Ruby build by passing --build-name and --build-number.

Prerequisites:
- Ruby, gem, and/or bundle installed and available on PATH.
- A configured JFrog Platform server (jf c add or jf login), or pass --server-id.

Common patterns:
$ jf ruby gem install rake --repo gems-virtual
$ jf ruby bundle install --build-name=my-app --build-number=1
$ jf ruby gem push my_gem-1.0.0.gem --repo gems-local --build-name=my-app --build-number=1
$ jf ruby bundle install --server-id my-rt --repo gems-virtual

Gotchas:
- All arguments after the tool name (gem/bundle) are passed straight to the native tool (SkipFlagParsing).
- Build-info is collected only when both --build-name and --build-number are provided; publish it afterwards with 'jf rt build-publish'.
- The --repo flag constructs the full Artifactory gems API URL from your server config, so you don't need to pass full URLs.

Related: jf rt build-publish, jf ruby-config`
}

func GetArguments() string {
return ` ruby <gem|bundle> <args>
Wraps the native 'gem' and 'bundle' tools. The first argument selects the
native tool; everything after it is passed straight through. Only
--build-name, --build-number, --module, --project, --server-id and --repo
are interpreted by jf.

Authentication is injected automatically from your jf server config and
respects credentials you have already configured natively (Gemfile source,
.bundle/config, ~/.gem/credentials, BUNDLE_* / GEM_HOST_API_KEY env vars).

The --repo flag specifies the Artifactory repository name and constructs
the full URL from your server config (eliminating the need to pass full
Artifactory URLs). When --repo is used with gem install/push, the
--source/--host argument is injected automatically.

Examples:
- jf ruby bundle install --build-name=my-build --build-number=1
- jf ruby bundle update rake --server-id=my-rt
- jf ruby gem install rails --repo gems-virtual
- jf ruby gem install rails --source https://server/artifactory/api/gems/gems-remote/
- jf ruby gem push my_gem-1.0.0.gem --repo gems-local --build-name=my-build --build-number=1
- jf ruby gem push my_gem-1.0.0.gem --host https://server/artifactory/api/gems/gems-local/ --build-name=my-build --build-number=1
- jf ruby gem install rake --repo gems-virtual --server-id my-rt`
}
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ replace (
github.com/CycloneDX/cyclonedx-go => github.com/CycloneDX/cyclonedx-go v0.10.0
// Should not be updated to 0.2.6 due to a bug (https://github.com/jfrog/jfrog-cli-core/pull/372)
github.com/c-bata/go-prompt => github.com/c-bata/go-prompt v0.2.5
github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.13.1-0.20260715194847-6e04c9b133c8
github.com/jfrog/jfrog-cli-artifactory => github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260715215659-f58023de2dd2
// Should not be updated to 0.2.0-beta.2 due to a bug (https://github.com/jfrog/jfrog-cli-core/pull/372)
github.com/pkg/term => github.com/pkg/term v1.1.0
)
Expand All @@ -21,7 +23,7 @@ require (
github.com/jfrog/build-info-go v1.13.1-0.20260713073853-4f3044bf0940
github.com/jfrog/gofrog v1.7.6
github.com/jfrog/jfrog-cli-application v1.0.2-0.20260713081138-6df6041db819
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260714082320-4fd5a71b4b4a
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260715215659-f58023de2dd2
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260624085155-5ba797de2616
github.com/jfrog/jfrog-cli-evidence v0.9.5-0.20260618135203-4d2bdd4ee35f
github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20260618062042-6053ab368cab
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -394,8 +394,8 @@ github.com/jellydator/ttlcache/v3 v3.4.0 h1:YS4P125qQS0tNhtL6aeYkheEaB/m8HCqdMMP
github.com/jellydator/ttlcache/v3 v3.4.0/go.mod h1:Hw9EgjymziQD3yGsQdf1FqFdpp7YjFMd4Srg5EJlgD4=
github.com/jfrog/archiver/v3 v3.6.3 h1:hkAmPjBw393tPmQ07JknLNWFNZjXdy2xFEnOW9wwOxI=
github.com/jfrog/archiver/v3 v3.6.3/go.mod h1:5V9l+Fte30Y4qe9dUOAd3yNTf8lmtVNuhKNrvI8PMhg=
github.com/jfrog/build-info-go v1.13.1-0.20260713073853-4f3044bf0940 h1:LthrPDN8YjDKrDNzOWS/w9NLFyeebdnWkmp8vhma0qo=
github.com/jfrog/build-info-go v1.13.1-0.20260713073853-4f3044bf0940/go.mod h1:CYRUCvLKfyARjoJXLWAxce1qNUxTEtbRKAARkV42vpE=
github.com/jfrog/build-info-go v1.13.1-0.20260715194847-6e04c9b133c8 h1:rXEAstQ879wh+o99c1RBz34wYOy4RywwasaPtP5JkTs=
github.com/jfrog/build-info-go v1.13.1-0.20260715194847-6e04c9b133c8/go.mod h1:CYRUCvLKfyARjoJXLWAxce1qNUxTEtbRKAARkV42vpE=
github.com/jfrog/froggit-go v1.23.0 h1:HGNIP9ZqoXKXHQONazhCENqIrFLfc8J3aX/F0QelQ2s=
github.com/jfrog/froggit-go v1.23.0/go.mod h1:wRDryqyp3oe+eHgME2mpnEQmO8XBECIPagFwj0nHmdI=
github.com/jfrog/go-mockhttp v0.3.1 h1:/wac8v4GMZx62viZmv4wazB5GNKs+GxawuS1u3maJH8=
Expand All @@ -406,8 +406,8 @@ github.com/jfrog/jfrog-apps-config v1.0.1 h1:mtv6k7g8A8BVhlHGlSveapqf4mJfonwvXYL
github.com/jfrog/jfrog-apps-config v1.0.1/go.mod h1:8AIIr1oY9JuH5dylz2S6f8Ym2MaadPLR6noCBO4C22w=
github.com/jfrog/jfrog-cli-application v1.0.2-0.20260713081138-6df6041db819 h1:nbhpYN6Sb+oPJWpEHAaNbnwJJ5R2/g/TDnpCKjC/mRA=
github.com/jfrog/jfrog-cli-application v1.0.2-0.20260713081138-6df6041db819/go.mod h1:p8yLtbmCxxQucIbLZKnWu0F+EDtj6NLXbRQCEK/nb6o=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260714082320-4fd5a71b4b4a h1:dySEIu0wXHrPr3P1ZdXeMhcriWHJrr1N43oPLEi8QhQ=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260714082320-4fd5a71b4b4a/go.mod h1:BJ8x7NhWxJvhG5Bjca2GwWlZN2bxlo+8AnpuRnZ9RMM=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260715215659-f58023de2dd2 h1:JFQQbx41jj1iUl7bQ1mWIooYh6DQhSW01VYLTDRhDYw=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260715215659-f58023de2dd2/go.mod h1:TEs/1MBqXyF3Vjv8Hi0tT7unqn8f7uTQv3B2vMNdFNo=
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260624085155-5ba797de2616 h1:bioFXGzf3pF2qnC3LZD1S1saWiHSekL4vdsDSWksj/4=
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260624085155-5ba797de2616/go.mod h1:9R90mhbczGXwW5EGlDs7F08ejQU/xdoDhYHMvzBiqgE=
github.com/jfrog/jfrog-cli-evidence v0.9.5-0.20260618135203-4d2bdd4ee35f h1:MV4BATdkEoUYJmdPDvaB9EBb8JQZg28n/K4X7dcmyAY=
Expand Down
4 changes: 2 additions & 2 deletions main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func setupIntegrationTests() {
InitArtifactoryTests()
}

if *tests.TestNpm || *tests.TestPnpm || *tests.TestGradle || *tests.TestMaven || *tests.TestGo || *tests.TestNuget || *tests.TestPip || *tests.TestPipenv || *tests.TestPoetry || *tests.TestConan || *tests.TestHelm || *tests.TestUv || *tests.TestNix || *tests.TestAlpine || (*tests.TestArtifactory && !*tests.TestArtifactoryProxy) || *tests.TestArtifactoryProject {
if *tests.TestNpm || *tests.TestPnpm || *tests.TestGradle || *tests.TestMaven || *tests.TestGo || *tests.TestNuget || *tests.TestPip || *tests.TestPipenv || *tests.TestPoetry || *tests.TestConan || *tests.TestHelm || *tests.TestUv || *tests.TestNix || *tests.TestAlpine || *tests.TestRuby || (*tests.TestArtifactory && !*tests.TestArtifactoryProxy) || *tests.TestArtifactoryProject {
InitBuildToolsTests()
}
if *tests.TestDocker || *tests.TestPodman || *tests.TestDockerScan {
Expand Down Expand Up @@ -122,7 +122,7 @@ func tearDownIntegrationTests() {
if (*tests.TestArtifactory && !*tests.TestArtifactoryProxy) || *tests.TestArtifactoryProject {
CleanArtifactoryTests()
}
if *tests.TestNpm || *tests.TestPnpm || *tests.TestGradle || *tests.TestMaven || *tests.TestGo || *tests.TestNuget || *tests.TestPip || *tests.TestPipenv || *tests.TestPoetry || *tests.TestConan || *tests.TestHelm || *tests.TestNix || *tests.TestAlpine || *tests.TestDocker || *tests.TestPodman || *tests.TestDockerScan || (*tests.TestArtifactory && !*tests.TestArtifactoryProxy) || *tests.TestArtifactoryProject {
if *tests.TestNpm || *tests.TestPnpm || *tests.TestGradle || *tests.TestMaven || *tests.TestGo || *tests.TestNuget || *tests.TestPip || *tests.TestPipenv || *tests.TestPoetry || *tests.TestConan || *tests.TestHelm || *tests.TestNix || *tests.TestAlpine || *tests.TestRuby || *tests.TestDocker || *tests.TestPodman || *tests.TestDockerScan || (*tests.TestArtifactory && !*tests.TestArtifactoryProxy) || *tests.TestArtifactoryProject {
CleanBuildToolsTests()
}
if *tests.TestDistribution {
Expand Down
11 changes: 8 additions & 3 deletions packagealias/dispatch.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,15 @@ func runJFMode(tool string, args []string) error {
return fmt.Errorf("%s could not determine executable path: %w", ghostFrogLogPrefix, err)
}

newArgs := make([]string, 0, len(os.Args)+1)
newArgs := make([]string, 0, len(os.Args)+2)
newArgs = append(newArgs, execPath) // Use actual executable path
newArgs = append(newArgs, tool) // Add tool name as first argument
newArgs = append(newArgs, args...) // Add remaining arguments
// RubyGems (gem) and Bundler (bundle) are exposed under the single
// `jf ruby <tool>` dispatcher rather than top-level `jf gem`/`jf bundle`.
if tool == "gem" || tool == "bundle" {
newArgs = append(newArgs, "ruby")
}
newArgs = append(newArgs, tool) // Add tool name as first argument
newArgs = append(newArgs, args...) // Add remaining arguments

os.Args = newArgs

Expand Down
Loading
Loading