From be7e7b4543dff264639507fc14a4e6d087f33412 Mon Sep 17 00:00:00 2001 From: Omer Zidkoni <50792403+omerzi@users.noreply.github.com> Date: Sun, 18 Aug 2024 10:28:19 +0300 Subject: [PATCH 1/4] Job Summary - Group Build-Info Related Modules into the Same Section (#1229) --- .../commandssummaries/buildinfosummary.go | 95 ++++++++--- .../buildinfosummary_test.go | 149 ++++++++++++++++-- .../commandssummaries/testdata/generic.md | 7 + .../commandssummaries/testdata/image2.md | 7 + .../commandssummaries/testdata/maven.md | 7 + .../commandssummaries/testdata/modules.md | 23 --- .../testdata/multiarch-image1.md | 21 +++ artifactory/utils/container/buildinfo.go | 1 + 8 files changed, 249 insertions(+), 61 deletions(-) create mode 100644 artifactory/commands/commandssummaries/testdata/generic.md create mode 100644 artifactory/commands/commandssummaries/testdata/image2.md create mode 100644 artifactory/commands/commandssummaries/testdata/maven.md delete mode 100644 artifactory/commands/commandssummaries/testdata/modules.md create mode 100644 artifactory/commands/commandssummaries/testdata/multiarch-image1.md diff --git a/artifactory/commands/commandssummaries/buildinfosummary.go b/artifactory/commands/commandssummaries/buildinfosummary.go index a870bae04..164e6de84 100644 --- a/artifactory/commands/commandssummaries/buildinfosummary.go +++ b/artifactory/commands/commandssummaries/buildinfosummary.go @@ -59,22 +59,12 @@ func (bis *BuildInfoSummary) buildInfoTable(builds []*buildInfo.BuildInfo) strin func (bis *BuildInfoSummary) buildInfoModules(builds []*buildInfo.BuildInfo) string { var markdownBuilder strings.Builder - markdownBuilder.WriteString("\n\n ### Modules Published As Part of This Build \n\n") + markdownBuilder.WriteString("\n### Modules Published As Part of This Build\n") var shouldGenerate bool for _, build := range builds { - for _, module := range build.Modules { - if len(module.Artifacts) == 0 { - continue - } - - switch module.Type { - case buildInfo.Docker, buildInfo.Maven, buildInfo.Npm, buildInfo.Go, buildInfo.Generic, buildInfo.Terraform: - markdownBuilder.WriteString(bis.generateModuleMarkdown(module)) - shouldGenerate = true - default: - // Skip unsupported module types. - continue - } + if modulesMarkdown := bis.generateModulesMarkdown(build.Modules...); modulesMarkdown != "" { + markdownBuilder.WriteString(modulesMarkdown) + shouldGenerate = true } } @@ -85,19 +75,36 @@ func (bis *BuildInfoSummary) buildInfoModules(builds []*buildInfo.BuildInfo) str return markdownBuilder.String() } -func parseBuildTime(timestamp string) string { - // Parse the timestamp string into a time.Time object - buildInfoTime, err := time.Parse(buildInfo.TimeFormat, timestamp) - if err != nil { - return "N/A" +func (bis *BuildInfoSummary) generateModulesMarkdown(modules ...buildInfo.Module) string { + var modulesMarkdown strings.Builder + parentToModulesMap := groupModulesByParent(modules) + if len(parentToModulesMap) == 0 { + return "" } - // Format the time in a more human-readable format and save it in a variable - return buildInfoTime.Format(timeFormat) + + for parentModuleID, parentModules := range parentToModulesMap { + modulesMarkdown.WriteString(fmt.Sprintf("#### %s\n
", parentModuleID))
+		isMultiModule := len(parentModules) > 1
+
+		for _, module := range parentModules {
+			if isMultiModule && parentModuleID == module.Id {
+				// Skip the parent module if there are multiple modules, as it will be displayed as a header
+				continue
+			}
+			artifactsTree := bis.createArtifactsTree(module)
+			if isMultiModule {
+				// Collapse the module tree if there are multiple modules
+				modulesMarkdown.WriteString(fmt.Sprintf("
%s\n%s
", module.Id, artifactsTree)) + } else { + modulesMarkdown.WriteString(artifactsTree) + } + } + modulesMarkdown.WriteString("
\n") + } + return modulesMarkdown.String() } -func (bis *BuildInfoSummary) generateModuleMarkdown(module buildInfo.Module) string { - var moduleMarkdown strings.Builder - moduleMarkdown.WriteString(fmt.Sprintf("\n #### %s \n", module.Id)) +func (bis *BuildInfoSummary) createArtifactsTree(module buildInfo.Module) string { artifactsTree := utils.NewFileTree() for _, artifact := range module.Artifacts { artifactUrlInArtifactory := bis.generateArtifactUrl(artifact) @@ -108,8 +115,7 @@ func (bis *BuildInfoSummary) generateModuleMarkdown(module buildInfo.Module) str artifactTreePath := path.Join(artifact.OriginalDeploymentRepo, artifact.Path) artifactsTree.AddFile(artifactTreePath, artifactUrlInArtifactory) } - moduleMarkdown.WriteString("\n\n
" + artifactsTree.String() + "
") - return moduleMarkdown.String() + return artifactsTree.String() } func (bis *BuildInfoSummary) generateArtifactUrl(artifact buildInfo.Artifact) string { @@ -118,3 +124,40 @@ func (bis *BuildInfoSummary) generateArtifactUrl(artifact buildInfo.Artifact) st } return generateArtifactUrl(bis.platformUrl, path.Join(artifact.OriginalDeploymentRepo, artifact.Path), bis.majorVersion) } + +// groupModulesByParent groups modules that share the same parent ID into a map where the key is the parent ID and the value is a slice of those modules. +func groupModulesByParent(modules []buildInfo.Module) map[string][]buildInfo.Module { + parentToModulesMap := make(map[string][]buildInfo.Module, len(modules)) + for _, module := range modules { + if len(module.Artifacts) == 0 || !isSupportedModuleType(module.Type) { + continue + } + + parentID := module.Parent + // If the module has no parent, that means it is the parent module itself, so we can use its ID as the parent ID. + if parentID == "" { + parentID = module.Id + } + parentToModulesMap[parentID] = append(parentToModulesMap[parentID], module) + } + return parentToModulesMap +} + +func isSupportedModuleType(moduleType buildInfo.ModuleType) bool { + switch moduleType { + case buildInfo.Docker, buildInfo.Maven, buildInfo.Npm, buildInfo.Go, buildInfo.Generic, buildInfo.Terraform: + return true + default: + return false + } +} + +func parseBuildTime(timestamp string) string { + // Parse the timestamp string into a time.Time object + buildInfoTime, err := time.Parse(buildInfo.TimeFormat, timestamp) + if err != nil { + return "N/A" + } + // Format the time in a more human-readable format and save it in a variable + return buildInfoTime.Format(timeFormat) +} diff --git a/artifactory/commands/commandssummaries/buildinfosummary_test.go b/artifactory/commands/commandssummaries/buildinfosummary_test.go index 73a613861..5ab5cce21 100644 --- a/artifactory/commands/commandssummaries/buildinfosummary_test.go +++ b/artifactory/commands/commandssummaries/buildinfosummary_test.go @@ -33,6 +33,19 @@ func TestBuildInfoModules(t *testing.T) { BuildUrl: "http://myJFrogPlatform/builds/buildName/123", Modules: []buildinfo.Module{ { + Id: "gradle", + // Validate that ignored types don't show. + Type: buildinfo.Gradle, + Artifacts: []buildinfo.Artifact{ + { + Name: "gradleArtifact", + Path: "dir/gradleArtifact", + OriginalDeploymentRepo: "gradle-local", + }, + }, + }, + { + Id: "maven", Type: buildinfo.Maven, Artifacts: []buildinfo.Artifact{{ Name: "artifact1", @@ -46,6 +59,7 @@ func TestBuildInfoModules(t *testing.T) { }, }, { + Id: "generic", Type: buildinfo.Generic, Artifacts: []buildinfo.Artifact{{ Name: "artifact2", @@ -53,22 +67,16 @@ func TestBuildInfoModules(t *testing.T) { OriginalDeploymentRepo: "generic-local", }}, }, - { - // Validate that ignored types don't show. - Type: buildinfo.Gradle, - Artifacts: []buildinfo.Artifact{ - { - Name: "gradleArtifact", - Path: "dir/gradleArtifact", - OriginalDeploymentRepo: "gradle-local", - }, - }, - }, }, }, } - assert.Equal(t, getTestDataFile(t, "modules.md"), gh.buildInfoModules(builds)) + result := gh.buildInfoModules(builds) + // Validate that the markdown contains the expected "generic" repo content as well as the "maven" repo content. + assert.Contains(t, result, getTestDataFile(t, "generic.md")) + assert.Contains(t, result, getTestDataFile(t, "maven.md")) + // The build-info also contains a "gradle" module, but it should not be included in the markdown. + assert.NotContains(t, result, "gradle") } // Validate that if no supported module with artifacts was found, we avoid generating the markdown. @@ -82,6 +90,7 @@ func TestBuildInfoModulesEmpty(t *testing.T) { BuildUrl: "http://myJFrogPlatform/builds/buildName/123", Modules: []buildinfo.Module{ { + Id: "maven", Type: buildinfo.Maven, Artifacts: []buildinfo.Artifact{}, Dependencies: []buildinfo.Dependency{{ @@ -90,6 +99,7 @@ func TestBuildInfoModulesEmpty(t *testing.T) { }, }, { + Id: "gradle", Type: buildinfo.Gradle, Artifacts: []buildinfo.Artifact{ { @@ -106,6 +116,121 @@ func TestBuildInfoModulesEmpty(t *testing.T) { assert.Empty(t, gh.buildInfoModules(builds)) } +func TestBuildInfoModulesWithGrouping(t *testing.T) { + gh := &BuildInfoSummary{platformUrl: platformUrl, majorVersion: 7} + var builds = []*buildinfo.BuildInfo{ + { + Name: "dockerx", + Number: "1", + Started: "2024-08-12T11:11:50.198+0300", + Modules: []buildinfo.Module{ + { + Properties: map[string]string{ + "docker.image.tag": "ecosysjfrog.jfrog.io/docker-local/multiarch-image:1", + }, + Type: "docker", + Id: "multiarch-image:1", + Artifacts: []buildinfo.Artifact{ + { + Type: "json", + Checksum: buildinfo.Checksum{ + Sha1: "faf9824aca9d192e16c2f8a6670b149392465ce7", + Sha256: "2217c766cddcd2d24994caaf7713db556a0fa8de108a946ebe5b0369f784a59a", + Md5: "ba0519ebb6feef0edefa03a7afb05406", + }, + Name: "list.manifest.json", + Path: "multiarch-image/1/list.manifest.json", + OriginalDeploymentRepo: "docker-local", + }, + }, + }, + { + Type: "docker", + Parent: "multiarch-image:1", + Id: "linux/amd64/multiarch-image:1", + Artifacts: []buildinfo.Artifact{ + { + Checksum: buildinfo.Checksum{ + Sha1: "32c1416f8430fbbabd82cb014c5e09c5fe702404", + Sha256: "aee9d258e62f0666e3286acca21be37d2e39f69f8dde74454b9f3cd8ef437e4e", + Md5: "f568bfb1c9576a1f06235ebe0389d2d8", + }, + Name: "sha256__aee9d258e62f0666e3286acca21be37d2e39f69f8dde74454b9f3cd8ef437e4e", + Path: "multiarch-image/sha256:552ccb2628970ef526f13151a0269258589fc8b5701519a9c255c4dd224b9a21/sha256__aee9d258e62f0666e3286acca21be37d2e39f69f8dde74454b9f3cd8ef437e4e", + OriginalDeploymentRepo: "docker-local", + }, + }, + }, + { + Type: "docker", + Parent: "multiarch-image:1", + Id: "linux/arm64/multiarch-image:1", + Artifacts: []buildinfo.Artifact{ + { + Checksum: buildinfo.Checksum{ + Sha1: "82b6d4ae1f673c609469a0a84170390ecdff5a38", + Sha256: "1f17f9d95f85ba55773db30ac8e6fae894831be87f5c28f2b58d17f04ef65e93", + Md5: "d178dd8c1e1fded51ade114136ebdaf2", + }, + Name: "sha256__1f17f9d95f85ba55773db30ac8e6fae894831be87f5c28f2b58d17f04ef65e93", + Path: "multiarch-image/sha256:bee6dc0408dfd20c01e12e644d8bc1d60ff100a8c180d6c7e85d374c13ae4f92/sha256__1f17f9d95f85ba55773db30ac8e6fae894831be87f5c28f2b58d17f04ef65e93", + OriginalDeploymentRepo: "docker-local", + }, + }, + }, + { + Type: "docker", + Parent: "multiarch-image:1", + Id: "linux/arm/multiarch-image:1", + Artifacts: []buildinfo.Artifact{ + { + Checksum: buildinfo.Checksum{ + Sha1: "63d3ac90f9cd322b76543d7bf96eeb92417faf41", + Sha256: "33b5b5485e88e63d3630e5dcb008f98f102b0f980a9daa31bd976efdec7a8e4c", + Md5: "99bbb1e1035aea4d9150e4348f24e107", + }, + Name: "sha256__33b5b5485e88e63d3630e5dcb008f98f102b0f980a9daa31bd976efdec7a8e4c", + Path: "multiarch-image/sha256:686085b9972e0f7a432b934574e3dca27b4fa0a3d10d0ae7099010160db6d338/sha256__33b5b5485e88e63d3630e5dcb008f98f102b0f980a9daa31bd976efdec7a8e4c", + OriginalDeploymentRepo: "docker-local", + }, + { + Checksum: buildinfo.Checksum{ + Sha1: "9dceac352f990a3149ff97ab605c3c8833409abf", + Sha256: "5480d2ca1740c20ce17652e01ed2265cdc914458acd41256a2b1ccff28f2762c", + Md5: "d6a694604c7e58b2c788dec5656a1add", + }, + Name: "sha256__5480d2ca1740c20ce17652e01ed2265cdc914458acd41256a2b1ccff28f2762c", + Path: "multiarch-image/sha256:686085b9972e0f7a432b934574e3dca27b4fa0a3d10d0ae7099010160db6d338/sha256__5480d2ca1740c20ce17652e01ed2265cdc914458acd41256a2b1ccff28f2762c", + OriginalDeploymentRepo: "docker-local", + }, + }, + }, + { + Type: "docker", + Parent: "image:2", + Id: "image:2", + Artifacts: []buildinfo.Artifact{ + { + Checksum: buildinfo.Checksum{ + Sha1: "32c1416f8430fbbabd82cb014c5e09c5fe702404", + Sha256: "aee9d258e62f0666e3286acca21be37d2e39f69f8dde74454b9f3cd8ef437e4e", + Md5: "f568bfb1c9576a1f06235ebe0389d2d8", + }, + Name: "sha256__aee9d258e62f0666e3286acca21be37d2e39f69f8dde74454b9f3cd8ef437e4e", + Path: "image2/sha256:552ccb2628970ef526f13151a0269258589fc8b5701519a9c255c4dd224b9a21/sha256__aee9d258e62f0666e3286acca21be37d2e39f69f8dde74454b9f3cd8ef437e4e", + OriginalDeploymentRepo: "docker-local", + }, + }, + }, + }, + }, + } + + result := gh.buildInfoModules(builds) + assert.Contains(t, result, getTestDataFile(t, "image2.md")) + assert.Contains(t, result, getTestDataFile(t, "multiarch-image1.md")) +} + func getTestDataFile(t *testing.T, fileName string) string { modulesPath := filepath.Join(".", "testdata", fileName) content, err := os.ReadFile(modulesPath) diff --git a/artifactory/commands/commandssummaries/testdata/generic.md b/artifactory/commands/commandssummaries/testdata/generic.md new file mode 100644 index 000000000..a283f7d34 --- /dev/null +++ b/artifactory/commands/commandssummaries/testdata/generic.md @@ -0,0 +1,7 @@ +#### generic +
📦 generic-local
+└── 📁 path
+    └── 📁 to
+        └── artifact2
+
+
\ No newline at end of file diff --git a/artifactory/commands/commandssummaries/testdata/image2.md b/artifactory/commands/commandssummaries/testdata/image2.md new file mode 100644 index 000000000..1fa49bbde --- /dev/null +++ b/artifactory/commands/commandssummaries/testdata/image2.md @@ -0,0 +1,7 @@ +#### image:2 +
📦 docker-local
+└── 📁 image2
+    └── 📁 sha256:552ccb2628970ef526f13151a0269258589fc8b5701519a9c255c4dd224b9a21
+        └── sha256__aee9d258e62f0666e3286acca21be37d2e39f69f8dde74454b9f3cd8ef437e4e
+
+
\ No newline at end of file diff --git a/artifactory/commands/commandssummaries/testdata/maven.md b/artifactory/commands/commandssummaries/testdata/maven.md new file mode 100644 index 000000000..eff437816 --- /dev/null +++ b/artifactory/commands/commandssummaries/testdata/maven.md @@ -0,0 +1,7 @@ +#### maven +
📦 libs-release
+└── 📁 path
+    └── 📁 to
+        └── artifact1
+
+
\ No newline at end of file diff --git a/artifactory/commands/commandssummaries/testdata/modules.md b/artifactory/commands/commandssummaries/testdata/modules.md deleted file mode 100644 index b87fb4653..000000000 --- a/artifactory/commands/commandssummaries/testdata/modules.md +++ /dev/null @@ -1,23 +0,0 @@ - - - ### Modules Published As Part of This Build - - - #### - - -
📦 libs-release
-└── 📁 path
-    └── 📁 to
-        └── artifact1
-
-
- #### - - -
📦 generic-local
-└── 📁 path
-    └── 📁 to
-        └── artifact2
-
-
\ No newline at end of file diff --git a/artifactory/commands/commandssummaries/testdata/multiarch-image1.md b/artifactory/commands/commandssummaries/testdata/multiarch-image1.md new file mode 100644 index 000000000..b85eb1714 --- /dev/null +++ b/artifactory/commands/commandssummaries/testdata/multiarch-image1.md @@ -0,0 +1,21 @@ +#### multiarch-image:1 +
linux/amd64/multiarch-image:1 +📦 docker-local +└── 📁 multiarch-image + └── 📁 sha256:552ccb2628970ef526f13151a0269258589fc8b5701519a9c255c4dd224b9a21 + └── sha256__aee9d258e62f0666e3286acca21be37d2e39f69f8dde74454b9f3cd8ef437e4e + +
linux/arm64/multiarch-image:1 +📦 docker-local +└── 📁 multiarch-image + └── 📁 sha256:bee6dc0408dfd20c01e12e644d8bc1d60ff100a8c180d6c7e85d374c13ae4f92 + └── sha256__1f17f9d95f85ba55773db30ac8e6fae894831be87f5c28f2b58d17f04ef65e93 + +
linux/arm/multiarch-image:1 +📦 docker-local +└── 📁 multiarch-image + └── 📁 sha256:686085b9972e0f7a432b934574e3dca27b4fa0a3d10d0ae7099010160db6d338 + ├── sha256__33b5b5485e88e63d3630e5dcb008f98f102b0f980a9daa31bd976efdec7a8e4c + └── sha256__5480d2ca1740c20ce17652e01ed2265cdc914458acd41256a2b1ccff28f2762c + +
\ No newline at end of file diff --git a/artifactory/utils/container/buildinfo.go b/artifactory/utils/container/buildinfo.go index 38080befd..05da9d30d 100644 --- a/artifactory/utils/container/buildinfo.go +++ b/artifactory/utils/container/buildinfo.go @@ -376,6 +376,7 @@ func (builder *buildInfoBuilder) createMultiPlatformBuildInfo(fatManifest *FatMa Id: getModuleIdByManifest(manifest, baseModuleId), Type: buildinfo.Docker, Artifacts: artifacts, + Parent: baseModuleId, }) } return buildInfo, setBuildProperties(builder.buildName, builder.buildNumber, builder.project, builder.imageLayers, builder.serviceManager) From db8be7344e72a20cecc6d6091595f4b1c17acba2 Mon Sep 17 00:00:00 2001 From: Omer Zidkoni <50792403+omerzi@users.noreply.github.com> Date: Tue, 20 Aug 2024 16:28:27 +0300 Subject: [PATCH 2/4] Job Summary - Handle Docker Multi-Module Sections Separately (#1236) --- .../commandssummaries/buildinfosummary.go | 60 +++++++++++++++---- .../buildinfosummary_test.go | 53 ++++++++++++++++ .../testdata/multiarch-image1.md | 23 +++---- .../commands/commandssummaries/utils.go | 2 + artifactory/utils/container/buildinfo.go | 26 ++++---- 5 files changed, 130 insertions(+), 34 deletions(-) diff --git a/artifactory/commands/commandssummaries/buildinfosummary.go b/artifactory/commands/commandssummaries/buildinfosummary.go index 164e6de84..acd3710c4 100644 --- a/artifactory/commands/commandssummaries/buildinfosummary.go +++ b/artifactory/commands/commandssummaries/buildinfosummary.go @@ -4,6 +4,7 @@ import ( "fmt" 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-cli-core/v2/commandsummary" "path" "strings" @@ -91,20 +92,31 @@ func (bis *BuildInfoSummary) generateModulesMarkdown(modules ...buildInfo.Module // Skip the parent module if there are multiple modules, as it will be displayed as a header continue } - artifactsTree := bis.createArtifactsTree(module) - if isMultiModule { - // Collapse the module tree if there are multiple modules - modulesMarkdown.WriteString(fmt.Sprintf("
%s\n%s
", module.Id, artifactsTree)) - } else { - modulesMarkdown.WriteString(artifactsTree) - } + modulesMarkdown.WriteString(bis.generateModuleArtifactsTree(&module, isMultiModule)) } modulesMarkdown.WriteString("\n") } return modulesMarkdown.String() } -func (bis *BuildInfoSummary) createArtifactsTree(module buildInfo.Module) string { +func (bis *BuildInfoSummary) generateModuleArtifactsTree(module *buildInfo.Module, shouldCollapseArtifactsTree bool) string { + artifactsTree := bis.createArtifactsTree(module) + if shouldCollapseArtifactsTree { + return bis.generateModuleCollapsibleSection(module, artifactsTree) + } + return artifactsTree +} + +func (bis *BuildInfoSummary) generateModuleCollapsibleSection(module *buildInfo.Module, sectionContent string) string { + switch module.Type { + case buildInfo.Docker: + return createCollapsibleSection(createDockerMultiArchTitle(module, bis.platformUrl), sectionContent) + default: + return createCollapsibleSection(module.Id, sectionContent) + } +} + +func (bis *BuildInfoSummary) createArtifactsTree(module *buildInfo.Module) string { artifactsTree := utils.NewFileTree() for _, artifact := range module.Artifacts { artifactUrlInArtifactory := bis.generateArtifactUrl(artifact) @@ -129,7 +141,7 @@ func (bis *BuildInfoSummary) generateArtifactUrl(artifact buildInfo.Artifact) st func groupModulesByParent(modules []buildInfo.Module) map[string][]buildInfo.Module { parentToModulesMap := make(map[string][]buildInfo.Module, len(modules)) for _, module := range modules { - if len(module.Artifacts) == 0 || !isSupportedModuleType(module.Type) { + if len(module.Artifacts) == 0 || !isSupportedModule(&module) { continue } @@ -143,10 +155,13 @@ func groupModulesByParent(modules []buildInfo.Module) map[string][]buildInfo.Mod return parentToModulesMap } -func isSupportedModuleType(moduleType buildInfo.ModuleType) bool { - switch moduleType { - case buildInfo.Docker, buildInfo.Maven, buildInfo.Npm, buildInfo.Go, buildInfo.Generic, buildInfo.Terraform: +func isSupportedModule(module *buildInfo.Module) bool { + switch module.Type { + case buildInfo.Maven, buildInfo.Npm, buildInfo.Go, buildInfo.Generic, buildInfo.Terraform: return true + case buildInfo.Docker: + // Skip attestations that are added as a module for multi-arch docker builds + return !strings.HasPrefix(module.Id, container.AttestationsModuleIdPrefix) default: return false } @@ -161,3 +176,24 @@ func parseBuildTime(timestamp string) string { // Format the time in a more human-readable format and save it in a variable return buildInfoTime.Format(timeFormat) } + +func createDockerMultiArchTitle(module *buildInfo.Module, platformUrl string) string { + // Extract the parent image name from the module ID (e.g. my-image:1.0 -> my-image) + parentImageName := strings.Split(module.Parent, ":")[0] + + // Get the relevant SHA256 + var sha256 string + for _, artifact := range module.Artifacts { + if artifact.Name == container.ManifestJsonFile { + sha256 = artifact.Sha256 + break + } + } + // Create a link to the Docker package in Artifactory UI + dockerModuleLink := fmt.Sprintf(artifactoryDockerPackagesUiFormat, strings.TrimSuffix(platformUrl, "/"), "%2F%2F"+parentImageName, sha256) + return fmt.Sprintf("%s (🐸 View)", module.Id, dockerModuleLink) +} + +func createCollapsibleSection(title, content string) string { + return fmt.Sprintf("
%s\n%s
", title, content) +} diff --git a/artifactory/commands/commandssummaries/buildinfosummary_test.go b/artifactory/commands/commandssummaries/buildinfosummary_test.go index 5ab5cce21..407c04ee1 100644 --- a/artifactory/commands/commandssummaries/buildinfosummary_test.go +++ b/artifactory/commands/commandssummaries/buildinfosummary_test.go @@ -149,6 +149,16 @@ func TestBuildInfoModulesWithGrouping(t *testing.T) { Parent: "multiarch-image:1", Id: "linux/amd64/multiarch-image:1", Artifacts: []buildinfo.Artifact{ + { + Checksum: buildinfo.Checksum{ + Sha1: "32c1416f8430fbbabd82cb014c5e09c5fe702404", + Sha256: "sha256:552ccb2628970ef526f13151a0269258589fc8b5701519a9c255c4dd224b9a21", + Md5: "f568bfb1c9576a1f06235ebe0389d2d8", + }, + Name: "manifest.json", + Path: "multiarch-image/sha256__552ccb2628970ef526f13151a0269258589fc8b5701519a9c255c4dd224b9a21", + OriginalDeploymentRepo: "docker-local", + }, { Checksum: buildinfo.Checksum{ Sha1: "32c1416f8430fbbabd82cb014c5e09c5fe702404", @@ -166,6 +176,16 @@ func TestBuildInfoModulesWithGrouping(t *testing.T) { Parent: "multiarch-image:1", Id: "linux/arm64/multiarch-image:1", Artifacts: []buildinfo.Artifact{ + { + Checksum: buildinfo.Checksum{ + Sha1: "32c1416f8430fbbabd82cb014c5e09c5fe702404", + Sha256: "sha256:bee6dc0408dfd20c01e12e644d8bc1d60ff100a8c180d6c7e85d374c13ae4f92", + Md5: "f568bfb1c9576a1f06235ebe0389d2d8", + }, + Name: "manifest.json", + Path: "multiarch-image/sha256__bee6dc0408dfd20c01e12e644d8bc1d60ff100a8c180d6c7e85d374c13ae4f92", + OriginalDeploymentRepo: "docker-local", + }, { Checksum: buildinfo.Checksum{ Sha1: "82b6d4ae1f673c609469a0a84170390ecdff5a38", @@ -183,6 +203,16 @@ func TestBuildInfoModulesWithGrouping(t *testing.T) { Parent: "multiarch-image:1", Id: "linux/arm/multiarch-image:1", Artifacts: []buildinfo.Artifact{ + { + Checksum: buildinfo.Checksum{ + Sha1: "32c1416f8430fbbabd82cb014c5e09c5fe702404", + Sha256: "sha256:686085b9972e0f7a432b934574e3dca27b4fa0a3d10d0ae7099010160db6d338", + Md5: "f568bfb1c9576a1f06235ebe0389d2d8", + }, + Name: "manifest.json", + Path: "multiarch-image/sha256__686085b9972e0f7a432b934574e3dca27b4fa0a3d10d0ae7099010160db6d338", + OriginalDeploymentRepo: "docker-local", + }, { Checksum: buildinfo.Checksum{ Sha1: "63d3ac90f9cd322b76543d7bf96eeb92417faf41", @@ -205,10 +235,33 @@ func TestBuildInfoModulesWithGrouping(t *testing.T) { }, }, }, + { + Type: "docker", + Parent: "multiarch-image:1", + Id: "attestations/multiarch-image:1", + Checksum: buildinfo.Checksum{ + Sha256: "33b5b5485e88e63d3630e5dcb008f98f102b0f980a9daa31bd976efdec7a8e4c", + }, + Artifacts: []buildinfo.Artifact{ + { + Checksum: buildinfo.Checksum{ + Sha1: "63d3ac90f9cd322b76543d7bf96eeb92417faf41", + Sha256: "33b5b5485e88e63d3630e5dcb008f98f102b0f980a9daa31bd976efdec7a8e4c", + Md5: "99bbb1e1035aea4d9150e4348f24e107", + }, + Name: "sha256:67a5a1efd2df970568a17c1178ec5df786bbf627274f285c6dbce71fae9ebe57", + Path: "multiarch-image/sha256:686085b9972e0f7a432b934574e3dca27b4fa0a3d10d0ae7099010160db6d338/sha256__33b5b5485e88e63d3630e5dcb008f98f102b0f980a9daa31bd976efdec7a8e4c", + OriginalDeploymentRepo: "docker-local", + }, + }, + }, { Type: "docker", Parent: "image:2", Id: "image:2", + Checksum: buildinfo.Checksum{ + Sha256: "aee9d258e62f0666e3286acca21be37d2e39f69f8dde74454b9f3cd8ef437e4e", + }, Artifacts: []buildinfo.Artifact{ { Checksum: buildinfo.Checksum{ diff --git a/artifactory/commands/commandssummaries/testdata/multiarch-image1.md b/artifactory/commands/commandssummaries/testdata/multiarch-image1.md index b85eb1714..b4db962ac 100644 --- a/artifactory/commands/commandssummaries/testdata/multiarch-image1.md +++ b/artifactory/commands/commandssummaries/testdata/multiarch-image1.md @@ -1,21 +1,24 @@ #### multiarch-image:1 -
linux/amd64/multiarch-image:1 +
linux/amd64/multiarch-image:1 (🐸 View) 📦 docker-local └── 📁 multiarch-image - └── 📁 sha256:552ccb2628970ef526f13151a0269258589fc8b5701519a9c255c4dd224b9a21 - └── sha256__aee9d258e62f0666e3286acca21be37d2e39f69f8dde74454b9f3cd8ef437e4e + ├── 📁 sha256:552ccb2628970ef526f13151a0269258589fc8b5701519a9c255c4dd224b9a21 + │ └── sha256__aee9d258e62f0666e3286acca21be37d2e39f69f8dde74454b9f3cd8ef437e4e + └── sha256__552ccb2628970ef526f13151a0269258589fc8b5701519a9c255c4dd224b9a21 -
linux/arm64/multiarch-image:1 +
linux/arm64/multiarch-image:1 (🐸 View) 📦 docker-local └── 📁 multiarch-image - └── 📁 sha256:bee6dc0408dfd20c01e12e644d8bc1d60ff100a8c180d6c7e85d374c13ae4f92 - └── sha256__1f17f9d95f85ba55773db30ac8e6fae894831be87f5c28f2b58d17f04ef65e93 + ├── 📁 sha256:bee6dc0408dfd20c01e12e644d8bc1d60ff100a8c180d6c7e85d374c13ae4f92 + │ └── sha256__1f17f9d95f85ba55773db30ac8e6fae894831be87f5c28f2b58d17f04ef65e93 + └── sha256__bee6dc0408dfd20c01e12e644d8bc1d60ff100a8c180d6c7e85d374c13ae4f92 -
linux/arm/multiarch-image:1 +
linux/arm/multiarch-image:1 (🐸 View) 📦 docker-local └── 📁 multiarch-image - └── 📁 sha256:686085b9972e0f7a432b934574e3dca27b4fa0a3d10d0ae7099010160db6d338 - ├── sha256__33b5b5485e88e63d3630e5dcb008f98f102b0f980a9daa31bd976efdec7a8e4c - └── sha256__5480d2ca1740c20ce17652e01ed2265cdc914458acd41256a2b1ccff28f2762c + ├── 📁 sha256:686085b9972e0f7a432b934574e3dca27b4fa0a3d10d0ae7099010160db6d338 + │ ├── sha256__33b5b5485e88e63d3630e5dcb008f98f102b0f980a9daa31bd976efdec7a8e4c + │ └── sha256__5480d2ca1740c20ce17652e01ed2265cdc914458acd41256a2b1ccff28f2762c + └── sha256__686085b9972e0f7a432b934574e3dca27b4fa0a3d10d0ae7099010160db6d338
\ No newline at end of file diff --git a/artifactory/commands/commandssummaries/utils.go b/artifactory/commands/commandssummaries/utils.go index 75417663c..465ca4dd9 100644 --- a/artifactory/commands/commandssummaries/utils.go +++ b/artifactory/commands/commandssummaries/utils.go @@ -8,6 +8,8 @@ import ( const ( artifactory7UiFormat = "%sui/repos/tree/General/%s?clearFilter=true" artifactory6UiFormat = "%sartifactory/webapp/#/artifacts/browse/tree/General/%s" + + artifactoryDockerPackagesUiFormat = "%s/ui/packages/docker:%s/sha256__%s" ) func generateArtifactUrl(rtUrl, pathInRt string, majorVersion int) string { diff --git a/artifactory/utils/container/buildinfo.go b/artifactory/utils/container/buildinfo.go index 05da9d30d..a3a301184 100644 --- a/artifactory/utils/container/buildinfo.go +++ b/artifactory/utils/container/buildinfo.go @@ -27,7 +27,9 @@ const ( markerLayerSuffix string = ".marker" attestationManifestRefType string = "attestation-manifest" unknownPlatformPlaceholder string = "unknown" - attestationsModuleIdPrefix string = "attestations" + + ManifestJsonFile = "manifest.json" + AttestationsModuleIdPrefix string = "attestations" ) // Docker image build info builder. @@ -128,9 +130,9 @@ func writeLayersToFile(layers []utils.ResultItem) (filePath string, err error) { // Return - manifest artifacts as buildinfo.Artifact struct. func getManifestArtifact(manifest *utils.ResultItem) (artifact buildinfo.Artifact) { return buildinfo.Artifact{ - Name: "manifest.json", + Name: ManifestJsonFile, Type: "json", - Checksum: buildinfo.Checksum{Sha1: manifest.Actual_Sha1, Md5: manifest.Actual_Md5}, + Checksum: buildinfo.Checksum{Sha1: manifest.Actual_Sha1, Md5: manifest.Actual_Md5, Sha256: manifest.Sha256}, Path: path.Join(manifest.Path, manifest.Name), OriginalDeploymentRepo: manifest.Repo, } @@ -141,7 +143,7 @@ func getFatManifestArtifact(fatManifest *utils.ResultItem) (artifact buildinfo.A return buildinfo.Artifact{ Name: "list.manifest.json", Type: "json", - Checksum: buildinfo.Checksum{Sha1: fatManifest.Actual_Sha1, Md5: fatManifest.Actual_Md5}, + Checksum: buildinfo.Checksum{Sha1: fatManifest.Actual_Sha1, Md5: fatManifest.Actual_Md5, Sha256: fatManifest.Sha256}, Path: path.Join(fatManifest.Path, fatManifest.Name), OriginalDeploymentRepo: fatManifest.Repo, } @@ -150,9 +152,9 @@ func getFatManifestArtifact(fatManifest *utils.ResultItem) (artifact buildinfo.A // Return - manifest dependency as buildinfo.Dependency struct. func getManifestDependency(searchResults *utils.ResultItem) (dependency buildinfo.Dependency) { return buildinfo.Dependency{ - Id: "manifest.json", + Id: ManifestJsonFile, Type: "json", - Checksum: buildinfo.Checksum{Sha1: searchResults.Actual_Sha1, Md5: searchResults.Actual_Md5}, + Checksum: buildinfo.Checksum{Sha1: searchResults.Actual_Sha1, Md5: searchResults.Actual_Md5, Sha256: searchResults.Sha256}, } } @@ -239,7 +241,7 @@ func performMultiPlatformImageSearch(imagePathPattern string, serviceManager art resultMap = make(map[string][]*utils.ResultItem) for resultItem := new(utils.ResultItem); reader.NextRecord(resultItem) == nil; resultItem = new(utils.ResultItem) { pathToImageLayers[resultItem.Path] = append(pathToImageLayers[resultItem.Path], resultItem) - if resultItem.Name == "manifest.json" { + if resultItem.Name == ManifestJsonFile { pathToSha2[resultItem.Path] = "sha256:" + resultItem.Sha256 } } @@ -366,7 +368,7 @@ func (builder *buildInfoBuilder) createMultiPlatformBuildInfo(fatManifest *FatMa var artifacts []buildinfo.Artifact for _, layer := range image { builder.imageLayers = append(builder.imageLayers, *layer) - if layer.Name == "manifest.json" { + if layer.Name == ManifestJsonFile { artifacts = append(artifacts, getManifestArtifact(layer)) } else { artifacts = append(artifacts, layer.ToArtifact()) @@ -385,7 +387,7 @@ func (builder *buildInfoBuilder) createMultiPlatformBuildInfo(fatManifest *FatMa // Construct the manifest's module ID by its type (attestation) or its platform. func getModuleIdByManifest(manifest ManifestDetails, baseModuleId string) string { if manifest.Annotations.ReferenceType == attestationManifestRefType { - return path.Join(attestationsModuleIdPrefix, baseModuleId) + return path.Join(AttestationsModuleIdPrefix, baseModuleId) } if manifest.Platform.Os != unknownPlatformPlaceholder && manifest.Platform.Architecture != unknownPlatformPlaceholder { return path.Join(manifest.Platform.Os, manifest.Platform.Architecture, baseModuleId) @@ -395,11 +397,11 @@ func getModuleIdByManifest(manifest ManifestDetails, baseModuleId string) string func (builder *buildInfoBuilder) createPushBuildProperties(imageManifest *manifest, candidateLayers map[string]*utils.ResultItem) (artifacts []buildinfo.Artifact, dependencies []buildinfo.Dependency, imageLayers []utils.ResultItem, err error) { // Add artifacts. - artifacts = append(artifacts, getManifestArtifact(candidateLayers["manifest.json"])) + artifacts = append(artifacts, getManifestArtifact(candidateLayers[ManifestJsonFile])) artifacts = append(artifacts, candidateLayers[digestToLayer(builder.imageSha2)].ToArtifact()) // Add layers. - imageLayers = append(imageLayers, *candidateLayers["manifest.json"]) + imageLayers = append(imageLayers, *candidateLayers[ManifestJsonFile]) imageLayers = append(imageLayers, *candidateLayers[digestToLayer(builder.imageSha2)]) totalLayers := len(imageManifest.Layers) @@ -448,7 +450,7 @@ func (builder *buildInfoBuilder) createPullBuildProperties(imageManifest *manife func getDependenciesFromManifestConfig(candidateLayers map[string]*utils.ResultItem, imageSha2 string) ([]buildinfo.Dependency, error) { var dependencies []buildinfo.Dependency - manifestSearchResults, found := candidateLayers["manifest.json"] + manifestSearchResults, found := candidateLayers[ManifestJsonFile] if !found { return nil, errorutils.CheckErrorf("failed to collect build-info. The manifest.json was not found in Artifactory") } From f90a225e406d943d77e198adca48a4cbe63f1693 Mon Sep 17 00:00:00 2001 From: Asaf Ambar Date: Wed, 21 Aug 2024 00:12:23 +0300 Subject: [PATCH 3/4] Recognize "403 forbidden" error from pip command output, and clasiffy it as "forbidden" error type (#1225) --- artifactory/commands/python/python.go | 30 +++++++++++++++++++++------ go.mod | 2 +- go.sum | 4 ++-- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/artifactory/commands/python/python.go b/artifactory/commands/python/python.go index fa0c37718..5e193040d 100644 --- a/artifactory/commands/python/python.go +++ b/artifactory/commands/python/python.go @@ -1,21 +1,22 @@ package python import ( + "bytes" "errors" - python "github.com/jfrog/jfrog-cli-core/v2/utils/python" - "io" - "os/exec" - "github.com/jfrog/build-info-go/build" "github.com/jfrog/build-info-go/entities" + buildInfoUtils "github.com/jfrog/build-info-go/utils" "github.com/jfrog/build-info-go/utils/pythonutils" - gofrogcmd "github.com/jfrog/gofrog/io" "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/python/dependencies" "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/utils/config" + python "github.com/jfrog/jfrog-cli-core/v2/utils/python" "github.com/jfrog/jfrog-client-go/utils/errorutils" "github.com/jfrog/jfrog-client-go/utils/log" + "io" + "os" + "os/exec" ) type PythonCommand struct { @@ -71,7 +72,24 @@ func (pc *PythonCommand) Run() (err error) { err = errorutils.CheckError(pythonModule.RunInstallAndCollectDependencies(pc.args)) } else { // Python native command - err = gofrogcmd.RunCmd(pc) + for k, v := range pc.GetEnv() { + if err := os.Setenv(k, v); err != nil { + return err + } + } + + cmd := pc.GetCmd() + errBuffer := bytes.NewBuffer([]byte{}) + multiWriter := io.MultiWriter(os.Stderr, errBuffer) + cmd.Stderr = multiWriter + cmd.Stdout = os.Stdout + + err = cmd.Run() + if err != nil { + if buildInfoUtils.IsForbiddenOutput(buildInfoUtils.Pip, errBuffer.String()) { + err = errors.Join(err, buildInfoUtils.NewForbiddenError()) + } + } } return } diff --git a/go.mod b/go.mod index 4682a1631..5bcea4480 100644 --- a/go.mod +++ b/go.mod @@ -98,6 +98,6 @@ require ( // replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20240811142930-ab9715567376 -// replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.8.9-0.20240804091815-7407ceb49077 +replace github.com/jfrog/build-info-go => github.com/asafambar/build-info-go v1.8.9-0.20240819133117-c3f52700927d // replace github.com/jfrog/gofrog => github.com/jfrog/gofrog v1.3.3-0.20231223133729-ef57bd08cedc diff --git a/go.sum b/go.sum index fba7bcc48..c5ede1ed4 100644 --- a/go.sum +++ b/go.sum @@ -20,6 +20,8 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= +github.com/asafambar/build-info-go v1.8.9-0.20240819133117-c3f52700927d h1:GS9yDbl7Moer5ODbWu+DPcQtyCYlmRL4TAdt1l+b/Vo= +github.com/asafambar/build-info-go v1.8.9-0.20240819133117-c3f52700927d/go.mod h1:6mdtqjREK76bHNODXakqKR/+ksJ9dvfLS7H57BZtnLY= github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M= github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= @@ -92,8 +94,6 @@ github.com/jedib0t/go-pretty/v6 v6.5.9 h1:ACteMBRrrmm1gMsXe9PSTOClQ63IXDUt03H5U+ github.com/jedib0t/go-pretty/v6 v6.5.9/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= 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.9.33 h1:TEeTHDc3tEwZe/7kKhm1hQDd5vA/HnVhp1ZczUOWExk= -github.com/jfrog/build-info-go v1.9.33/go.mod h1:JTGnENexG1jRhKWCkQtZuDb0PerlzlSzF5OmMLG9kfc= github.com/jfrog/gofrog v1.7.5 h1:dFgtEDefJdlq9cqTRoe09RLxS5Bxbe1Ev5+E6SmZHcg= github.com/jfrog/gofrog v1.7.5/go.mod h1:jyGiCgiqSSR7k86hcUSu67XVvmvkkgWTmPsH25wI298= github.com/jfrog/jfrog-client-go v1.44.1 h1:Dj2+gIWMInHe7MWX3XLRhPRnlFOm7jnbCrGSgFDSMFY= From d507532c4863f60b2f7a85ad20e469a39b72c9a4 Mon Sep 17 00:00:00 2001 From: Eyal Ben Moshe Date: Wed, 21 Aug 2024 00:33:06 +0300 Subject: [PATCH 4/4] Promote to v2.55.2 (#1237) --- go.mod | 6 +++--- go.sum | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 5bcea4480..fa0f53b44 100644 --- a/go.mod +++ b/go.mod @@ -12,9 +12,9 @@ require ( github.com/google/uuid v1.6.0 github.com/gookit/color v1.5.4 github.com/jedib0t/go-pretty/v6 v6.5.9 - github.com/jfrog/build-info-go v1.9.33 + github.com/jfrog/build-info-go v1.9.34 github.com/jfrog/gofrog v1.7.5 - github.com/jfrog/jfrog-client-go v1.44.1 + github.com/jfrog/jfrog-client-go v1.44.2 github.com/magiconair/properties v1.8.7 github.com/manifoldco/promptui v0.9.0 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c @@ -98,6 +98,6 @@ require ( // replace github.com/jfrog/jfrog-client-go => github.com/jfrog/jfrog-client-go v1.28.1-0.20240811142930-ab9715567376 -replace github.com/jfrog/build-info-go => github.com/asafambar/build-info-go v1.8.9-0.20240819133117-c3f52700927d +// replace github.com/jfrog/build-info-go => github.com/asafambar/build-info-go v1.8.9-0.20240819133117-c3f52700927d // replace github.com/jfrog/gofrog => github.com/jfrog/gofrog v1.3.3-0.20231223133729-ef57bd08cedc diff --git a/go.sum b/go.sum index c5ede1ed4..e8046cf29 100644 --- a/go.sum +++ b/go.sum @@ -20,8 +20,6 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/asafambar/build-info-go v1.8.9-0.20240819133117-c3f52700927d h1:GS9yDbl7Moer5ODbWu+DPcQtyCYlmRL4TAdt1l+b/Vo= -github.com/asafambar/build-info-go v1.8.9-0.20240819133117-c3f52700927d/go.mod h1:6mdtqjREK76bHNODXakqKR/+ksJ9dvfLS7H57BZtnLY= github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M= github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= @@ -94,10 +92,12 @@ github.com/jedib0t/go-pretty/v6 v6.5.9 h1:ACteMBRrrmm1gMsXe9PSTOClQ63IXDUt03H5U+ github.com/jedib0t/go-pretty/v6 v6.5.9/go.mod h1:zbn98qrYlh95FIhwwsbIip0LYpwSG8SUOScs+v9/t0E= 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.9.34 h1:bPnW58VpclbpBe/x8XEu/2BIviEOoJrJ5PkRRcmU3Co= +github.com/jfrog/build-info-go v1.9.34/go.mod h1:6mdtqjREK76bHNODXakqKR/+ksJ9dvfLS7H57BZtnLY= github.com/jfrog/gofrog v1.7.5 h1:dFgtEDefJdlq9cqTRoe09RLxS5Bxbe1Ev5+E6SmZHcg= github.com/jfrog/gofrog v1.7.5/go.mod h1:jyGiCgiqSSR7k86hcUSu67XVvmvkkgWTmPsH25wI298= -github.com/jfrog/jfrog-client-go v1.44.1 h1:Dj2+gIWMInHe7MWX3XLRhPRnlFOm7jnbCrGSgFDSMFY= -github.com/jfrog/jfrog-client-go v1.44.1/go.mod h1:cRCuMvRgWJ6fSdyYs1pknBin41LLcXY94UOl7KHiQ8U= +github.com/jfrog/jfrog-client-go v1.44.2 h1:5t8tx6NOth6Xq24SdF3MYSd6vo0bTibW93nads2DEuY= +github.com/jfrog/jfrog-client-go v1.44.2/go.mod h1:f5Jfv+RGKVr4smOp4a4pxyBKdlpLG7R894kx2XW+w8c= 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=