Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 2 additions & 2 deletions .github/workflows/transferTests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ jobs:
- name: Run transfer tests
if: matrix.os.name != 'macos'
run: >-
go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.transfer --test.installDataTransferPlugin
go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.transfer
--jfrog.url=${{ env.JFROG_TESTS_URL || 'http://127.0.0.1:8082' }}
--jfrog.adminToken=${{ env.JFROG_TESTS_LOCAL_ACCESS_TOKEN }}
--jfrog.targetUrl=${{ secrets.PLATFORM_URL }}
Expand Down Expand Up @@ -121,7 +121,7 @@ jobs:

- name: Run transfer tests
run: >-
go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.transfer --test.installDataTransferPlugin
go test -v github.com/jfrog/jfrog-cli --timeout 0 --test.transfer
--jfrog.targetUrl=${{ secrets.PLATFORM_URL }}
--jfrog.targetAdminToken=${{ secrets.PLATFORM_ADMIN_TOKEN }}
--jfrog.home=${{ runner.temp }}
Expand Down
1 change: 0 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,6 @@ The Transfer tests execute `transfer-files` commands between a local Artifactory
| `-jfrog.targetUrl` | JFrog target platform URL. |
| `-jfrog.targetAdminToken` | JFrog target platform admin token. |
| `-jfrog.jfrogHome` | The JFrog home directory of the local Artifactory installation. |
| `-jfrog.installDataTransferPlugin` | Set this flag to `true` if you want the test to automatically install the data-transfer plugin in the source Artifactory server. |

To run Transfer tests, execute the following command:

Expand Down
39 changes: 5 additions & 34 deletions artifactory/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@ import (

"github.com/jfrog/jfrog-cli/utils/accesstoken"

"github.com/jfrog/gofrog/version"
"github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/transferinstall"
"github.com/jfrog/jfrog-cli/docs/artifactory/transferplugininstall"

"github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/generic"
Expand Down Expand Up @@ -557,6 +555,7 @@ func GetCommands() []cli.Command {
BashComplete: corecommon.CreateBashCompletionFunc(),
Action: dataTransferPluginInstallCmd,
Category: transferCategory,
Hidden: true,
},
})
}
Expand Down Expand Up @@ -1245,38 +1244,10 @@ func buildTransferConfigMergeResult(csvPath string, originalErr error) transferC
}
}

func dataTransferPluginInstallCmd(c *cli.Context) error {
// Get the Artifactory serverID from the argument or use default if not exists
serverID := ""
if c.NArg() > 1 {
return cliutils.WrongNumberOfArgumentsHandler(c)
} else if c.NArg() == 1 {
serverID = c.Args()[0]
}
serverDetails, err := coreConfig.GetSpecificConfig(serverID, true, true)
if err != nil {
return err
}
installCmd := transferinstall.NewInstallDataTransferCommand(serverDetails)
// Optional flags
versionToInstall := c.String(cliutils.Version)
if versionToInstall != "" {
installCmd.SetInstallVersion(version.NewVersion(versionToInstall))
}
sourceFilesPath := c.String(cliutils.InstallPluginSrcDir)
if sourceFilesPath != "" {
installCmd.SetLocalPluginFiles(sourceFilesPath)
}

if versionToInstall != "" && sourceFilesPath != "" {
return cliutils.PrintHelpAndReturnError("Only version or dir is allowed, not both.", c)
}

homePath := c.String(cliutils.InstallPluginHomeDir)
if homePath != "" {
installCmd.SetJFrogHomePath(homePath)
}
return commands.Exec(installCmd)
func dataTransferPluginInstallCmd(_ *cli.Context) error {
log.Warn("The 'transfer-plugin-install' command is deprecated and no longer installs the data-transfer user plugin. " +
"'jf rt transfer-files' does not require the plugin on the source Artifactory. This command will be removed in a future release.")
return nil
}

func transferFilesCmd(c *cli.Context) error {
Expand Down
22 changes: 22 additions & 0 deletions artifactory/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,28 @@ func newTransferFilesFormatContext(formatVal string) *cli.Context {
return cli.NewContext(app, fs, nil)
}

func TestTransferPluginInstallIsHiddenAndDeprecated(t *testing.T) {
var found bool
for _, cmd := range GetCommands() {
if cmd.Name != "transfer-plugin-install" {
continue
}
found = true
assert.True(t, cmd.Hidden)
assert.Contains(t, cmd.Usage, "[DEPRECATED]")
}
assert.True(t, found, "transfer-plugin-install command should remain registered to inform users that the plugin is no longer required")
}

func TestTransferPluginInstallOnlyWarns(t *testing.T) {
// A non-existent server ID and conflicting flags would fail if the command still attempted an installation.
set := flag.NewFlagSet("transfer-plugin-install", flag.ContinueOnError)
set.String(cliutils.Version, "", "")
set.String(cliutils.InstallPluginSrcDir, "", "")
require.NoError(t, set.Parse([]string{"--version=1.0.0", "--dir=/non/existent", "no-such-server-id", "extra-arg"}))
assert.NoError(t, dataTransferPluginInstallCmd(cli.NewContext(nil, set, nil)))
}

// ---------------------------------------------------------------------------
// GetOutputFormat (transfer-files) tests
// ---------------------------------------------------------------------------
Expand Down
5 changes: 2 additions & 3 deletions docs/artifactory/transferfiles/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ When to use:
Prerequisites:
- Both source and target server IDs configured with admin tokens.
- 'jf rt transfer-config' (or transfer-config-merge) already run so repos exist on the target.
- 'jf rt transfer-plugin-install' installed on the source server's primary node.
- 'jf rt transfer-settings' tuned for throughput.

Common patterns:
Expand All @@ -33,12 +32,12 @@ Common patterns:
$ jf rt transfer-files source-prod target-cloud --status # check progress

Gotchas:
- Requires the data-transfer plugin on the source (install via 'jf rt transfer-plugin-install').
- Does not require the data-transfer user plugin on the source; 'jf rt transfer-plugin-install' is deprecated.
- Long-running; expect hours-to-days for large stores. Run inside a long-lived session (nohup, tmux, screen).
- Throughput is governed by 'jf rt transfer-settings'; defaults are conservative.
- Idempotent on file content but not on repo property changes; re-running after a target-side delete causes redelivery.

Related: jf rt transfer-config, jf rt transfer-settings, jf rt transfer-plugin-install
Related: jf rt transfer-config, jf rt transfer-settings

QA:
Q: What's the JFrog CLI command to transfer the configuration from my artifactory to the target artifactory?
Expand Down
25 changes: 7 additions & 18 deletions docs/artifactory/transferplugininstall/help.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,38 +3,27 @@ package transferplugininstall
var Usage = []string{"rt transfer-plugin-install <server-id> [command options]"}

func GetDescription() string {
return "Download and install the data-transfer user plugin on the primary node of Artifactory, which is running on this local machine."
return "[DEPRECATED] This command no longer installs the data-transfer user plugin and only prints a deprecation warning. 'jf rt transfer-files' does not require the plugin."
}

func GetArguments() string {
return ` server-id
The ID of the source server, on which the plugin should be installed.`
Ignored.`
}

func GetAIDescription() string {
return `Download the data-transfer Artifactory user plugin and install it on the primary node of the source Artifactory. Required as a one-time prep before 'jf rt transfer-files'. The plugin handles the actual byte streaming on the server side.
return `[DEPRECATED] Informational command only. It no longer downloads or installs the data-transfer Artifactory user plugin; it only prints a deprecation warning and exits successfully. 'jf rt transfer-files' does not require the plugin on the source server. The command will be removed in a future release.

When to use:
- One-time setup on the source server before starting a self-hosted-to-cloud migration.

Prerequisites:
- Must be run on the same host as the source Artifactory's primary node (or with filesystem access to its etc/artifactory/plugins/ directory).
- Admin privileges on the source server.
- The source server ID is configured locally.

Common patterns:
$ jf rt transfer-plugin-install source-prod
$ jf rt transfer-plugin-install source-prod --dir=/opt/jfrog/artifactory/var/etc/artifactory/plugins
- Do not use. Run 'jf rt transfer-files' directly.

Gotchas:
- Must run as the user that owns the Artifactory installation; otherwise the file write fails.
- The plugin requires a Groovy plugins admin restart (or wait for the scheduled reload).
- This command only targets self-hosted instances; cloud-hosted sources need a different transfer mechanism.
- All arguments and flags (--version, --dir, --home-dir) are accepted but ignored.

Related: jf rt transfer-files, jf rt transfer-settings

QA:
Q: What's the JFrog CLI command to install the data-transfer user plugin in the primary node of the source instance?
A: jf rt transfer-plugin-install source-server
Q: Do I need to install the data-transfer user plugin before running 'jf rt transfer-files'?
A: No. The plugin is no longer required, and 'jf rt transfer-plugin-install' is deprecated and does nothing.
`
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ require (
github.com/jfrog/gofrog v1.7.7
github.com/jfrog/jfrog-cli-application v1.0.2-0.20260917110731-d7783acedd8c
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20261103060251-30c80a7deec4
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20261102064148-e4c77ed13cc6
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20261104085101-89d932ea6d45
github.com/jfrog/jfrog-cli-evidence v0.11.1-0.20261102090321-5b0bce39abfe
github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20261030162302-b4948e3a2cb1
github.com/jfrog/jfrog-cli-security v1.41.2
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -404,8 +404,8 @@ github.com/jfrog/jfrog-cli-application v1.0.2-0.20260917110731-d7783acedd8c h1:B
github.com/jfrog/jfrog-cli-application v1.0.2-0.20260917110731-d7783acedd8c/go.mod h1:RHjDVsgfIE+6N49R1t1nBjbK2Je4VTN7CQm9OlwtFnQ=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20261103060251-30c80a7deec4 h1:Z4WqOlZZe3NA02ekqFrbSNlO8hkdGPHn/PuWq1sb+CA=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20261103060251-30c80a7deec4/go.mod h1:94/aLloMSK6avu4umcJS3DJ6IuGM5K10PwZ6kDqgzSo=
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20261102064148-e4c77ed13cc6 h1:7Jdj+FiaMN5jiQ94+Xlehf9OSLqSbAqAvO44XB9d7E4=
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20261102064148-e4c77ed13cc6/go.mod h1:dxy3GflCOX9kGxcdEkCXWhV+EMUAGBWO+CY5fGjWcCQ=
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20261104085101-89d932ea6d45 h1:1FDVeHvnUQJEww5HE23JA/7aiSVuEzET/WNkJiy6u64=
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20261104085101-89d932ea6d45/go.mod h1:dxy3GflCOX9kGxcdEkCXWhV+EMUAGBWO+CY5fGjWcCQ=
github.com/jfrog/jfrog-cli-evidence v0.11.1-0.20261102090321-5b0bce39abfe h1:BRaNdb6JIdGqGa79XwxIsZHDmZ26pQ5V1cPJ7zYLJoM=
github.com/jfrog/jfrog-cli-evidence v0.11.1-0.20261102090321-5b0bce39abfe/go.mod h1:4OGLCLQjdHg9PpjFkxvn8bGflOZGEJsoBHAGys7gUio=
github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20261030162302-b4948e3a2cb1 h1:1NA6meQs1Nbe7B1AKcvLdX+hKpxyWVe+cNpTDJznZcs=
Expand Down
10 changes: 0 additions & 10 deletions transfer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,6 @@ func initTransferTest(t *testing.T) func() {
t.Skip("Skipping transfer test. To run transfer test add the '-test.transfer=true' option.")
}
oldHomeDir, newHomeDir := prepareHomeDir(t)
if *tests.InstallDataTransferPlugin {
if *tests.JfrogHome != "" {
coreutils.ExitOnErr(artifactoryCli.WithoutCredentials().Exec("transfer-plugin-install", inttestutils.SourceServerId, "--home-dir="+*tests.JfrogHome))
} else {
coreutils.ExitOnErr(artifactoryCli.WithoutCredentials().Exec("transfer-plugin-install", inttestutils.SourceServerId))
}
}

// Delete the target server if exist
targetConfig, err := commands.GetConfig(inttestutils.TargetServerId, false)
Expand All @@ -83,9 +76,6 @@ func initTransferTest(t *testing.T) func() {
err = coretests.NewJfrogCli(execMain, "jfrog config", "--access-token="+*tests.JfrogTargetAccessToken).Exec("add", inttestutils.TargetServerId, "--interactive=false", "--url="+*tests.JfrogTargetUrl)
assert.NoError(t, err)

if *tests.InstallDataTransferPlugin {
assert.NoError(t, artifactoryCli.WithoutCredentials().Exec("curl", "-XPOST", "/api/plugins/reload"))
}
return func() {
cleanArtifactory()
inttestutils.CleanTargetRepos(targetArtifactoryCli)
Expand Down
6 changes: 3 additions & 3 deletions utils/cliutils/commandsflags.go
Original file line number Diff line number Diff line change
Expand Up @@ -1969,15 +1969,15 @@ var flagsMap = map[string]cli.Flag{
},
installPluginVersion: cli.StringFlag{
Name: Version,
Usage: "[Default: latest] The plugin version to download and install.` `",
Usage: "[DEPRECATED] Ignored.` `",
},
InstallPluginSrcDir: cli.StringFlag{
Name: InstallPluginSrcDir,
Usage: "[Optional] The local directory that contains the plugin files to install.` `",
Usage: "[DEPRECATED] Ignored.` `",
},
InstallPluginHomeDir: cli.StringFlag{
Name: InstallPluginHomeDir,
Usage: "[Default: /opt/jfrog] The local JFrog home directory to install the plugin in.` `",
Usage: "[DEPRECATED] Ignored.` `",
},
PreChecks: cli.BoolFlag{
Name: PreChecks,
Expand Down
108 changes: 54 additions & 54 deletions utils/tests/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,59 +43,58 @@ import (
)

var (
JfrogUrl *string
JfrogUser *string
JfrogPassword *string
JfrogSshKeyPath *string
JfrogSshPassphrase *string
JfrogAccessToken *string
JfrogTargetUrl *string
JfrogTargetAccessToken *string
JfrogHome *string
TestArtifactoryProject *bool
TestArtifactory *bool
TestArtifactoryProxy *bool
TestDistribution *bool
TestDocker *bool
TestPodman *bool
TestDockerScan *bool
ContainerRegistry *string
TestGo *bool
TestNpm *bool
TestPnpm *bool
TestGradle *bool
TestMaven *bool
TestNuget *bool
TestChoco *bool
TestPSResource *bool
TestPip *bool
TestPipenv *bool
TestPoetry *bool
TestUv *bool
TestNix *bool
TestCargo *bool
TestAlpine *bool
TestRuby *bool
TestApt *bool
TestAgentPlugins *bool
TestAgentSkills *bool
TestApm *bool
TestConan *bool
TestHelm *bool
TestHuggingFace *bool
TestPlugins *bool
TestXray *bool
TestAccess *bool
TestTransfer *bool
TestLifecycle *bool
TestEvidence *bool
TestApi *bool
TestGhostFrog *bool
TestIde *bool
HideUnitTestLog *bool
ciRunId *string
InstallDataTransferPlugin *bool
timestampAdded bool
JfrogUrl *string
JfrogUser *string
JfrogPassword *string
JfrogSshKeyPath *string
JfrogSshPassphrase *string
JfrogAccessToken *string
JfrogTargetUrl *string
JfrogTargetAccessToken *string
JfrogHome *string
TestArtifactoryProject *bool
TestArtifactory *bool
TestArtifactoryProxy *bool
TestDistribution *bool
TestDocker *bool
TestPodman *bool
TestDockerScan *bool
ContainerRegistry *string
TestGo *bool
TestNpm *bool
TestPnpm *bool
TestGradle *bool
TestMaven *bool
TestNuget *bool
TestChoco *bool
TestPSResource *bool
TestPip *bool
TestPipenv *bool
TestPoetry *bool
TestUv *bool
TestNix *bool
TestCargo *bool
TestAlpine *bool
TestRuby *bool
TestApt *bool
TestAgentPlugins *bool
TestAgentSkills *bool
TestApm *bool
TestConan *bool
TestHelm *bool
TestHuggingFace *bool
TestPlugins *bool
TestXray *bool
TestAccess *bool
TestTransfer *bool
TestLifecycle *bool
TestEvidence *bool
TestApi *bool
TestGhostFrog *bool
TestIde *bool
HideUnitTestLog *bool
ciRunId *string
timestampAdded bool
)

// nonProjectKeyCharsRegex matches any character that isn't allowed in an Artifactory
Expand Down Expand Up @@ -171,8 +170,9 @@ func init() {
TestIde = flag.Bool("test.ide", false, "Test IDE (VS Code / Cursor / Windsurf / Kiro / JetBrains) setup commands")
ContainerRegistry = flag.String("test.containerRegistry", "localhost:8082", "Container registry")
HideUnitTestLog = flag.Bool("test.hideUnitTestLog", false, "Hide unit tests logs and print it in a file")
InstallDataTransferPlugin = flag.Bool("test.installDataTransferPlugin", false, "Install data-transfer plugin on the source Artifactory server")
ciRunId = flag.String("ci.runId", "", "A unique identifier used as a suffix to create repositories and builds in the tests")
// Deprecated: ignored, kept so existing pipelines don't fail on an unknown flag.
_ = flag.Bool("test.installDataTransferPlugin", false, "[DEPRECATED] Ignored")
}

func CleanFileSystem() {
Expand Down
Loading