Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,94 @@ func TestContainerPushWithDetailedSummary(t *testing.T) {
}
}

// TestContainerPushFatManifestWithDetailedSummary validates that --detailed-summary
// works for fat-manifest (multi-arch) images. Before the fix, the detailed-summary
// post-processing only knew about manifest.json and failed for fat-manifest images
// with: "could not find image manifest in Artifactory".
//
// We exercise SearchLayersForDetailedSummary - the exact function invoked by
// 'jf docker push --detailed-summary' when build-info collection isn't requested -
// against an image pushed to Artifactory as a fat manifest via 'docker buildx build --push'.
// The buildx setup mirrors TestPushFatManifestImage since 'docker push' alone
// can't produce a multi-arch manifest list locally.
func TestContainerPushFatManifestWithDetailedSummary(t *testing.T) {
if !*tests.TestDocker {
t.Skip("Skipping test. To run it, add the '-test.docker=true' option.")
}

workspace, err := filepath.Abs(tests.Out)
assert.NoError(t, err)
assert.NoError(t, fileutils.CreateDirIfNotExist(workspace))
testDataDir := filepath.Join(filepath.FromSlash(tests.GetTestResourcesPath()), "docker")
files, err := os.ReadDir(testDataDir)
assert.NoError(t, err)
for _, file := range files {
if !file.IsDir() {
_, err := tests.ReplaceTemplateVariables(filepath.Join(testDataDir, file.Name()), tests.Out)
assert.NoError(t, err)
}
}

testContainer := buildBuilderImage(t, workspace, "Dockerfile.Buildx.Fatmanifest", "buildx_detailed_summary_container")
defer func() { assert.NoError(t, testContainer.Terminate(context.Background())) }()

err = testContainer.Exec(context.Background(), "sh", "script.sh")
assert.NoError(t, err)

loginToArtifactory(t, testContainer)

imageName := tests.DockerImageName + "-multiarch-detailed-summary"
imageTag := path.Join(tests.RtContainerHostName, tests.DockerLocalRepo, imageName) + ":1"

assert.NoError(t, testContainer.Exec(
context.Background(),
"docker",
"buildx",
"build",
"--platform",
"linux/amd64,linux/arm64,linux/arm/v7",
"--tag",
imageTag,
"-f",
"Dockerfile.Fatmanifest",
"--push",
".",
))
defer inttestutils.ContainerTestCleanup(t, serverDetails, artHttpDetails, imageName, "", tests.DockerLocalRepo)

serviceManager, err := utils.CreateServiceManager(serverDetails, -1, 0, false)
require.NoError(t, err)
image := container.NewImage(imageTag)
repo, err := image.ExtractArtifactoryRepoKey()
require.NoError(t, err)

layers, err := container.SearchLayersForDetailedSummary(image, repo, serviceManager, "")
require.NoError(t, err, "SearchLayersForDetailedSummary should succeed for fat-manifest images")
require.NotNil(t, layers)
require.NotEmpty(t, *layers, "fat-manifest detailed summary should not be empty")

const (
fatManifestFile = "list.manifest.json"
manifestFile = "manifest.json"
)
var foundFatManifest bool
var manifestCount int
var blobCount int
for _, layer := range *layers {
switch layer.Name {
case fatManifestFile:
foundFatManifest = true
case manifestFile:
manifestCount++
default:
blobCount++
}
}
assert.True(t, foundFatManifest, "fat manifest (list.manifest.json) should be in detailed summary")
assert.GreaterOrEqual(t, manifestCount, 3, "expected at least one manifest.json per platform (3 platforms requested)")
assert.Greater(t, blobCount, 0, "expected at least one image blob (config/layer) in detailed summary")
}

func TestContainerPushWithMultipleSlash(t *testing.T) {
containerManagers := initContainerTest(t)
for _, repo := range []string{tests.DockerLocalRepo, tests.DockerVirtualRepo} {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ require (

//replace github.com/ktrysmt/go-bitbucket => github.com/ktrysmt/go-bitbucket v0.9.80

// replace github.com/jfrog/jfrog-cli-artifactory => github.com/agrasth/jfrog-cli-artifactory v0.2.2-0.20260428100316-aa702370ec20
replace github.com/jfrog/jfrog-cli-artifactory => github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260514152016-5023d66d7a8f

// replace github.com/jfrog/build-info-go => github.com/jfrog/build-info-go v1.13.1-0.20260428071432-1e9d9a1991ad

Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -418,8 +418,8 @@ github.com/jfrog/jfrog-apps-config v1.0.1 h1:mtv6k7g8A8BVhlHGlSveapqf4mJfonwvXYL
github.com/jfrog/jfrog-apps-config v1.0.1/go.mod h1:8AIIr1oY9JuH5dylz2S6f8Ym2MaadPLR6noCBO4C22w=
github.com/jfrog/jfrog-cli-application v1.0.2-0.20260405065840-c930d515ef34 h1:qD53oDmaw7+5HjaU7FupqbB55saabNzMoMtu3kJfmg4=
github.com/jfrog/jfrog-cli-application v1.0.2-0.20260405065840-c930d515ef34/go.mod h1:xum2HquWO5uExa/A7MQs3TgJJVEeoqTR+6Z4mfBr1Xw=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260514080218-aef923f46e93 h1:5SjZGAsV0MDk5H8DK+7yBmbahdakfblRe0CW8Kp9vvk=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260514080218-aef923f46e93/go.mod h1:XESHQN9MEeje13fJaXtbljidwTqlJO+qhhUHHDxwntQ=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260514152016-5023d66d7a8f h1:e8LSE707voo34MHkPNDrXvjw2gR+5Zlswzs9NOq6T7A=
github.com/jfrog/jfrog-cli-artifactory v0.8.1-0.20260514152016-5023d66d7a8f/go.mod h1:XESHQN9MEeje13fJaXtbljidwTqlJO+qhhUHHDxwntQ=
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260430125911-ad12ac6f1316 h1:xAl5D+SjLeRH1gCsSHFPpXJeQQBv2HDGqDTDkFOKJ2s=
github.com/jfrog/jfrog-cli-core/v2 v2.60.1-0.20260430125911-ad12ac6f1316/go.mod h1:bjAkVD8c2W+jg4whqy10bSXDC/c+Se8/ll/GPp5F/+0=
github.com/jfrog/jfrog-cli-evidence v0.9.2 h1:huiBzQSI9z3OF3l2RphthdXl1aH9zBsvAt+zLsApORI=
Expand Down
Loading