diff --git a/buildtools/cli.go b/buildtools/cli.go index 4daff389c..90c497cc7 100644 --- a/buildtools/cli.go +++ b/buildtools/cli.go @@ -3,8 +3,10 @@ package buildtools import ( "errors" "fmt" + dotnetutils "github.com/jfrog/build-info-go/build/utils/dotnet" conancommand "github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/conan" nixcommand "github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/nix" + nugetcommand "github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/nuget" "io/fs" "os" "os/exec" @@ -945,6 +947,11 @@ func NugetCmd(c *cli.Context) error { return cliutils.WrongNumberOfArgumentsHandler(c) } + // FlexPack native mode: bypass config file requirement + if artutils.ShouldRunNative("") { + return runNugetFlexPackCmd(c, dotnetutils.Nuget) + } + configFilePath, err := getProjectConfigPathOrThrow(project.Nuget, "nuget", "nuget-config") if err != nil { return err @@ -989,6 +996,11 @@ func DotnetCmd(c *cli.Context) error { return cliutils.WrongNumberOfArgumentsHandler(c) } + // FlexPack native mode: bypass config file requirement + if artutils.ShouldRunNative("") { + return runNugetFlexPackCmd(c, dotnetutils.DotnetCore) + } + // Get configuration file path. configFilePath, err := getProjectConfigPathOrThrow(project.Dotnet, "dotnet", "dotnet-config") if err != nil { @@ -2071,6 +2083,79 @@ func ConanCmd(c *cli.Context) error { return commands.ExecWithPackageManager(conanCommand, project.Conan.String()) } +// runNugetFlexPackCmd handles NuGet/dotnet commands in FlexPack native mode. +// No project config file is required; server details come from --server-id or the default profile. +func runNugetFlexPackCmd(c *cli.Context, toolchainType dotnetutils.ToolchainType) error { + args := cliutils.ExtractCommand(c) + + args, serverID, err := coreutils.ExtractServerIdFromCommand(args) + if err != nil { + return fmt.Errorf("extract server ID: %w", err) + } + + filteredArgs, buildConfiguration, err := build.ExtractBuildDetailsFromArgs(args) + if err != nil { + return err + } + + // Extract --repo-resolve and --repo flags. + var repoResolve, repoDeploy string + filteredArgs, repoResolve, err = coreutils.ExtractStringOptionFromArgs(filteredArgs, "repo-resolve") + if err != nil { + return fmt.Errorf("extract --repo-resolve: %w", err) + } + filteredArgs, repoDeploy, err = coreutils.ExtractStringOptionFromArgs(filteredArgs, "repo") + if err != nil { + return fmt.Errorf("extract --repo: %w", err) + } + + useNugetV2, err := cliutils.ExtractBoolFlagFromArgs(&filteredArgs, "nuget-v2") + if err != nil { + return err + } + allowInsecure, err := cliutils.ExtractBoolFlagFromArgs(&filteredArgs, "insecure-tls") + if err != nil { + return err + } + + cmdName, nugetArgs := getNugetCommandName(filteredArgs, toolchainType) + workingDir, err := filepath.Abs(".") + if err != nil { + return err + } + + nugetCmd := nugetcommand.NewNuGetFlexPackCommand(). + SetToolchainType(toolchainType). + SetSubCommand(cmdName). + SetArgs(nugetArgs). + SetRepoResolve(repoResolve). + SetRepoDeploy(repoDeploy). + SetUseNugetV2(useNugetV2). + SetAllowInsecureConnections(allowInsecure). + SetBuildConfiguration(buildConfiguration). + SetWorkingDir(workingDir) + + if nugetCmd.RequiresServerDetails() { + serverDetails, err := coreConfig.GetSpecificConfig(serverID, true, false) + if err != nil { + return err + } + nugetCmd.SetServerDetails(serverDetails) + } + + return commands.ExecWithPackageManager(nugetCmd, project.Nuget.String()) +} + +// getNugetCommandName parses the native NuGet command and handles dotnet's two-token +// "nuget push" subcommand without changing the argument list for any other command. +func getNugetCommandName(args []string, toolchainType dotnetutils.ToolchainType) (string, []string) { + commandName, commandArgs := getCommandName(args) + if toolchainType == dotnetutils.DotnetCore && commandName == "nuget" && len(commandArgs) > 0 && commandArgs[0] == "push" { + return "nuget push", commandArgs[1:] + } + return commandName, commandArgs +} + func NixCmd(c *cli.Context) error { if show, err := cliutils.ShowCmdHelpIfNeeded(c, c.Args()); show || err != nil { return err diff --git a/buildtools/cli_test.go b/buildtools/cli_test.go index c03c912b4..89e2b2753 100644 --- a/buildtools/cli_test.go +++ b/buildtools/cli_test.go @@ -5,6 +5,7 @@ import ( "os" "testing" + dotnetutils "github.com/jfrog/build-info-go/build/utils/dotnet" containerutils "github.com/jfrog/jfrog-cli-artifactory/artifactory/commands/ocicontainer" "github.com/jfrog/jfrog-cli-core/v2/plugins/components" securityDocs "github.com/jfrog/jfrog-cli-security/cli/docs" @@ -13,6 +14,53 @@ import ( "github.com/urfave/cli" ) +func TestGetNugetCommandName(t *testing.T) { + tests := []struct { + name string + toolchainType dotnetutils.ToolchainType + args []string + expectedCommand string + expectedArgs []string + }{ + { + name: "dotnet nuget push", + toolchainType: dotnetutils.DotnetCore, + args: []string{"nuget", "push", "Package.1.0.0.nupkg", "--skip-duplicate"}, + expectedCommand: "nuget push", + expectedArgs: []string{"Package.1.0.0.nupkg", "--skip-duplicate"}, + }, + { + name: "dotnet restore", + toolchainType: dotnetutils.DotnetCore, + args: []string{"restore", "Project.csproj"}, + expectedCommand: "restore", + expectedArgs: []string{"Project.csproj"}, + }, + { + name: "nuget push remains one token", + toolchainType: dotnetutils.Nuget, + args: []string{"push", "Package.1.0.0.nupkg"}, + expectedCommand: "push", + expectedArgs: []string{"Package.1.0.0.nupkg"}, + }, + { + name: "dotnet nuget non-push passthrough", + toolchainType: dotnetutils.DotnetCore, + args: []string{"nuget", "locals", "all", "--clear"}, + expectedCommand: "nuget", + expectedArgs: []string{"locals", "all", "--clear"}, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + actualCommand, actualArgs := getNugetCommandName(test.args, test.toolchainType) + assert.Equal(t, test.expectedCommand, actualCommand) + assert.Equal(t, test.expectedArgs, actualArgs) + }) + } +} + func TestExtractDockerBuildOptionsFromArgs(t *testing.T) { tests := []struct { name string diff --git a/go.mod b/go.mod index 1847d35d5..e2019675c 100644 --- a/go.mod +++ b/go.mod @@ -238,7 +238,7 @@ require ( helm.sh/helm/v3 v3.21.0 // indirect k8s.io/client-go v0.36.1 // indirect k8s.io/klog/v2 v2.140.0 // indirect - oras.land/oras-go/v2 v2.6.0 // indirect + oras.land/oras-go/v2 v2.6.1 // indirect sigs.k8s.io/yaml v1.6.0 // indirect ) @@ -249,3 +249,7 @@ require ( // replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260604085947-7c110b77b4b4 //replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.54.2-0.20251007084958-5eeaa42c31a6 + +replace github.com/jfrog/build-info-go => github.com/bhanurp/build-info-go v1.10.10-0.20260729175019-12ca2bdfff04 + +replace github.com/jfrog/jfrog-cli-artifactory => github.com/bhanurp/jfrog-cli-artifactory v0.1.12-0.20260729175419-4c07eea6deff diff --git a/go.sum b/go.sum index 7cc72b13c..6a72a226e 100644 --- a/go.sum +++ b/go.sum @@ -101,6 +101,10 @@ github.com/beevik/etree v1.6.0 h1:u8Kwy8pp9D9XeITj2Z0XtA5qqZEmtJtuXZRQi+j03eE= github.com/beevik/etree v1.6.0/go.mod h1:bh4zJxiIr62SOf9pRzN7UUYaEDa9HEKafK25+sLc0Gc= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bhanurp/build-info-go v1.10.10-0.20260729175019-12ca2bdfff04 h1:oNa4yw9haWLPPTFvxl0TYpJqeVS6qyBtUTkHwZ4GYnc= +github.com/bhanurp/build-info-go v1.10.10-0.20260729175019-12ca2bdfff04/go.mod h1:CYRUCvLKfyARjoJXLWAxce1qNUxTEtbRKAARkV42vpE= +github.com/bhanurp/jfrog-cli-artifactory v0.1.12-0.20260729175419-4c07eea6deff h1:+sfdVuMXxx9ADLtBWI/H7ArKE/h0Nld34YIR0mLnVKk= +github.com/bhanurp/jfrog-cli-artifactory v0.1.12-0.20260729175419-4c07eea6deff/go.mod h1:VtYzAnn0XUczOcTCyE+fWVgu3mEZoKvwPREEa7PKEM0= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M= @@ -394,8 +398,6 @@ 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.20260615080618-42488b58c305 h1:q7/hTPm6ibQf45CztScTgPb8cAmKIeQ9im0ClISsq7Y= -github.com/jfrog/build-info-go v1.13.1-0.20260615080618-42488b58c305/go.mod h1:CYRUCvLKfyARjoJXLWAxce1qNUxTEtbRKAARkV42vpE= github.com/jfrog/froggit-go v1.22.0 h1:eeN5F8sOUo+h2cXkzArAu4nvSdjkDTAZtgqwrct70qg= github.com/jfrog/froggit-go v1.22.0/go.mod h1:wRDryqyp3oe+eHgME2mpnEQmO8XBECIPagFwj0nHmdI= github.com/jfrog/go-mockhttp v0.3.1 h1:/wac8v4GMZx62viZmv4wazB5GNKs+GxawuS1u3maJH8= @@ -885,8 +887,8 @@ k8s.io/client-go v0.36.1 h1:FN/K8QIT2CEDt+2WB2HnWrUANZ50AP5GII43/SP2JR0= k8s.io/client-go v0.36.1/go.mod h1:s6rAnCtTGYDQnpNjEhSaISV+2O8jwruZ6m3QOYBFbtU= k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc= k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0= -oras.land/oras-go/v2 v2.6.0 h1:X4ELRsiGkrbeox69+9tzTu492FMUu7zJQW6eJU+I2oc= -oras.land/oras-go/v2 v2.6.0/go.mod h1:magiQDfG6H1O9APp+rOsvCPcW1GD2MM7vgnKY0Y+u1o= +oras.land/oras-go/v2 v2.6.1 h1:bonOEkjLfp8tt6qXWRRWP6p1F+9octchOf2EqnWB4Zs= +oras.land/oras-go/v2 v2.6.1/go.mod h1:dhtFrFOuZuDtAVeZ9FUnaa5zfzplG3ZnFX9/uH1J/Yk= pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk= pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04= sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs= diff --git a/nuget_test.go b/nuget_test.go index 796e0992d..d8929d07c 100644 --- a/nuget_test.go +++ b/nuget_test.go @@ -184,9 +184,9 @@ func testNugetCmd(t *testing.T, projectPath, buildName, buildNumber string, expe inttestutils.DeleteBuild(serverDetails.ArtifactoryUrl, buildName, artHttpDetails) } -// Add allow insecure connection for testings to work with localhost server +// Add --insecure-tls for tests that use a localhost server. func allowInsecureConnectionForTests(args *[]string) { - *args = append(*args, "--allow-insecure-connections") + *args = append(*args, "--insecure-tls") } func assertNugetDependencies(t *testing.T, module buildInfo.Module, moduleName string) { diff --git a/testdata/gradle/projectwithplugin/build/reports/problems/problems-report.html b/testdata/gradle/projectwithplugin/build/reports/problems/problems-report.html new file mode 100644 index 000000000..732833d47 --- /dev/null +++ b/testdata/gradle/projectwithplugin/build/reports/problems/problems-report.html @@ -0,0 +1,659 @@ + + + +
+ + + + + + + + +