diff --git a/buildtools/cli.go b/buildtools/cli.go index 082af5afb..db434ee7c 100644 --- a/buildtools/cli.go +++ b/buildtools/cli.go @@ -393,23 +393,15 @@ func GetCommands() []cli.Command { }, }, { - Name: "docker", - Flags: cliutils.GetCommandFlags(cliutils.Docker), - Usage: docker.GetDescription(), - HelpName: corecommon.CreateUsage("docker", docker.GetDescription(), docker.Usage), - UsageText: docker.GetArguments(), - SkipFlagParsing: func() bool { - for i, arg := range os.Args { - // 'docker scan' isn't a docker client command. We won't skip its flags. - if arg == "docker" && len(os.Args) > i+1 && os.Args[i+1] == "scan" { - return false - } - } - return true - }(), - BashComplete: corecommon.CreateBashCompletionFunc("login", "push", "pull", "scan"), - Category: buildToolsCategory, - Action: dockerCmd, + Name: "docker", + Flags: cliutils.GetCommandFlags(cliutils.Docker), + Usage: docker.GetDescription(), + HelpName: corecommon.CreateUsage("docker", docker.GetDescription(), docker.Usage), + UsageText: docker.GetArguments(), + SkipFlagParsing: skipFlagParsingForDockerCmd(), + BashComplete: corecommon.CreateBashCompletionFunc("login", "push", "pull", "scan"), + Category: buildToolsCategory, + Action: dockerCmd, }, { Name: "terraform-config", @@ -453,6 +445,24 @@ func GetCommands() []cli.Command { return decorateWithFlagCapture(cmds) } +func skipFlagParsingForDockerCmd() bool { + isDockerScan := false + hasHelpFlag := false + for i, arg := range os.Args { + if arg == "docker" && len(os.Args) > i+1 && os.Args[i+1] == "scan" { + isDockerScan = true + } + if arg == "--help" || arg == "-h" { + hasHelpFlag = true + } + } + // 'docker scan' isn't a docker client command. We won't skip its flags. + if isDockerScan { + return hasHelpFlag + } + return true +} + // decorateWithFlagCapture injects a Before hook into every command returned from this package, // so we can capture user-provided flags consistently in one place for all build commands. func decorateWithFlagCapture(cmds []cli.Command) []cli.Command { @@ -964,6 +974,9 @@ func loginCmd(c *cli.Context) error { } func dockerScanCmd(c *cli.Context, imageTag string) error { + if show, err := cliutils.ShowGenericCmdHelpIfNeeded(c, c.Args(), securityCLI.DockerScanCmdHiddenName); show || err != nil { + return err + } convertedCtx, err := components.ConvertContext(c, securityDocs.GetCommandFlags(securityDocs.DockerScan)...) if err != nil { return err diff --git a/docker_test.go b/docker_test.go index 76068d8b8..9e2dae5e2 100644 --- a/docker_test.go +++ b/docker_test.go @@ -2,8 +2,8 @@ package main import ( "context" + "errors" "fmt" - tests2 "github.com/jfrog/jfrog-cli-artifactory/utils/tests" "os" "os/exec" "path" @@ -12,6 +12,8 @@ import ( "testing" "time" + tests2 "github.com/jfrog/jfrog-cli-artifactory/utils/tests" + "github.com/docker/docker/api/types/mount" biutils "github.com/jfrog/build-info-go/utils" @@ -601,17 +603,23 @@ func TestNativeDockerFlagParsing(t *testing.T) { defer cleanup() dockerTestCases := []struct { - name string - args []string + name string + args []string + expectedErr error }{ - {"docker", []string{"docker"}}, - {"docker version", []string{"docker", "version"}}, - {"docker scan", []string{"docker", "scan"}}, - {"cli flags after args", []string{"docker", "version", "--build-name=d", "--build-number=1", "--module=1"}}, - {"cli flags before args", []string{"docker", "--build-name=d", "--build-number=1", "--module=1", "version"}}, + {"docker", []string{"docker"}, nil}, + {"docker version", []string{"docker", "version"}, nil}, + {"docker scan", []string{"docker", "scan", "--min-severity=low"}, errors.New("a docker image name must be provided")}, + {"cli flags after args", []string{"docker", "version", "--build-name=d", "--build-number=1", "--module=1"}, nil}, + {"cli flags before args", []string{"docker", "--build-name=d", "--build-number=1", "--module=1", "version"}, nil}, } for _, testCase := range dockerTestCases { t.Run(testCase.name, func(t *testing.T) { + if testCase.expectedErr != nil { + err := runJfrogCliWithoutAssertion(testCase.args...) + assert.EqualError(t, err, testCase.expectedErr.Error()) + return + } runCmdWithRetries(t, jfCliTask(testCase.args...)) }) } diff --git a/go.mod b/go.mod index 5a862b796..c9c186555 100644 --- a/go.mod +++ b/go.mod @@ -19,10 +19,10 @@ require ( github.com/jfrog/gofrog v1.7.6 github.com/jfrog/jfrog-cli-application v1.0.2-0.20251120093802-1c39a37efcae github.com/jfrog/jfrog-cli-artifactory v0.7.3-0.20251118100843-ac34330a70d3 - github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20251120025936-6dba15f12343 + github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20251125083543-e689762c4ff0 github.com/jfrog/jfrog-cli-evidence v0.8.3-0.20251116083852-12dc534b4d13 github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20251114155350-7ea4c8e32d5a - github.com/jfrog/jfrog-cli-security v1.22.0 + github.com/jfrog/jfrog-cli-security v1.23.0 github.com/jfrog/jfrog-client-go v1.55.1-0.20251119183924-d765eb708cec github.com/jszwec/csvutil v1.10.0 github.com/manifoldco/promptui v0.9.0 @@ -278,6 +278,8 @@ replace github.com/docker/docker => github.com/docker/docker v27.5.1+incompatibl // replace github.com/jfrog/jfrog-cli-core/v2 => github.com/reshmifrog/jfrog-cli-core/v2 v2.58.5-0.20251110095124-ab9a4102ec5a -// replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20250812100044-b52afcc698c1 +// replace github.com/jfrog/jfrog-cli-core/v2 => github.com/attiasas/jfrog-cli-core/v2 v2.0.0-20251104113958-abd9de5958c4 -//replace github.com/jfrog/jfrog-cli-security => github.com/jfrog/jfrog-cli-security v1.17.2-0.20250511132918-d9cc4cd50020 +//replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.54.2-0.20251007084958-5eeaa42c31a6 + +// replace github.com/jfrog/jfrog-cli-security => github.com/jfrog/jfrog-cli-security dev diff --git a/go.sum b/go.sum index e8e656405..2da4e4d87 100644 --- a/go.sum +++ b/go.sum @@ -1161,14 +1161,14 @@ github.com/jfrog/jfrog-cli-application v1.0.2-0.20251120093802-1c39a37efcae h1:L github.com/jfrog/jfrog-cli-application v1.0.2-0.20251120093802-1c39a37efcae/go.mod h1:mBvgtVcGVjRAqc0b+TPmpYNz70nlXJqt1aitL0RGapA= github.com/jfrog/jfrog-cli-artifactory v0.7.3-0.20251118100843-ac34330a70d3 h1:sIjwBWBmyb7UEqP0IhQ22CWOedOPlNetyHzECS3sUyA= github.com/jfrog/jfrog-cli-artifactory v0.7.3-0.20251118100843-ac34330a70d3/go.mod h1:3hLZrM2xT+PkIevIGret4x1xDFTaVoNu3h374QnrKyc= -github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20251120025936-6dba15f12343 h1:mOEDdk2dMe3zCF83spCGwZbkvUN/LhmoJUS0vea8JxY= -github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20251120025936-6dba15f12343/go.mod h1:d9aADumiyjCBvZLffp8wldvP9XFHxcvk2PoOSUYms2g= +github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20251125083543-e689762c4ff0 h1:EsasTBE5i2MyCESS/icZxKIlObpGiOyW9K67MAaEWco= +github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20251125083543-e689762c4ff0/go.mod h1:d9aADumiyjCBvZLffp8wldvP9XFHxcvk2PoOSUYms2g= github.com/jfrog/jfrog-cli-evidence v0.8.3-0.20251116083852-12dc534b4d13 h1:V9KRanq6ulMMLLwJcnbN2+UlDa0/+sWrUEC2Dex48+E= github.com/jfrog/jfrog-cli-evidence v0.8.3-0.20251116083852-12dc534b4d13/go.mod h1:6KohlDOtLswaJ4YYi/FqflJEZTvt7yP7SA1cjGG0If4= github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20251114155350-7ea4c8e32d5a h1:2EhQHDB15mIRPDJ62MwO5pruugpHRkeZq5P0PR4jWKI= github.com/jfrog/jfrog-cli-platform-services v1.10.1-0.20251114155350-7ea4c8e32d5a/go.mod h1:qbu4iqBST9x8LgD8HhzUm91iOB3vHqtoGmaxOnmw0ok= -github.com/jfrog/jfrog-cli-security v1.22.0 h1:KNovA+BA1IpE0c0jI6jWF33fOimgylR9a7T84ZmgNJI= -github.com/jfrog/jfrog-cli-security v1.22.0/go.mod h1:uoACrGyWZViNPU0STC0fF38bVKtNXjm3hzWW/DKI0DY= +github.com/jfrog/jfrog-cli-security v1.23.0 h1:kV/NQhyID/P9Lf7D+sgscvkIDQ0l1sYMXnjs1EKWXaE= +github.com/jfrog/jfrog-cli-security v1.23.0/go.mod h1:qBAvU9kN41nReJk/O4V9Q/xwiXfAdyhqRIYaOjVm8nE= github.com/jfrog/jfrog-client-go v1.55.1-0.20251119183924-d765eb708cec h1:tNfeGi/2FuxIUSi8urFZuqa33grynAHwLRH6iIK/DB0= github.com/jfrog/jfrog-client-go v1.55.1-0.20251119183924-d765eb708cec/go.mod h1:ureS+L3wNs0qYUBSwH8C9PjwnraTX9ibZu7JkaqjO/E= github.com/jhump/protoreflect v1.17.0 h1:qOEr613fac2lOuTgWN4tPAtLL7fUSbuJL5X5XumQh94= diff --git a/main_test.go b/main_test.go index 87c056627..d4f057028 100644 --- a/main_test.go +++ b/main_test.go @@ -398,6 +398,14 @@ func TestSurvey_NotDisplayedOnNonHelp(t *testing.T) { assert.NotContains(t, string(contentErr), "https://") } +func TestDockerScanHelp(t *testing.T) { + t.Setenv("CI", "false") + jfrogCli := coreTests.NewJfrogCli(execMain, "jfrog", "") + content, _, err := tests.GetCmdOutput(t, jfrogCli, "docker", "scan", "--help") + require.NoError(t, err) + assert.Contains(t, string(content), "jfrog docker scan - Scan local docker image using the docker client and Xray.") +} + func TestSurvey_DisplayedOnHelp(t *testing.T) { t.Setenv("CI", "false") jfrogCli := coreTests.NewJfrogCli(execMain, "jfrog", "")