Skip to content
Open
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
225 changes: 85 additions & 140 deletions buildtools/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"errors"
"fmt"
conancommand "github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/conan"
nixcommand "github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/nix"
"io/fs"
"os"
"os/exec"
Expand Down Expand Up @@ -32,8 +33,8 @@
huggingfaceCommands "github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/huggingface"
"github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/mvn"
"github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/npm"
containerutils "github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/ocicontainer"
"github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/pnpm"
containerutils "github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/ocicontainer"
"github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/terraform"
"github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/yarn"
commandsUtils "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils"
Expand All @@ -53,7 +54,7 @@
"github.com/jfrog/jfrog-cli/docs/artifactory/terraformconfig"
twinedocs "github.com/jfrog/jfrog-cli/docs/artifactory/twine"
"github.com/jfrog/jfrog-cli/docs/buildtools/conan"
"github.com/jfrog/jfrog-cli/docs/buildtools/conanconfig"
"github.com/jfrog/jfrog-cli/docs/buildtools/nix"

Check failure on line 57 in buildtools/cli.go

View workflow job for this annotation

GitHub Actions / Lint

no required module provides package github.com/jfrog/jfrog-cli/docs/buildtools/nix; to add it:
"github.com/jfrog/jfrog-cli/docs/buildtools/docker"
dotnetdocs "github.com/jfrog/jfrog-cli/docs/buildtools/dotnet"
"github.com/jfrog/jfrog-cli/docs/buildtools/dotnetconfig"
Expand All @@ -69,17 +70,16 @@
"github.com/jfrog/jfrog-cli/docs/buildtools/mvnconfig"
"github.com/jfrog/jfrog-cli/docs/buildtools/npmcommand"
"github.com/jfrog/jfrog-cli/docs/buildtools/npmconfig"
"github.com/jfrog/jfrog-cli/docs/buildtools/pnpmcommand"
nugetdocs "github.com/jfrog/jfrog-cli/docs/buildtools/nuget"
"github.com/jfrog/jfrog-cli/docs/buildtools/nugetconfig"
"github.com/jfrog/jfrog-cli/docs/buildtools/pipconfig"
"github.com/jfrog/jfrog-cli/docs/buildtools/pipenvconfig"
"github.com/jfrog/jfrog-cli/docs/buildtools/pipenvinstall"
"github.com/jfrog/jfrog-cli/docs/buildtools/pipinstall"
"github.com/jfrog/jfrog-cli/docs/buildtools/pnpmcommand"
"github.com/jfrog/jfrog-cli/docs/buildtools/pnpmconfig"
"github.com/jfrog/jfrog-cli/docs/buildtools/poetry"
"github.com/jfrog/jfrog-cli/docs/buildtools/poetryconfig"
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"
"github.com/jfrog/jfrog-cli/docs/common"
Expand Down Expand Up @@ -358,19 +358,6 @@
Category: buildToolsCategory,
Action: PoetryCmd,
},
{
Name: "uv",
Flags: cliutils.GetCommandFlags(cliutils.Uv),
Usage: uvcommand.GetDescription(),
HelpName: corecommon.CreateUsage("uv", uvcommand.GetDescription(), uvcommand.Usage),
UsageText: uvcommand.GetArguments(),
ArgsUsage: common.CreateEnvVars(),
SkipFlagParsing: true,
BashComplete: corecommon.CreateBashCompletionFunc(),
Category: buildToolsCategory,
Action: UvCmd,
Hidden: true,
},
{
Name: "helm",
Flags: cliutils.GetCommandFlags(cliutils.Helm),
Expand All @@ -384,19 +371,6 @@
Category: buildToolsCategory,
Action: HelmCmd,
},
{
Name: "conan-config",
Flags: cliutils.GetCommandFlags(cliutils.ConanConfig),
Aliases: []string{"conanc"},
Usage: conanconfig.GetDescription(),
HelpName: corecommon.CreateUsage("conan-config", conanconfig.GetDescription(), conanconfig.Usage),
ArgsUsage: common.CreateEnvVars(),
BashComplete: corecommon.CreateBashCompletionFunc(),
Category: buildToolsCategory,
Action: func(c *cli.Context) error {
return cliutils.CreateConfigCmd(c, project.Conan)
},
},
{
Name: "conan",
Hidden: false,
Expand All @@ -410,6 +384,19 @@
Category: buildToolsCategory,
Action: ConanCmd,
},
{
Name: "nix",
Hidden: false,
Flags: cliutils.GetCommandFlags(cliutils.Nix),
Usage: nix.GetDescription(),
HelpName: corecommon.CreateUsage("nix", nix.GetDescription(), nix.Usage),
UsageText: nix.GetArguments(),
ArgsUsage: common.CreateEnvVars(),
SkipFlagParsing: true,
BashComplete: corecommon.CreateBashCompletionFunc(),
Category: buildToolsCategory,
Action: NixCmd,
},
{
Name: "ruby-config",
Flags: cliutils.GetCommandFlags(cliutils.RubyConfig),
Expand Down Expand Up @@ -707,12 +694,9 @@
if !xrayScan && format != "" {
return cliutils.PrintHelpAndReturnError("The --format option can be sent only with the --scan option", c)
}
scanOutputFormat := outputFormat.Table
if format != "" {
scanOutputFormat, err = outputFormat.ParseOutputFormat(format, outputFormat.All)
if err != nil {
return err
}
scanOutputFormat, err := outputFormat.GetOutputFormat(format)
if err != nil {
return err
}
mvnCmd := mvn.NewMvnCommand().SetConfiguration(buildConfiguration).SetConfigPath(configFilePath).SetGoals(filteredMavenArgs).SetThreads(threads).SetInsecureTls(insecureTls).SetDetailedSummary(detailedSummary || printDeploymentView).SetXrayScan(xrayScan).SetScanOutputFormat(scanOutputFormat)
err = commands.Exec(mvnCmd)
Expand Down Expand Up @@ -816,14 +800,9 @@
if !xrayScan && format != "" {
return cliutils.PrintHelpAndReturnError("The --format option can be sent only with the --scan option", c)
}
var scanOutputFormat outputFormat.OutputFormat
if format == "" {
scanOutputFormat = outputFormat.Table
} else {
scanOutputFormat, err = outputFormat.ParseOutputFormat(format, outputFormat.All)
if err != nil {
return err
}
scanOutputFormat, err := outputFormat.GetOutputFormat(format)
if err != nil {
return err
}
printDeploymentView := log.IsStdErrTerminal()
gradleCmd := gradle.NewGradleCommand().SetConfiguration(buildConfiguration).SetTasks(filteredGradleArgs).SetConfigPath(configFilePath).SetThreads(threads).SetDetailedSummary(detailedSummary || printDeploymentView).SetXrayScan(xrayScan).SetScanOutputFormat(scanOutputFormat)
Expand Down Expand Up @@ -1080,52 +1059,6 @@
return configFilePath, nil
}

// containerManagerEnvVar lets users force the container manager used by 'jf docker'
// subcommands, bypassing auto-detection. Accepted values (case-insensitive): "docker", "podman".
const containerManagerEnvVar = "JFROG_CLI_CONTAINER_MANAGER"

// podmanDetector is indirected through a package-level variable so tests can
// replace the real 'docker version' probe with a deterministic stub.
var podmanDetector = dockerIsPodman

// resolveContainerManagerType returns the container manager to use when running 'jf docker' subcommands.
//
// Resolution order:
// 1. Explicit override via the JFROG_CLI_CONTAINER_MANAGER env var ("docker" or "podman").
// 2. Auto-detection: if the local 'docker' binary reports Podman in its version output
// (i.e. the podman-docker shim or native podman aliased as docker), treat it as Podman
// so 'jf docker ...' works transparently for Podman users without daemon-socket access.
// 3. Default: Docker.
//
// Detection is intentionally conservative: only a positive "Podman" signal from 'docker version'
// switches behavior. Real Docker installations are unaffected.
func resolveContainerManagerType() containerutils.ContainerManagerType {
switch strings.ToLower(strings.TrimSpace(os.Getenv(containerManagerEnvVar))) {
case "podman":
log.Debug(containerManagerEnvVar + "=podman. Routing 'jf docker' subcommands through Podman.")
return containerutils.Podman
case "docker":
log.Debug(containerManagerEnvVar + "=docker. Routing 'jf docker' subcommands through Docker.")
return containerutils.DockerClient
}
if podmanDetector() {
log.Debug("Detected Podman-backed 'docker' CLI. Routing 'jf docker' subcommands through Podman.")
return containerutils.Podman
}
return containerutils.DockerClient
}

// dockerIsPodman returns true if the local 'docker' binary is actually Podman
// (either via the podman-docker shim or an alias). Any error or missing binary returns false.
func dockerIsPodman() bool {
cmd := exec.Command("docker", "version")
out, err := cmd.CombinedOutput()
if err != nil {
return false
}
return strings.Contains(strings.ToLower(string(out)), "podman")
}

func dockerCmd(c *cli.Context) error {
args := cliutils.ExtractCommand(c)
var cmd, cmdArg string
Expand Down Expand Up @@ -1177,7 +1110,7 @@
if err != nil {
return err
}
PullCommand := container.NewPullCommand(resolveContainerManagerType())
PullCommand := container.NewPullCommand(containerutils.DockerClient)
PullCommand.SetCmdParams(filteredDockerArgs).SetSkipLogin(skipLogin).SetImageTag(image).SetServerDetails(rtDetails).SetBuildConfiguration(buildConfiguration)
supported, err := PullCommand.IsGetRepoSupported()
if err != nil {
Expand All @@ -1201,7 +1134,7 @@
return
}
printDeploymentView := log.IsStdErrTerminal()
pushCommand := container.NewPushCommand(resolveContainerManagerType())
pushCommand := container.NewPushCommand(containerutils.DockerClient)
pushCommand.SetThreads(threads).SetDetailedSummary(detailedSummary || printDeploymentView).SetCmdParams(filteredDockerArgs).SetSkipLogin(skipLogin).SetBuildConfiguration(buildConfiguration).SetServerDetails(rtDetails).SetValidateSha(validateSha).SetImageTag(image)
supported, err := pushCommand.IsGetRepoSupported()
if err != nil {
Expand Down Expand Up @@ -1524,7 +1457,7 @@
if err != nil {
return err
}
cm := containerutils.NewManager(resolveContainerManagerType())
cm := containerutils.NewManager(containerutils.DockerClient)
return cm.RunNativeCmd(cleanArgs)
}

Expand Down Expand Up @@ -1831,53 +1764,6 @@
return pythonCmd(c, project.Poetry)
}

func UvCmd(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)
filteredArgs, buildConfiguration, err := build.ExtractBuildDetailsFromArgs(args)
if err != nil {
return err
}
var serverID string
filteredArgs, serverID, err = coreutils.ExtractServerIdFromCommand(filteredArgs)
if err != nil {
return fmt.Errorf("failed to extract server ID: %w", err)
}
cmdName, uvArgs := getCommandName(filteredArgs)
// Peek at --publish-url to populate DeployerRepo for build-info enrichment.
// The flag is NOT consumed here — it is forwarded to uv as-is.
deployerRepo := ""
for i, arg := range uvArgs {
if strings.HasPrefix(arg, "--publish-url=") {
deployerRepo = strings.TrimPrefix(arg, "--publish-url=")
} else if arg == "--publish-url" && i+1 < len(uvArgs) {
deployerRepo = uvArgs[i+1]
}
}
uvCommand := python.NewNativeUVCommand().
SetCommandName(cmdName).
SetArgs(uvArgs).
SetServerID(serverID).
SetDeployerRepo(deployerRepo).
SetBuildConfiguration(buildConfiguration)
// For help requests, bypass commands.Exec() to skip the concurrent usage-reporting
// goroutine that would otherwise make Artifactory version calls unnecessarily.
for _, a := range uvArgs {
if a == "-h" || a == "--help" {
return uvCommand.Run()
}
}
if cmdName == "help" || cmdName == "" {
return uvCommand.Run()
}
return commands.Exec(uvCommand)
}

// HelmCmd executes Helm commands with build info collection support
func HelmCmd(c *cli.Context) error {
if show, err := cliutils.ShowCmdHelpIfNeeded(c, c.Args()); show || err != nil {
Expand Down Expand Up @@ -2007,6 +1893,65 @@
return commands.Exec(conanCommand)
}

func NixCmd(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)

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

// Extract --repo and --server-id flags before passing to nix
var repo, serverID string
var cleanedArgs []string
for i := 0; i < len(filteredArgs); i++ {
arg := filteredArgs[i]
if strings.HasPrefix(arg, "--repo=") {
repo = strings.TrimPrefix(arg, "--repo=")
} else if arg == "--repo" && i+1 < len(filteredArgs) {
repo = filteredArgs[i+1]
i++
} else if strings.HasPrefix(arg, "--server-id=") {
serverID = strings.TrimPrefix(arg, "--server-id=")
} else if arg == "--server-id" && i+1 < len(filteredArgs) {
serverID = filteredArgs[i+1]
i++
} else {
cleanedArgs = append(cleanedArgs, arg)
}
}
filteredArgs = cleanedArgs

cmdName, nixArgs := getCommandName(filteredArgs)

// Use jfrog-cli-artifactory Nix command with build info support
cmd := nixcommand.NewNixCommand().SetCommandName(cmdName).SetArgs(nixArgs).SetBuildConfiguration(buildConfiguration)
if repo != "" {
cmd.SetRepo(repo)
}

// Pass server details — use specific server if --server-id provided, else default
var serverDetails *coreConfig.ServerDetails
if serverID != "" {
serverDetails, err = coreConfig.GetSpecificConfig(serverID, true, true)
} else {
serverDetails, err = coreConfig.GetDefaultServerConf()
}
if err == nil && serverDetails != nil {
cmd.SetServerDetails(serverDetails)
}

return commands.Exec(cmd)
}

func pythonCmd(c *cli.Context, projectType project.ProjectType) error {
if show, err := cliutils.ShowCmdHelpIfNeeded(c, c.Args()); show || err != nil {
return err
Expand Down
6 changes: 5 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ require (
github.com/jfrog/build-info-go v1.13.1-0.20260429070557-93b98034d295
github.com/jfrog/gofrog v1.7.6
github.com/jfrog/jfrog-cli-application v1.0.2-0.20260405065840-c930d515ef34
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260429074430-a5871f2898b5
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260507055916-1a22779f8183
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260430125911-ad12ac6f1316
github.com/jfrog/jfrog-cli-evidence v0.9.2
github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20260430094150-ce7d9b371c6f
Expand Down Expand Up @@ -248,6 +248,10 @@ require (

//replace github.com/ktrysmt/go-bitbucket => github.com/ktrysmt/go-bitbucket v0.9.80

replace github.com/jfrog/jfrog-cli-artifactory => github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260507045358-c25254577a25

replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.13.1-0.20260507043136-ec39c1c5ff9e

// replace github.com/jfrog/jfrog-cli-artifactory => github.com/agrasth/jfrog-cli-artifactory v0.2.2-0.20260428100316-aa702370ec20

// replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.13.1-0.20260428071432-1e9d9a1991ad
Expand Down
10 changes: 4 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -406,8 +406,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.20260429070557-93b98034d295 h1:EH0h86KwGvNHWyEBQoHoU9WfMMKy1GJ6jJQNmfy6E0U=
github.com/jfrog/build-info-go v1.13.1-0.20260429070557-93b98034d295/go.mod h1:+OCtMb22/D+u7Wne5lzkjJjaWr0LRZcHlDwTH86Mpwo=
github.com/jfrog/build-info-go v1.13.1-0.20260507043136-ec39c1c5ff9e h1:4EEOa1EFVmqGEXtXaXINvwr3fohBPEdU04J+tMaw6Nw=
github.com/jfrog/build-info-go v1.13.1-0.20260507043136-ec39c1c5ff9e/go.mod h1:+OCtMb22/D+u7Wne5lzkjJjaWr0LRZcHlDwTH86Mpwo=
github.com/jfrog/froggit-go v1.21.1 h1:I/XUOO6GQ1d/rmBlM361F8T654C3ohIWrpw23xNL9JY=
github.com/jfrog/froggit-go v1.21.1/go.mod h1:umBiakJB0CSPFfe0AHVaC3n9xsmUT7NGkDCny3bRchI=
github.com/jfrog/go-mockhttp v0.3.1 h1:/wac8v4GMZx62viZmv4wazB5GNKs+GxawuS1u3maJH8=
Expand All @@ -418,10 +418,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.20260405065840-c930d515ef34 h1:qD53oDmaw7+5HjaU7FupqbB55saabNzMoMtu3kJfmg4=
github.com/jfrog/jfrog-cli-application v1.0.2-0.20260405065840-c930d515ef34/go.mod h1:xum2HquWO5uExa/A7MQs3TgJJVEeoqTR+6Z4mfBr1Xw=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260429074430-a5871f2898b5 h1:+52DDmdSZFP1dxgeu0pkB1sQuoHa0PWbW7HVdFOqK3A=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260429074430-a5871f2898b5/go.mod h1:BV+aCTQsaZeFec2WjgmQjqlxecju4CkkM9NqfiFyjo0=
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260430091103-6242ecf15d29 h1:J5+08rOpv/avgt53jNFZ+j5gU8mllcj7Dcfja5Ewodw=
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260430091103-6242ecf15d29/go.mod h1:bjAkVD8c2W+jg4whqy10bSXDC/c+Se8/ll/GPp5F/+0=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260507045358-c25254577a25 h1:fJ67ikaYGaINyE4mM/dA8URv9IyAiuF9znVQ1CtOjjM=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260507045358-c25254577a25/go.mod h1:9l8+WjlIb9bn+HA4eRFD6GTU/Fzy+2O97VM/AvHHg1Y=
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260430125911-ad12ac6f1316 h1:xAl5D+SjLeRH1gCsSHFPpXJeQQBv2HDGqDTDkFOKJ2s=
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260430125911-ad12ac6f1316/go.mod h1:bjAkVD8c2W+jg4whqy10bSXDC/c+Se8/ll/GPp5F/+0=
github.com/jfrog/jfrog-cli-evidence v0.9.2 h1:huiBzQSI9z3OF3l2RphthdXl1aH9zBsvAt+zLsApORI=
Expand Down
Loading
Loading