From 012218a896b61423dec4a5aeb9a7bad34354e5f8 Mon Sep 17 00:00:00 2001 From: Kanishk Date: Fri, 4 Jul 2025 01:34:45 +0530 Subject: [PATCH] initial commit --- go.mod | 6 +- go.sum | 6 -- main.go | 67 ++++++++++++++++++ newImpl/utilityImpls.go | 148 ++++++++++++++++++++++++++++++++++++++++ utils/cliutils/utils.go | 6 +- 5 files changed, 221 insertions(+), 12 deletions(-) create mode 100644 newImpl/utilityImpls.go diff --git a/go.mod b/go.mod index 100ca495a..9818d100a 100644 --- a/go.mod +++ b/go.mod @@ -191,10 +191,10 @@ require ( // replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20250529104758-6d769a684388 -replace github.com/jfrog/jfrog-cli-artifactory => github.com/jfrog/jfrog-cli-artifactory v0.3.3-0.20250623095509-b3fe2c4681ad +replace github.com/jfrog/jfrog-cli-artifactory => ../jfrog-cli-artifactory -replace github.com/jfrog/jfrog-cli-core/v2 => github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20250629143350-c43614bbffcd +replace github.com/jfrog/jfrog-cli-core/v2 => ../jfrog-cli-core -replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20250629142537-bb24db402fe1 +replace github.com/jfrog/jfrog-client-go => ../jfrog-client-go //replace github.com/jfrog/jfrog-cli-security => github.com/jfrog/jfrog-cli-security v1.17.2-0.20250511132918-d9cc4cd50020 diff --git a/go.sum b/go.sum index b90da55c8..f06538fc6 100644 --- a/go.sum +++ b/go.sum @@ -186,16 +186,10 @@ github.com/jfrog/gofrog v1.7.6 h1:QmfAiRzVyaI7JYGsB7cxfAJePAZTzFz0gRWZSE27c6s= github.com/jfrog/gofrog v1.7.6/go.mod h1:ntr1txqNOZtHplmaNd7rS4f8jpA5Apx8em70oYEe7+4= github.com/jfrog/jfrog-apps-config v1.0.1 h1:mtv6k7g8A8BVhlHGlSveapqf4mJfonwvXYLipdsOFMY= github.com/jfrog/jfrog-apps-config v1.0.1/go.mod h1:8AIIr1oY9JuH5dylz2S6f8Ym2MaadPLR6noCBO4C22w= -github.com/jfrog/jfrog-cli-artifactory v0.3.3-0.20250623095509-b3fe2c4681ad h1:cnbcCK0VTHdLdmmv/9fYTRjuR1ewrYBW/S87pVE+d+s= -github.com/jfrog/jfrog-cli-artifactory v0.3.3-0.20250623095509-b3fe2c4681ad/go.mod h1:hnXaevmDyQpyhpH5kwDufIjUUXXuKs54i+AX2CEywKE= -github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20250629143350-c43614bbffcd h1:1Nw+HKbtQZGEogerQBNM77RvbUwHYNKFNYJk4lmNF9w= -github.com/jfrog/jfrog-cli-core/v2 v2.31.1-0.20250629143350-c43614bbffcd/go.mod h1:BkDHfCVecjcRNC+aqmHtTrKe+/K8MyjzmHYe5rER5Yg= github.com/jfrog/jfrog-cli-platform-services v1.10.0 h1:O+N/VAF+QjFvq9xkHpmzKLcdl9aJu3IP204Su0L14rw= github.com/jfrog/jfrog-cli-platform-services v1.10.0/go.mod h1:qbu4iqBST9x8LgD8HhzUm91iOB3vHqtoGmaxOnmw0ok= github.com/jfrog/jfrog-cli-security v1.19.0 h1:4qggon1biuOvjMjHZ5IWDA4Mh+qp2qecWEdeX6s4Xv8= github.com/jfrog/jfrog-cli-security v1.19.0/go.mod h1:QMoGTGfKMSnXOuWv3/IclZU+M/AshoJMt68Ft6l7EdE= -github.com/jfrog/jfrog-client-go v1.28.1-0.20250629142537-bb24db402fe1 h1:0t6dQHoalUDNVrfZujD3iCmDGLDl+ndHclFkmONSpq0= -github.com/jfrog/jfrog-client-go v1.28.1-0.20250629142537-bb24db402fe1/go.mod h1:1v0eih4thdPA4clBo9TuvAMT25sGDr1IQJ81DXQ/lBY= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jszwec/csvutil v1.10.0 h1:upMDUxhQKqZ5ZDCs/wy+8Kib8rZR8I8lOR34yJkdqhI= diff --git a/main.go b/main.go index 3aec5037a..cb238682a 100644 --- a/main.go +++ b/main.go @@ -3,9 +3,13 @@ package main import ( "crypto/rand" "encoding/hex" + "errors" "fmt" "github.com/agnivade/levenshtein" + gofrogcmd "github.com/jfrog/gofrog/io" artifactoryCLI "github.com/jfrog/jfrog-cli-artifactory/cli" + "github.com/jfrog/jfrog-cli-core/v2/common/build" + "github.com/jfrog/jfrog-cli-core/v2/common/project" corecommon "github.com/jfrog/jfrog-cli-core/v2/docs/common" "github.com/jfrog/jfrog-cli-core/v2/plugins/components" coreconfig "github.com/jfrog/jfrog-cli-core/v2/utils/config" @@ -28,6 +32,7 @@ import ( "github.com/jfrog/jfrog-cli/general/summary" "github.com/jfrog/jfrog-cli/general/token" "github.com/jfrog/jfrog-cli/missioncontrol" + "github.com/jfrog/jfrog-cli/newImpl" "github.com/jfrog/jfrog-cli/pipelines" "github.com/jfrog/jfrog-cli/plugins" "github.com/jfrog/jfrog-cli/plugins/utils" @@ -128,13 +133,75 @@ func execMain() error { if err = setUberTraceIdToken(); err != nil { clientlog.Warn("failed generating a trace ID token:", err.Error()) } + if os.Getenv("JFROG_RUN_NATIVE") == "true" { + // If the JFROG_RUN_NATIVE environment variable is set to true, we run the new implementation. + // This is used for testing purposes. + if err = runNativeImplementation(ctx); err != nil { + clientlog.Error("Failed to run native implementation:", err) + os.Exit(1) + } + os.Exit(0) + } return nil } + + app.CommandNotFound = func(c *cli.Context, command string) { + err := runNativeImplementation(c) + if err != nil { + clientlog.Error("Failed to run native implementation:", err) + os.Exit(1) + } + os.Exit(0) + } + err = app.Run(args) logTraceIdOnFailure(err) return err } +func runNativeImplementation(ctx *cli.Context) error { + // extract the build name and number from the command arguments + args, buildArgs, err := build.ExtractBuildDetailsFromArgs(ctx.Args()) + if len(args) < 2 { + return errors.New("jfrog jf " + strings.Join(args, " ") + " not specified") + } + buildName, err := buildArgs.GetBuildName() + buildNumber, err := buildArgs.GetBuildNumber() + + // create config if it doesn't exist + confType := args[0] + if confType == "bundle" { + confType = "gem" + } + err = cliutils.CreateConfigCmd(ctx, project.FromString(confType)) + if err != nil { + return err + } + + err = RunActions(args) + + if err != nil { + return err + } + + if buildName != "" && buildNumber != "" { + err = newImpl.GetBuildInfoForUploadedArtifacts(args[2], buildArgs) + } + + return err +} + +func RunActions(args []string) error { + executableCommand := append([]string{}, args[2:]...) + command := gofrogcmd.NewCommand(args[0], args[1], executableCommand) + _, _, _, err := gofrogcmd.RunCmdWithOutputParser(command, true) + if err != nil { + clientlog.Error("Error occurred while running command: ", err) + os.Exit(1) + } + return err +} + // This command generates and sets an Uber Trace ID token which will be attached as a header to every request. // This allows users to easily identify which logs on the server side are related to the command executed by the CLI. func setUberTraceIdToken() error { diff --git a/newImpl/utilityImpls.go b/newImpl/utilityImpls.go new file mode 100644 index 000000000..0256ce90b --- /dev/null +++ b/newImpl/utilityImpls.go @@ -0,0 +1,148 @@ +package newImpl + +import ( + "errors" + "fmt" + buildinfo "github.com/jfrog/build-info-go/entities" + "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" + buildUtils "github.com/jfrog/jfrog-cli-core/v2/common/build" + "github.com/jfrog/jfrog-cli-core/v2/common/project" + "github.com/jfrog/jfrog-cli-core/v2/utils/config" + "github.com/jfrog/jfrog-client-go/artifactory/services" + serviceutils "github.com/jfrog/jfrog-client-go/artifactory/services/utils" + specutils "github.com/jfrog/jfrog-client-go/artifactory/services/utils" + "github.com/jfrog/jfrog-client-go/utils/io/content" + "github.com/jfrog/jfrog-client-go/utils/log" +) + +type aqlResult struct { + Results []*serviceutils.ResultItem `json:"results,omitempty"` +} + +func GetFiles(pkgManager, fileUploaded string) ([]string, error) { + switch pkgManager { + case "gem": + return []string{fileUploaded + ".gem", fileUploaded + ".gemspec.rz", fileUploaded}, nil + default: + return []string{}, errors.New("unsupported package manager") + } +} + +func GetBuildInfoForUploadedArtifacts(uploadedFile string, buildConfiguration *buildUtils.BuildConfiguration) error { + repoConfig, err := extractRepositoryConfig() + if err != nil { + return err + } + serverDetails, err := repoConfig.ServerDetails() + if err != nil { + return err + } + err = saveBuildInfo(serverDetails, repoConfig.TargetRepo(), uploadedFile, buildConfiguration) + return err +} + +func saveBuildInfo(serverDetails *config.ServerDetails, searchRepo string, fileName string, buildConfiguration *buildUtils.BuildConfiguration) error { + servicesManager, err := utils.CreateServiceManager(serverDetails, -1, 0, false) + if err != nil { + return err + } + + var buildProps string + var searchReader *content.ContentReader + var buildName, buildNumber string + buildName, err = buildConfiguration.GetBuildName() + if err != nil { + return err + } + buildNumber, err = buildConfiguration.GetBuildNumber() + if err != nil { + return err + } + buildProject := buildConfiguration.GetProject() + + buildProps, err = getBuildPropsForArtifact(buildName, buildNumber, buildProject) + if err != nil { + return err + } + + searchQuery := CreateAqlQueryForSearch(searchRepo, fileName) + searchParams := services.SearchParams{ + CommonParams: &specutils.CommonParams{ + Aql: specutils.Aql{ + ItemsFind: searchQuery, + }, + }, + } + searchReader, err = servicesManager.SearchFiles(searchParams) + if err != nil { + log.Error("Failed to get uploaded npm package: ", err.Error()) + return err + } + + propsParams := services.PropsParams{ + Reader: searchReader, + Props: buildProps, + } + _, err = servicesManager.SetProps(propsParams) + if err != nil { + log.Warn("Unable to set build properties: ", err, "\nThis may cause build to not properly link with artifact, please add build name and build number properties on the tarball artifact manually") + } + buildInfoArtifacts, err := utils.ConvertArtifactsSearchDetailsToBuildInfoArtifacts(searchReader) + err = createBuildInfo(buildName, buildNumber, buildProject, buildConfiguration.GetModule(), buildInfoArtifacts) + if err != nil { + return err + } + return nil +} + +func getBuildPropsForArtifact(buildName, buildNumber, project string) (string, error) { + err := buildUtils.SaveBuildGeneralDetails(buildName, buildNumber, project) + if err != nil { + return "", err + } + return buildUtils.CreateBuildProperties(buildName, buildNumber, project) +} + +func createBuildInfo(buildName, buildNumber, project, moduleName string, artifacts []buildinfo.Artifact) error { + buildInfoService := buildUtils.CreateBuildInfoService() + build, err := buildInfoService.GetOrCreateBuildWithProject(buildName, buildNumber, project) + if err != nil { + return err + } + err = build.AddArtifacts(moduleName, "generic", artifacts...) + return err +} + +func extractRepositoryConfig() (*project.RepositoryConfig, error) { + prefix := project.ProjectConfigDeployerPrefix + configFilePath, exists, err := project.GetProjectConfFilePath(project.Gem) + if !exists { + return nil, fmt.Errorf("project configuration file not found for %s", project.Gem) + } + if err != nil { + return nil, err + } + vConfig, err := project.ReadConfigFile(configFilePath, project.YAML) + if err != nil { + return nil, err + } + repoConfig, err := project.GetRepoConfigByPrefix(configFilePath, prefix, vConfig) + if err != nil { + return nil, err + } + return repoConfig, nil +} + +func CreateAqlQueryForSearch(repo, file string) string { + itemsPart := + `{` + + `"repo": "%s",` + + `"$or": [{` + + `"$and":[{` + + `"path": {"$match": "*"},` + + `"name": {"$match": "%s"}` + + `}]` + + `}]` + + `}` + return fmt.Sprintf(itemsPart, repo, file) +} diff --git a/utils/cliutils/utils.go b/utils/cliutils/utils.go index 4a11ec798..dc5cbb714 100644 --- a/utils/cliutils/utils.go +++ b/utils/cliutils/utils.go @@ -476,9 +476,9 @@ func OverrideFieldsIfSet(spec *speccore.File, c *cli.Context) { } func CreateConfigCmd(c *cli.Context, confType project.ProjectType) error { - if c.NArg() != 0 { - return WrongNumberOfArgumentsHandler(c) - } + //if c.NArg() != 0 { + // return WrongNumberOfArgumentsHandler(c) + //} return commonCommands.CreateBuildConfig(c, confType) }