diff --git a/artifactory/commands/npm/npmcommand.go b/artifactory/commands/npm/npmcommand.go index 47c57b37f..079bc1714 100644 --- a/artifactory/commands/npm/npmcommand.go +++ b/artifactory/commands/npm/npmcommand.go @@ -4,6 +4,11 @@ import ( "bufio" "errors" "fmt" + "os" + "path/filepath" + "strconv" + "strings" + "github.com/jfrog/build-info-go/build" biUtils "github.com/jfrog/build-info-go/build/utils" "github.com/jfrog/gofrog/version" @@ -18,10 +23,6 @@ import ( "github.com/jfrog/jfrog-client-go/utils/errorutils" "github.com/jfrog/jfrog-client-go/utils/log" "github.com/spf13/viper" - "os" - "path/filepath" - "strconv" - "strings" ) const ( @@ -31,7 +32,7 @@ const ( // Scoped authentication env var that sets the _auth or _authToken npm config variables. npmConfigAuthEnv = "npm_config_%s:%s" - npmVersionSupportingScopedAuthEnv = "9.3.1" + npmVersionSupportingScopedAuthEnv = "9.2.0" // Legacy un-scoped auth env vars doesn't support access tokens (with _authToken suffix). npmLegacyConfigAuthEnv = "npm_config__auth" ) diff --git a/artifactory/commands/transferfiles/transfer.go b/artifactory/commands/transferfiles/transfer.go index f303c1ca9..31b3f77a8 100644 --- a/artifactory/commands/transferfiles/transfer.go +++ b/artifactory/commands/transferfiles/transfer.go @@ -289,7 +289,7 @@ func (tdc *TransferFilesCommand) reportTransferFilesUsage() { AttributeValue: sourceStorageInfo.BinariesSize, }, } - if err = usage.NewArtifactoryCallHome().SendUsage(coreutils.GetCliUserAgent(), tdc.CommandName(), tdc.targetStorageInfoManager.GetServiceManager(), reportUsageAttributes...); err != nil { + if err = usage.NewArtifactoryCallHome().Send(coreutils.GetCliUserAgent(), tdc.CommandName(), tdc.targetStorageInfoManager.GetServiceManager(), reportUsageAttributes...); err != nil { log.Debug(err.Error()) } } diff --git a/artifactory/utils/commandsummary/buildinfosummary.go b/artifactory/utils/commandsummary/buildinfosummary.go index 806cf59a6..8071b7694 100644 --- a/artifactory/utils/commandsummary/buildinfosummary.go +++ b/artifactory/utils/commandsummary/buildinfosummary.go @@ -2,13 +2,14 @@ package commandsummary import ( "fmt" + "net/url" + "path" + "strings" + buildInfo "github.com/jfrog/build-info-go/entities" "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils/container" "github.com/jfrog/jfrog-client-go/utils/log" - "net/url" - "path" - "strings" ) const ( @@ -62,8 +63,14 @@ func (bis *BuildInfoSummary) GenerateMarkdownFromFiles(dataFilePaths []string) ( return } - buildInfoTableMarkdown := bis.buildInfoTable(builds) - publishedModulesMarkdown := bis.buildInfoModules(builds) + buildInfoTableMarkdown, err := bis.buildInfoTable(builds) + if err != nil { + return "", err + } + publishedModulesMarkdown, err := bis.buildInfoModules(builds) + if err != nil { + return "", err + } if publishedModulesMarkdown != "" { publishedModulesMarkdown = WrapCollapsableMarkdown(modulesTitle, publishedModulesMarkdown, 2) } @@ -73,61 +80,75 @@ func (bis *BuildInfoSummary) GenerateMarkdownFromFiles(dataFilePaths []string) ( } // Create a table with published builds and possible scan results. -func (bis *BuildInfoSummary) buildInfoTable(builds []*buildInfo.BuildInfo) string { +func (bis *BuildInfoSummary) buildInfoTable(builds []*buildInfo.BuildInfo) (string, error) { var tableBuilder strings.Builder tableBuilder.WriteString(getBuildInfoTableHeader()) for _, build := range builds { - appendBuildInfoRow(&tableBuilder, build) + if err := appendBuildInfoRow(&tableBuilder, build); err != nil { + return "", err + } } tableBuilder.WriteString("\n\n") - return tableBuilder.String() + return tableBuilder.String(), nil } // Generates a view for published modules within the build. // Modules are displayed as tables if they are scannable via CLI command, // otherwise, they are shown as an artifact tree. -func (bis *BuildInfoSummary) buildInfoModules(builds []*buildInfo.BuildInfo) string { +func (bis *BuildInfoSummary) buildInfoModules(builds []*buildInfo.BuildInfo) (string, error) { var markdownBuilder strings.Builder markdownBuilder.WriteString("\n\n

Published Modules

\n\n") var shouldGenerate bool for _, build := range builds { supportedModules := filterModules(build.Modules...) - if modulesMarkdown := bis.generateModulesMarkdown(supportedModules...); modulesMarkdown != "" { + modulesMarkdown, err := bis.generateModulesMarkdown(supportedModules...) + if err != nil { + return "", err + } + if modulesMarkdown != "" { markdownBuilder.WriteString(modulesMarkdown) shouldGenerate = true } } if !shouldGenerate { - return "" + return "", nil } - return markdownBuilder.String() + return markdownBuilder.String(), nil } -func (bis *BuildInfoSummary) generateModulesMarkdown(modules ...buildInfo.Module) string { +func (bis *BuildInfoSummary) generateModulesMarkdown(modules ...buildInfo.Module) (string, error) { var modulesMarkdown strings.Builder // Modules could include nested modules inside of them // Group the modules by their root module ID // If a module has no root, it is considered as a root module itself. groupedModuleMap := groupModules(modules) if len(groupedModuleMap) == 0 { - return "" + return "", nil } for rootModuleID, subModules := range groupedModuleMap { if len(subModules) == 0 { continue } if !scannableModuleType[subModules[0].Type] { - modulesMarkdown.WriteString(bis.generateModuleArtifactTree(rootModuleID, subModules)) + tree, err := bis.generateModuleArtifactTree(rootModuleID, subModules) + if err != nil { + return "", err + } + modulesMarkdown.WriteString(tree) } else { - modulesMarkdown.WriteString(bis.generateModuleTableView(rootModuleID, subModules)) + view, err := bis.generateModuleTableView(rootModuleID, subModules) + if err != nil { + return "", err + } + modulesMarkdown.WriteString(view) } } - return modulesMarkdown.String() + return modulesMarkdown.String(), nil } -func (bis *BuildInfoSummary) generateModuleArtifactTree(rootModuleID string, nestedModules []buildInfo.Module) string { +func (bis *BuildInfoSummary) generateModuleArtifactTree(rootModuleID string, nestedModules []buildInfo.Module) (string, error) { if len(nestedModules) == 0 { - return "" + return "", nil } var markdownBuilder strings.Builder isMultiModule := len(nestedModules) > 1 @@ -140,26 +161,33 @@ func (bis *BuildInfoSummary) generateModuleArtifactTree(rootModuleID string, nes if isMultiModule && rootModuleID == module.Id { continue } - markdownBuilder.WriteString(fmt.Sprintf("\n\n
%s
\n\n", bis.generateModuleArtifactsTree(&module, isMultiModule))) + tree, err := bis.generateModuleArtifactsTree(&module, isMultiModule) + if err != nil { + return "", err + } + markdownBuilder.WriteString(fmt.Sprintf("\n\n
%s
\n\n", tree)) } - return markdownBuilder.String() + return markdownBuilder.String(), nil } -func (bis *BuildInfoSummary) generateModuleTableView(rootModuleID string, subModules []buildInfo.Module) string { +func (bis *BuildInfoSummary) generateModuleTableView(rootModuleID string, subModules []buildInfo.Module) (string, error) { var markdownBuilder strings.Builder markdownBuilder.WriteString(generateModuleHeader(rootModuleID)) markdownBuilder.WriteString(generateModuleTableHeader()) isMultiModule := len(subModules) > 1 - nestedModuleMarkdownTree := bis.generateTableModuleMarkdown(subModules, rootModuleID, isMultiModule) + nestedModuleMarkdownTree, err := bis.generateTableModuleMarkdown(subModules, rootModuleID, isMultiModule) + if err != nil { + return "", err + } scanResult := getScanResults(extractDockerImageTag(subModules)) markdownBuilder.WriteString(generateTableRow(nestedModuleMarkdownTree, scanResult)) - return markdownBuilder.String() + return markdownBuilder.String(), nil } -func (bis *BuildInfoSummary) generateTableModuleMarkdown(nestedModules []buildInfo.Module, parentModuleID string, isMultiModule bool) string { +func (bis *BuildInfoSummary) generateTableModuleMarkdown(nestedModules []buildInfo.Module, parentModuleID string, isMultiModule bool) (string, error) { var nestedModuleMarkdownTree strings.Builder if len(nestedModules) == 0 { - return "" + return "", nil } if !StaticMarkdownConfig.IsExtendedSummary() { @@ -174,19 +202,26 @@ func (bis *BuildInfoSummary) generateTableModuleMarkdown(nestedModules []buildIn if isMultiModule && parentModuleID == module.Id { continue } - nestedModuleMarkdownTree.WriteString(bis.generateModuleArtifactsTree(&module, isMultiModule)) + tree, err := bis.generateModuleArtifactsTree(&module, isMultiModule) + if err != nil { + return "", err + } + nestedModuleMarkdownTree.WriteString(tree) } nestedModuleMarkdownTree.WriteString(appendSpacesToTableColumn("")) nestedModuleMarkdownTree.WriteString("") - return nestedModuleMarkdownTree.String() + return nestedModuleMarkdownTree.String(), nil } -func (bis *BuildInfoSummary) generateModuleArtifactsTree(module *buildInfo.Module, shouldCollapseArtifactsTree bool) string { - artifactsTree := bis.createArtifactsTree(module) +func (bis *BuildInfoSummary) generateModuleArtifactsTree(module *buildInfo.Module, shouldCollapseArtifactsTree bool) (string, error) { + artifactsTree, err := bis.createArtifactsTree(module) + if err != nil { + return "", err + } if shouldCollapseArtifactsTree { - return bis.generateModuleCollapsibleSection(module, artifactsTree) + return bis.generateModuleCollapsibleSection(module, artifactsTree), nil } - return artifactsTree + return artifactsTree, nil } func (bis *BuildInfoSummary) generateModuleCollapsibleSection(module *buildInfo.Module, sectionContent string) string { @@ -198,12 +233,16 @@ func (bis *BuildInfoSummary) generateModuleCollapsibleSection(module *buildInfo. } } -func (bis *BuildInfoSummary) createArtifactsTree(module *buildInfo.Module) string { +func (bis *BuildInfoSummary) createArtifactsTree(module *buildInfo.Module) (string, error) { artifactsTree := utils.NewFileTree() for _, artifact := range module.Artifacts { var artifactUrlInArtifactory string + var err error if StaticMarkdownConfig.IsExtendedSummary() { - artifactUrlInArtifactory = generateArtifactUrl(artifact) + artifactUrlInArtifactory, err = generateArtifactUrl(artifact, *module) + if err != nil { + return "", err + } } if artifact.OriginalDeploymentRepo == "" { artifact.OriginalDeploymentRepo = " " @@ -211,17 +250,24 @@ func (bis *BuildInfoSummary) createArtifactsTree(module *buildInfo.Module) strin artifactTreePath := path.Join(artifact.OriginalDeploymentRepo, artifact.Path) artifactsTree.AddFile(artifactTreePath, artifactUrlInArtifactory) if artifactsTree.IsTreeExceedsMax() { - return "" + return "", nil } } - return artifactsTree.String() + return artifactsTree.String(), nil } -func generateArtifactUrl(artifact buildInfo.Artifact) string { +func generateArtifactUrl(artifact buildInfo.Artifact, module buildInfo.Module) (string, error) { if strings.TrimSpace(artifact.OriginalDeploymentRepo) == "" { - return "" + return "", nil + } + var section summarySection + + if module.Type == buildInfo.Generic { + section = artifactsSection + } else { + section = packagesSection } - return GenerateArtifactUrl(path.Join(artifact.OriginalDeploymentRepo, artifact.Path)) + return GenerateArtifactUrl(path.Join(artifact.OriginalDeploymentRepo, artifact.Path), section) } func groupModules(modules []buildInfo.Module) map[string][]buildInfo.Module { @@ -280,16 +326,21 @@ func appendSpacesToTableColumn(str string) string { return str } -func appendBuildInfoRow(tableBuilder *strings.Builder, build *buildInfo.BuildInfo) { +func appendBuildInfoRow(tableBuilder *strings.Builder, build *buildInfo.BuildInfo) error { buildName := build.Name + " " + build.Number buildScanResult := getScanResults(buildName) if StaticMarkdownConfig.IsExtendedSummary() { - tableBuilder.WriteString(fmt.Sprintf("| [%s](%s) %s | %s | %s | \n", buildName, build.BuildUrl, appendSpacesToTableColumn(""), appendSpacesToTableColumn(buildScanResult.GetViolations()), appendSpacesToTableColumn(buildScanResult.GetVulnerabilities()))) + buildInfoUrl, err := addGitHubTrackingToUrl(build.BuildUrl, buildInfoSection) + if err != nil { + return err + } + tableBuilder.WriteString(fmt.Sprintf("| [%s](%s) %s | %s | %s | \n", buildName, buildInfoUrl, appendSpacesToTableColumn(""), appendSpacesToTableColumn(buildScanResult.GetViolations()), appendSpacesToTableColumn(buildScanResult.GetVulnerabilities()))) } else { upgradeMessage := fmt.Sprintf(basicSummaryUpgradeNotice, StaticMarkdownConfig.GetExtendedSummaryLangPage()) buildName = fmt.Sprintf(" %s %s", upgradeMessage, buildName) tableBuilder.WriteString(fmt.Sprintf("| %s %s | %s | %s |\n", fitInsideMarkdownTable(buildName), appendSpacesToTableColumn(""), appendSpacesToTableColumn(buildScanResult.GetViolations()), appendSpacesToTableColumn(buildScanResult.GetVulnerabilities()))) } + return nil } func getBuildInfoTableHeader() string { diff --git a/artifactory/utils/commandsummary/buildinfosummary_test.go b/artifactory/utils/commandsummary/buildinfosummary_test.go index 7b20f072e..a533cde2a 100644 --- a/artifactory/utils/commandsummary/buildinfosummary_test.go +++ b/artifactory/utils/commandsummary/buildinfosummary_test.go @@ -1,15 +1,16 @@ package commandsummary import ( - buildInfo "github.com/jfrog/build-info-go/entities" - buildinfo "github.com/jfrog/build-info-go/entities" - "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" - "github.com/stretchr/testify/assert" "os" "path/filepath" "regexp" "strings" "testing" + + buildInfo "github.com/jfrog/build-info-go/entities" + buildinfo "github.com/jfrog/build-info-go/entities" + "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + "github.com/stretchr/testify/assert" ) const ( @@ -58,6 +59,8 @@ func prepareBuildInfoTest() (*BuildInfoSummary, func()) { return buildInfoSummary, cleanup } +const buildUrl = "http://myJFrogPlatform/builds/buildName/123?gh_job_id=JFrog+CLI+Core+Tests&gh_section=buildInfo" + func TestBuildInfoTable(t *testing.T) { buildInfoSummary, cleanUp := prepareBuildInfoTest() defer func() { @@ -68,17 +71,19 @@ func TestBuildInfoTable(t *testing.T) { Name: "buildName", Number: "123", Started: "2024-05-05T12:47:20.803+0300", - BuildUrl: "http://myJFrogPlatform/builds/buildName/123", + BuildUrl: buildUrl, }, } t.Run("Extended Summary", func(t *testing.T) { StaticMarkdownConfig.setExtendedSummary(true) - res := buildInfoSummary.buildInfoTable(builds) + res, err := buildInfoSummary.buildInfoTable(builds) + assert.NoError(t, err) testMarkdownOutput(t, getTestDataFile(t, buildInfoTable), res) }) t.Run("Basic Summary", func(t *testing.T) { StaticMarkdownConfig.setExtendedSummary(false) - res := buildInfoSummary.buildInfoTable(builds) + res, err := buildInfoSummary.buildInfoTable(builds) + assert.NoError(t, err) testMarkdownOutput(t, getTestDataFile(t, buildInfoTable), res) }) } @@ -93,7 +98,7 @@ func TestBuildInfoModulesMaven(t *testing.T) { Name: "buildName", Number: "123", Started: "2024-05-05T12:47:20.803+0300", - BuildUrl: "http://myJFrogPlatform/builds/buildName/123", + BuildUrl: buildUrl, Modules: []buildinfo.Module{ { Id: "maven", @@ -113,12 +118,14 @@ func TestBuildInfoModulesMaven(t *testing.T) { t.Run("Extended Summary", func(t *testing.T) { StaticMarkdownConfig.setExtendedSummary(true) - res := buildInfoSummary.buildInfoModules(builds) + res, err := buildInfoSummary.buildInfoModules(builds) + assert.NoError(t, err) testMarkdownOutput(t, getTestDataFile(t, mavenModule), res) }) t.Run("Basic Summary", func(t *testing.T) { StaticMarkdownConfig.setExtendedSummary(false) - res := buildInfoSummary.buildInfoModules(builds) + res, err := buildInfoSummary.buildInfoModules(builds) + assert.NoError(t, err) testMarkdownOutput(t, getTestDataFile(t, mavenModule), res) }) } @@ -133,7 +140,7 @@ func TestBuildInfoModulesMavenWithSubModules(t *testing.T) { Name: "buildName", Number: "123", Started: "2024-05-05T12:47:20.803+0300", - BuildUrl: "http://myJFrogPlatform/builds/buildName/123", + BuildUrl: buildUrl, Modules: []buildinfo.Module{ { Id: "maven", @@ -179,12 +186,14 @@ func TestBuildInfoModulesMavenWithSubModules(t *testing.T) { t.Run("Extended Summary", func(t *testing.T) { StaticMarkdownConfig.setExtendedSummary(true) - res := buildInfoSummary.buildInfoModules(builds) + res, err := buildInfoSummary.buildInfoModules(builds) + assert.NoError(t, err) testMarkdownOutput(t, getTestDataFile(t, mavenNestedModule), res) }) t.Run("Basic Summary", func(t *testing.T) { StaticMarkdownConfig.setExtendedSummary(false) - res := buildInfoSummary.buildInfoModules(builds) + res, err := buildInfoSummary.buildInfoModules(builds) + assert.NoError(t, err) testMarkdownOutput(t, getTestDataFile(t, mavenNestedModule), res) }) } @@ -199,7 +208,7 @@ func TestBuildInfoModulesGradle(t *testing.T) { Name: "buildName", Number: "123", Started: "2024-05-05T12:47:20.803+0300", - BuildUrl: "http://myJFrogPlatform/builds/buildName/123", + BuildUrl: buildUrl, Modules: []buildinfo.Module{ { Id: "gradle", @@ -218,12 +227,14 @@ func TestBuildInfoModulesGradle(t *testing.T) { t.Run("Extended Summary", func(t *testing.T) { StaticMarkdownConfig.setExtendedSummary(true) - res := buildInfoSummary.buildInfoModules(builds) + res, err := buildInfoSummary.buildInfoModules(builds) + assert.NoError(t, err) assert.Empty(t, res) }) t.Run("Basic Summary", func(t *testing.T) { StaticMarkdownConfig.setExtendedSummary(false) - res := buildInfoSummary.buildInfoModules(builds) + res, err := buildInfoSummary.buildInfoModules(builds) + assert.NoError(t, err) assert.Empty(t, res) }) } @@ -238,7 +249,7 @@ func TestBuildInfoModulesGeneric(t *testing.T) { Name: "buildName", Number: "123", Started: "2024-05-05T12:47:20.803+0300", - BuildUrl: "http://myJFrogPlatform/builds/buildName/123", + BuildUrl: buildUrl, Modules: []buildinfo.Module{ { Id: "generic", @@ -255,12 +266,14 @@ func TestBuildInfoModulesGeneric(t *testing.T) { t.Run("Extended Summary", func(t *testing.T) { StaticMarkdownConfig.setExtendedSummary(true) - res := buildInfoSummary.buildInfoModules(builds) + res, err := buildInfoSummary.buildInfoModules(builds) + assert.NoError(t, err) testMarkdownOutput(t, getTestDataFile(t, genericModule), res) }) t.Run("Basic Summary", func(t *testing.T) { StaticMarkdownConfig.setExtendedSummary(false) - res := buildInfoSummary.buildInfoModules(builds) + res, err := buildInfoSummary.buildInfoModules(builds) + assert.NoError(t, err) testMarkdownOutput(t, getTestDataFile(t, genericModule), res) }) } @@ -305,12 +318,14 @@ func TestDockerModule(t *testing.T) { t.Run("Extended Summary", func(t *testing.T) { StaticMarkdownConfig.setExtendedSummary(true) - res := buildInfoSummary.buildInfoModules(builds) + res, err := buildInfoSummary.buildInfoModules(builds) + assert.NoError(t, err) testMarkdownOutput(t, getTestDataFile(t, dockerImageModule), res) }) t.Run("Basic Summary", func(t *testing.T) { StaticMarkdownConfig.setExtendedSummary(false) - res := buildInfoSummary.buildInfoModules(builds) + res, err := buildInfoSummary.buildInfoModules(builds) + assert.NoError(t, err) testMarkdownOutput(t, getTestDataFile(t, dockerImageModule), res) }) @@ -380,12 +395,14 @@ func TestDockerMultiArchModule(t *testing.T) { t.Run("Extended Summary", func(t *testing.T) { StaticMarkdownConfig.setExtendedSummary(true) - res := buildInfoSummary.buildInfoModules(builds) + res, err := buildInfoSummary.buildInfoModules(builds) + assert.NoError(t, err) testMarkdownOutput(t, getTestDataFile(t, dockerMultiArchModule), res) }) t.Run("Basic Summary", func(t *testing.T) { StaticMarkdownConfig.setExtendedSummary(false) - res := buildInfoSummary.buildInfoModules(builds) + res, err := buildInfoSummary.buildInfoModules(builds) + assert.NoError(t, err) testMarkdownOutput(t, getTestDataFile(t, dockerMultiArchModule), res) }) diff --git a/artifactory/utils/commandsummary/uploadsummary.go b/artifactory/utils/commandsummary/uploadsummary.go index cccaca2d8..542e96b48 100644 --- a/artifactory/utils/commandsummary/uploadsummary.go +++ b/artifactory/utils/commandsummary/uploadsummary.go @@ -2,6 +2,7 @@ package commandsummary import ( "fmt" + "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" ) @@ -33,8 +34,12 @@ func (us *UploadSummary) GenerateMarkdownFromFiles(dataFilePaths []string) (mark if err = us.loadResults(dataFilePaths); err != nil { return } + md, err := us.generateFileTreeMarkdown() + if err != nil { + return + } // Wrap the Markdown in a
 tags to preserve spaces
-	markdown = fmt.Sprintf("\n
\n\n\n%s
\n\n", us.generateFileTreeMarkdown()) + markdown = fmt.Sprintf("\n
\n\n\n%s
\n\n", md) return } @@ -51,21 +56,25 @@ func (us *UploadSummary) loadResults(filePaths []string) error { return nil } -func (us *UploadSummary) generateFileTreeMarkdown() string { +func (us *UploadSummary) generateFileTreeMarkdown() (string, error) { us.uploadTree = utils.NewFileTree() for _, uploadResult := range us.uploadedArtifacts.Results { - us.uploadTree.AddFile(uploadResult.TargetPath, us.buildUiUrl(uploadResult.TargetPath)) + buildUiUrl, err := us.buildUiUrl(uploadResult.TargetPath) + if err != nil { + return "", err + } + us.uploadTree.AddFile(uploadResult.TargetPath, buildUiUrl) if us.uploadTree.IsTreeExceedsMax() { - return "" + return "", nil } } - return us.uploadTree.String() + return us.uploadTree.String(), nil } -func (us *UploadSummary) buildUiUrl(targetPath string) string { +func (us *UploadSummary) buildUiUrl(targetPath string) (string, error) { // Only build URL if extended summary is enabled if StaticMarkdownConfig.IsExtendedSummary() { - return GenerateArtifactUrl(targetPath) + return GenerateArtifactUrl(targetPath, artifactsSection) } - return "" + return "", nil } diff --git a/artifactory/utils/commandsummary/utils.go b/artifactory/utils/commandsummary/utils.go index fa92f98af..f9e51b3ec 100644 --- a/artifactory/utils/commandsummary/utils.go +++ b/artifactory/utils/commandsummary/utils.go @@ -4,6 +4,10 @@ import ( "crypto/sha1" // #nosec G505 - This is only used for encoding, not security. "encoding/hex" "fmt" + "net/url" + "os" + + "github.com/jfrog/jfrog-client-go/utils/errorutils" ) const ( @@ -12,11 +16,14 @@ const ( artifactoryDockerPackagesUiFormat = "%s/ui/packages/docker:%s/sha256__%s" ) -func GenerateArtifactUrl(pathInRt string) string { +func GenerateArtifactUrl(pathInRt string, section summarySection) (url string, err error) { if StaticMarkdownConfig.GetPlatformMajorVersion() == 6 { - return fmt.Sprintf(artifactory6UiFormat, StaticMarkdownConfig.GetPlatformUrl(), pathInRt) + url = fmt.Sprintf(artifactory6UiFormat, StaticMarkdownConfig.GetPlatformUrl(), pathInRt) + } else { + url = fmt.Sprintf(artifactory7UiFormat, StaticMarkdownConfig.GetPlatformUrl(), pathInRt) } - return fmt.Sprintf(artifactory7UiFormat, StaticMarkdownConfig.GetPlatformUrl(), pathInRt) + url, err = addGitHubTrackingToUrl(url, section) + return } func WrapCollapsableMarkdown(title, markdown string, headerSize int) string { @@ -33,3 +40,37 @@ func fileNameToSha1(fileName string) string { hashBytes := hash.Sum(nil) return hex.EncodeToString(hashBytes) } + +type summarySection string + +const ( + artifactsSection summarySection = "artifacts" + packagesSection summarySection = "packages" + buildInfoSection summarySection = "buildInfo" +) + +// addGitHubTrackingToUrl adds GitHub-related query parameters to a given URL if the GITHUB_WORKFLOW environment variable is set. +func addGitHubTrackingToUrl(urlStr string, section summarySection) (string, error) { + // Check if GITHUB_WORKFLOW environment variable is set + githubWorkflow := os.Getenv("GITHUB_WORKFLOW") + if githubWorkflow == "" { + // Return the original URL if the variable is not set + return urlStr, nil + } + + // Parse the input URL + parsedUrl, err := url.Parse(urlStr) + if errorutils.CheckError(err) != nil { + // Return an error if the URL is invalid + return "", err + } + + // Get the query parameters and add the GitHub tracking parameters + queryParams := parsedUrl.Query() + queryParams.Set("gh_job_id", githubWorkflow) + queryParams.Set("gh_section", string(section)) + parsedUrl.RawQuery = queryParams.Encode() + + // Return the modified URL + return parsedUrl.String(), nil +} diff --git a/artifactory/utils/commandsummary/utils_test.go b/artifactory/utils/commandsummary/utils_test.go index 364239afc..5473df4d0 100644 --- a/artifactory/utils/commandsummary/utils_test.go +++ b/artifactory/utils/commandsummary/utils_test.go @@ -1,8 +1,10 @@ package commandsummary import ( - "github.com/stretchr/testify/assert" "testing" + + testsutils "github.com/jfrog/jfrog-client-go/utils/tests" + "github.com/stretchr/testify/assert" ) const ( @@ -17,15 +19,16 @@ func TestGenerateArtifactUrl(t *testing.T) { majorVersion int expected string }{ - {"artifactory 7 without project", "", 7, "https://myplatform.com/ui/repos/tree/General/repo/path/file?clearFilter=true"}, - {"artifactory 7 with project", "proj", 7, "https://myplatform.com/ui/repos/tree/General/repo/path/file?clearFilter=true"}, - {"artifactory 6 without project", "", 6, "https://myplatform.com/artifactory/webapp/#/artifacts/browse/tree/General/repo/path/file"}, + {"artifactory 7 without project", "", 7, "https://myplatform.com/ui/repos/tree/General/repo/path/file?clearFilter=true&gh_job_id=JFrog+CLI+Core+Tests&gh_section=test-section"}, + {"artifactory 7 with project", "proj", 7, "https://myplatform.com/ui/repos/tree/General/repo/path/file?clearFilter=true&gh_job_id=JFrog+CLI+Core+Tests&gh_section=test-section"}, + {"artifactory 6 without project", "", 6, "https://myplatform.com/artifactory/webapp/?gh_job_id=JFrog+CLI+Core+Tests&gh_section=test-section#/artifacts/browse/tree/General/repo/path/file"}, } StaticMarkdownConfig.setPlatformUrl(testPlatformUrl) for _, testCase := range cases { t.Run(testCase.testName, func(t *testing.T) { StaticMarkdownConfig.setPlatformMajorVersion(testCase.majorVersion) - artifactUrl := GenerateArtifactUrl(fullPath) + artifactUrl, err := GenerateArtifactUrl(fullPath, "test-section") + assert.NoError(t, err) assert.Equal(t, testCase.expected, artifactUrl) }) } @@ -45,3 +48,74 @@ func TestFileNameToSha1(t *testing.T) { assert.Equal(t, test.expected, hash) } } + +func TestAddGitHubTrackingToUrl(t *testing.T) { + tests := []struct { + name string + url string + section summarySection + envValue string + expectedResult string + expectsError bool + }{ + { + "No GITHUB_WORKFLOW set", + "https://example.com/path", + buildInfoSection, + "", + "https://example.com/path", + false, + }, + { + "GITHUB_WORKFLOW set", + "https://example.com/path", + buildInfoSection, + "workflow123", + "https://example.com/path?gh_job_id=workflow123&gh_section=buildInfo", + false, + }, + { + "Invalid URL", + ":invalid-url", + buildInfoSection, + "workflow123", + "", + true, + }, + { + "URL with existing query parameters", + "https://example.com/path?existing_param=value", + packagesSection, + "workflow123", + "https://example.com/path?existing_param=value&gh_job_id=workflow123&gh_section=packages", + false, + }, + { + "GITHUB_WORKFLOW with special characters", + "https://example.com/path", + artifactsSection, + "workflow with spaces & special?characters", + "https://example.com/path?gh_job_id=workflow+with+spaces+%26+special%3Fcharacters&gh_section=artifacts", + false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + // Set up the environment variable + + cleanup := testsutils.SetEnvWithCallbackAndAssert(t, "GITHUB_WORKFLOW", test.envValue) + defer cleanup() + + // Call the function + result, err := addGitHubTrackingToUrl(test.url, test.section) + + if test.expectsError { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, test.expectedResult, result) + } + }) + } +} diff --git a/artifactory/utils/testdata/command_summaries/extended/build-info-table.md b/artifactory/utils/testdata/command_summaries/extended/build-info-table.md index c8b411b49..5d0bb212c 100644 --- a/artifactory/utils/testdata/command_summaries/extended/build-info-table.md +++ b/artifactory/utils/testdata/command_summaries/extended/build-info-table.md @@ -2,6 +2,6 @@ | Build Info| Security Violations| Security Issues| |:---------|:------------|:------------| -| [buildName 123](http://myJFrogPlatform/builds/buildName/123) | Not scanned| Not scanned| +| [buildName 123](http://myJFrogPlatform/builds/buildName/123?gh_job_id=JFrog+CLI+Core+Tests&gh_section=buildInfo) | Not scanned| Not scanned| diff --git a/artifactory/utils/testdata/command_summaries/extended/docker-image-module.md b/artifactory/utils/testdata/command_summaries/extended/docker-image-module.md index 1227569a1..2300c23c0 100644 --- a/artifactory/utils/testdata/command_summaries/extended/docker-image-module.md +++ b/artifactory/utils/testdata/command_summaries/extended/docker-image-module.md @@ -10,4 +10,4 @@ | Artifacts | Security Violations | Security Issues | | :------------ | :--------------------- | :------------------ | -|
📦 docker-local
└── 📁 image2
└── 📁 sha256:552c
└── sha256__aae9

| Not scanned | Not scanned | +|
📦 docker-local
└── 📁 image2
└── 📁 sha256:552c
└── sha256__aae9

| Not scanned | Not scanned | diff --git a/artifactory/utils/testdata/command_summaries/extended/generic-module.md b/artifactory/utils/testdata/command_summaries/extended/generic-module.md index af0bee52e..33e1fe0f1 100644 --- a/artifactory/utils/testdata/command_summaries/extended/generic-module.md +++ b/artifactory/utils/testdata/command_summaries/extended/generic-module.md @@ -11,7 +11,7 @@
📦 generic-local
 └── 📁 path
     └── 📁 to
-        └── artifact2
+        └── artifact2
 
 
diff --git a/artifactory/utils/testdata/command_summaries/extended/maven-module.md b/artifactory/utils/testdata/command_summaries/extended/maven-module.md index 738da70cb..c1454b39c 100644 --- a/artifactory/utils/testdata/command_summaries/extended/maven-module.md +++ b/artifactory/utils/testdata/command_summaries/extended/maven-module.md @@ -11,7 +11,7 @@
📦 libs-release
 └── 📁 path
     └── 📁 to
-        └── artifact1
+        └── artifact1
 
 
diff --git a/artifactory/utils/testdata/command_summaries/extended/maven-nested-module.md b/artifactory/utils/testdata/command_summaries/extended/maven-nested-module.md index 59a105406..5e6d5b90c 100644 --- a/artifactory/utils/testdata/command_summaries/extended/maven-nested-module.md +++ b/artifactory/utils/testdata/command_summaries/extended/maven-nested-module.md @@ -12,7 +12,7 @@ 📦 libs-release └── 📁 path └── 📁 to - └── artifact2 + └── artifact2
@@ -22,7 +22,7 @@ 📦 libs-release └── 📁 path └── 📁 to - └── artifact3 + └── artifact3 diff --git a/artifactory/utils/testdata/command_summaries/extended/multiarch-docker-image.md b/artifactory/utils/testdata/command_summaries/extended/multiarch-docker-image.md index c460a99b2..5dfc53802 100644 --- a/artifactory/utils/testdata/command_summaries/extended/multiarch-docker-image.md +++ b/artifactory/utils/testdata/command_summaries/extended/multiarch-docker-image.md @@ -10,4 +10,4 @@ | Artifacts | Security Violations | Security Issues | | :------------ | :--------------------- | :------------------ | -|
linux/amd64/multiarch-image:1 (🐸 View)
📦 docker-local
└── 📁 multiarch-image
├── 📁 sha256:552c
│ └── sha256
└── sha256

| Not scanned | Not scanned | +|
linux/amd64/multiarch-image:1 (🐸 View)
📦 docker-local
└── 📁 multiarch-image
├── 📁 sha256:552c
│ └── sha256
└── sha256

| Not scanned | Not scanned | diff --git a/artifactory/utils/utils.go b/artifactory/utils/utils.go index 68831475e..0ebe42265 100644 --- a/artifactory/utils/utils.go +++ b/artifactory/utils/utils.go @@ -262,7 +262,7 @@ func CreateMetadataServiceManager(serviceDetails *config.ServerDetails, isDryRun return metadata.NewManager(serviceConfig) } -func CreateJfConnectServiceManager(serverDetails *config.ServerDetails) (jfconnect.Manager, error) { +func CreateJfConnectServiceManager(serverDetails *config.ServerDetails, httpRetries, httpRetryWaitMilliSecs int) (jfconnect.Manager, error) { certsPath, err := coreutils.GetJfrogCertsDir() if err != nil { return nil, err @@ -275,6 +275,8 @@ func CreateJfConnectServiceManager(serverDetails *config.ServerDetails) (jfconne SetServiceDetails(jfConnectAuth). SetCertificatesPath(certsPath). SetInsecureTls(serverDetails.InsecureTls). + SetHttpRetries(httpRetries). + SetHttpRetryWaitMilliSecs(httpRetryWaitMilliSecs). Build() if err != nil { return nil, err diff --git a/common/commands/command.go b/common/commands/command.go index 52bd83cf6..f103dfda7 100644 --- a/common/commands/command.go +++ b/common/commands/command.go @@ -3,15 +3,22 @@ package commands import ( "sync" + "github.com/jfrog/gofrog/version" "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" coreusage "github.com/jfrog/jfrog-cli-core/v2/utils/usage" usageReporter "github.com/jfrog/jfrog-cli-core/v2/utils/usage" + rtClient "github.com/jfrog/jfrog-client-go/artifactory" "github.com/jfrog/jfrog-client-go/artifactory/usage" "github.com/jfrog/jfrog-client-go/utils/log" ) +const ( + minCallHomeArtifactoryVersion = "6.9.0" + minVisibilitySystemArtifactoryVersion = "7.102" +) + type Command interface { // Runs the command Run() error @@ -43,32 +50,45 @@ func reportUsage(command Command, channel chan<- bool) { serverDetails, err := command.ServerDetails() if err != nil { - log.Debug("Usage reporting:", err.Error()) + log.Debug("Usage reporting. Failed accessing ServerDetails.", err.Error()) + return + } + if serverDetails == nil || serverDetails.ArtifactoryUrl == "" { + return + } + serviceManager, err := utils.CreateServiceManager(serverDetails, -1, 0, false) + if err != nil { + log.Debug("Usage reporting. Failed creating the Artifactory Service Manager.", err.Error()) + return + } + artifactoryVersion, err := serviceManager.GetVersion() + if err != nil { + log.Debug("Usage reporting. Failed getting the version of Artifactory", err.Error()) return } - if serverDetails != nil { - var wg sync.WaitGroup + var wg sync.WaitGroup - // Report the usage to Artifactory's Call Home API. - if serverDetails.ArtifactoryUrl != "" { - wg.Add(1) - go func() { - defer wg.Done() - reportUsageToArtifactoryCallHome(command, serverDetails) - }() - } + // Report the usage to Artifactory's Call Home API. + if version.NewVersion(artifactoryVersion).AtLeast(minCallHomeArtifactoryVersion) { + wg.Add(1) + go func() { + defer wg.Done() + reportUsageToArtifactoryCallHome(command, serviceManager) + }() + } - // Report the usage to the Visibility System. + // Report the usage to the Visibility System. + if version.NewVersion(artifactoryVersion).AtLeast(minVisibilitySystemArtifactoryVersion) { wg.Add(1) go func() { defer wg.Done() reportUsageToVisibilitySystem(command, serverDetails) }() - - // Wait for the two report actions to finish. - wg.Wait() } + + // Wait for the two report actions to finish. + wg.Wait() } func reportUsageToVisibilitySystem(command Command, serverDetails *config.ServerDetails) { @@ -77,14 +97,9 @@ func reportUsageToVisibilitySystem(command Command, serverDetails *config.Server } } -func reportUsageToArtifactoryCallHome(command Command, serverDetails *config.ServerDetails) { +func reportUsageToArtifactoryCallHome(command Command, serviceManager rtClient.ArtifactoryServicesManager) { log.Debug(usageReporter.ArtifactoryCallHomePrefix, "Sending info...") - serviceManager, err := utils.CreateServiceManager(serverDetails, -1, 0, false) - if err != nil { - log.Debug(usageReporter.ArtifactoryCallHomePrefix, err.Error()) - return - } - if err = usage.NewArtifactoryCallHome().SendUsage(coreutils.GetCliUserAgent(), command.CommandName(), serviceManager); err != nil { + if err := usage.NewArtifactoryCallHome().Send(coreutils.GetCliUserAgent(), command.CommandName(), serviceManager); err != nil { log.Debug(err.Error()) } } diff --git a/go.mod b/go.mod index ca3eae9a2..e36659a68 100644 --- a/go.mod +++ b/go.mod @@ -11,11 +11,11 @@ require ( github.com/gocarina/gocsv v0.0.0-20240520201108-78e41c74b4b1 github.com/google/uuid v1.6.0 github.com/gookit/color v1.5.4 - github.com/jedib0t/go-pretty/v6 v6.6.3 + github.com/jedib0t/go-pretty/v6 v6.6.5 github.com/jfrog/build-info-go v1.10.7 github.com/jfrog/gofrog v1.7.6 - github.com/jfrog/jfrog-client-go v1.48.5 - github.com/magiconair/properties v1.8.7 + github.com/jfrog/jfrog-client-go v1.48.6 + github.com/magiconair/properties v1.8.9 github.com/manifoldco/promptui v0.9.0 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c github.com/spf13/viper v1.19.0 @@ -89,14 +89,14 @@ require ( go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect golang.org/x/crypto v0.31.0 // indirect - golang.org/x/net v0.31.0 // indirect + golang.org/x/net v0.33.0 // indirect golang.org/x/sys v0.28.0 // indirect golang.org/x/tools v0.27.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) -// replace github.com/jfrog/jfrog-client-go => github.com/eyalbe4/jfrog-client-go v1.28.1-0.20241222155750-04d75d451f23 +// replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20241225183733-80a5e1ba7a2c // replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20241121100855-e7a75ceee2bd diff --git a/go.sum b/go.sum index 302de5215..c1956415a 100644 --- a/go.sum +++ b/go.sum @@ -85,16 +85,16 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jedib0t/go-pretty/v6 v6.6.3 h1:nGqgS0tgIO1Hto47HSaaK4ac/I/Bu7usmdD3qvs0WvM= -github.com/jedib0t/go-pretty/v6 v6.6.3/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= +github.com/jedib0t/go-pretty/v6 v6.6.5 h1:9PgMJOVBedpgYLI56jQRJYqngxYAAzfEUua+3NgSqAo= +github.com/jedib0t/go-pretty/v6 v6.6.5/go.mod h1:Uq/HrbhuFty5WSVNfjpQQe47x16RwVGXIveNGEyGtHs= github.com/jfrog/archiver/v3 v3.6.1 h1:LOxnkw9pOn45DzCbZNFV6K0+6dCsQ0L8mR3ZcujO5eI= github.com/jfrog/archiver/v3 v3.6.1/go.mod h1:VgR+3WZS4N+i9FaDwLZbq+jeU4B4zctXL+gL4EMzfLw= github.com/jfrog/build-info-go v1.10.7 h1:10NVHYg0193gJpQft+S4WQfvYMtj5jlwwhJRvkFJtBE= github.com/jfrog/build-info-go v1.10.7/go.mod h1:JcISnovFXKx3wWf3p1fcMmlPdt6adxScXvoJN4WXqIE= 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-client-go v1.48.5 h1:q8v8oZ2HwwVw6+ZCwKbuIpUmxpWUeZzvTASQl/QKxKw= -github.com/jfrog/jfrog-client-go v1.48.5/go.mod h1:2ySOMva54L3EYYIlCBYBTcTgqfrrQ19gtpA/MWfA/ec= +github.com/jfrog/jfrog-client-go v1.48.6 h1:Pl9foa9XBaPbP3gz4wevDmF/mpfit94IQHKQKnfk3lA= +github.com/jfrog/jfrog-client-go v1.48.6/go.mod h1:2ySOMva54L3EYYIlCBYBTcTgqfrrQ19gtpA/MWfA/ec= github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= @@ -112,8 +112,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= -github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM= +github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -229,8 +229,8 @@ golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1 golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.31.0 h1:68CPQngjLL0r2AlUKiSxtQFKvzRVbnzLwMUn5SzcLHo= -golang.org/x/net v0.31.0/go.mod h1:P4fl1q7dY2hnZFxEk4pPSkDHF+QqjitcnDjUQyMM+pM= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= diff --git a/utils/usage/usage.go b/utils/usage/usage.go index b73cfd2b4..6834b63d3 100644 --- a/utils/usage/usage.go +++ b/utils/usage/usage.go @@ -169,7 +169,7 @@ func (ur *UsageReporter) reportToArtifactory(features ...ReportFeature) (err err if err != nil { return } - return usage.NewArtifactoryCallHome().SendUsageToArtifactory(ur.ProductId, serviceManager, converted...) + return usage.NewArtifactoryCallHome().SendToArtifactory(ur.ProductId, serviceManager, converted...) } func convertAttributesToMap(reportFeature ReportFeature) (converted map[string]string) { diff --git a/utils/usage/visibility_system_manager.go b/utils/usage/visibility_system_manager.go index e9053bf01..d8baf29b1 100644 --- a/utils/usage/visibility_system_manager.go +++ b/utils/usage/visibility_system_manager.go @@ -22,6 +22,7 @@ func NewVisibilitySystemManager(serverDetails *config.ServerDetails) *Visibility func (vsm *VisibilitySystemManager) createMetric(commandName string) services.VisibilityMetric { metricLabels := services.Labels{ ProductID: coreutils.GetCliUserAgentName(), + ProductVersion: coreutils.GetCliUserAgentVersion(), FeatureID: commandName, OIDCUsed: os.Getenv("JFROG_CLI_USAGE_OIDC_USED"), JobID: os.Getenv("JFROG_CLI_USAGE_JOB_ID"), @@ -38,7 +39,7 @@ func (vsm *VisibilitySystemManager) createMetric(commandName string) services.Vi } func (vsm *VisibilitySystemManager) SendUsage(commandName string) error { - manager, err := utils.CreateJfConnectServiceManager(vsm.serverDetails) + manager, err := utils.CreateJfConnectServiceManager(vsm.serverDetails, -1, 0) if err != nil { return err } diff --git a/utils/usage/visibility_system_manager_test.go b/utils/usage/visibility_system_manager_test.go index bc27f4433..edcbbb62e 100644 --- a/utils/usage/visibility_system_manager_test.go +++ b/utils/usage/visibility_system_manager_test.go @@ -12,11 +12,11 @@ import ( func TestCreateMetric(t *testing.T) { // Set environment variables for the test using SetEnvWithCallbackAndAssert envVars := map[string]string{ - "JFROG_CLI_USAGE_OIDC_USED": "true", + "JFROG_CLI_USAGE_OIDC_USED": "TRUE", "JFROG_CLI_USAGE_JOB_ID": "job123", "JFROG_CLI_USAGE_RUN_ID": "run456", "JFROG_CLI_USAGE_GIT_REPO": "test-repo", - "JFROG_CLI_USAGE_GH_TOKEN_FOR_CODE_SCANNING_ALERTS_PROVIDED": "true", + "JFROG_CLI_USAGE_GH_TOKEN_FOR_CODE_SCANNING_ALERTS_PROVIDED": "TRUE", } cleanupFuncs := []func(){} for key, value := range envVars { @@ -40,12 +40,13 @@ func TestCreateMetric(t *testing.T) { "metrics_name": "jfcli_commands_count", "labels": { "product_id": "` + coreutils.GetCliUserAgentName() + `", + "product_version": "` + coreutils.GetCliUserAgentVersion() + `", "feature_id": "testCommand", - "oidc_used": "true", + "oidc_used": "TRUE", "job_id": "job123", "run_id": "run456", "git_repo": "test-repo", - "gh_token_for_code_scanning_alerts_provided": "true" + "gh_token_for_code_scanning_alerts_provided": "TRUE" } }`