@@ -32,6 +32,7 @@ var imagetoolsTests = []func(t *testing.T, sb integration.Sandbox){
3232 testImagetoolsInspectAndFilter ,
3333 testImagetoolsCreatePlatformFilter ,
3434 testImagetoolsAppend ,
35+ testImagetoolsFile ,
3536 testImagetoolsAnnotation ,
3637 testImagetoolsMergeSources ,
3738 testImagetoolsMergeSourcesWithAttestations ,
@@ -398,6 +399,70 @@ func testImagetoolsAppend(t *testing.T, sb integration.Sandbox) {
398399 require .Equal (t , "linux/arm64" , platformsByDigest [arm64Digest ])
399400}
400401
402+ // testImagetoolsFile verifies create --file reads a source descriptor from disk
403+ // and resolves it against the target repository.
404+ func testImagetoolsFile (t * testing.T , sb integration.Sandbox ) {
405+ if ! isDockerContainerWorker (sb ) {
406+ t .Skip ("only testing with docker-container worker, imagetools only runs on docker-container" )
407+ }
408+
409+ dir := createDockerfile (t )
410+ registry , err := sb .NewRegistry ()
411+ if errors .Is (err , integration .ErrRequirements ) {
412+ t .Skip (err .Error ())
413+ }
414+ require .NoError (t , err )
415+
416+ source := registry + "/buildx/imtools-file:latest"
417+ out , err := buildCmd (sb , withArgs ("-t" , source , "--push" , "--platform=linux/amd64" , "--provenance=false" , dir ))
418+ require .NoError (t , err , string (out ))
419+
420+ cmd := buildxCmd (sb , withArgs ("imagetools" , "inspect" , source , "--raw" ))
421+ dt , err := cmd .CombinedOutput ()
422+ require .NoError (t , err , string (dt ))
423+
424+ var sourceManifest ocispecs.Manifest
425+ err = json .Unmarshal (dt , & sourceManifest )
426+ require .NoError (t , err )
427+ sourceDesc := ocispecs.Descriptor {
428+ MediaType : sourceManifest .MediaType ,
429+ Digest : digest .FromBytes (dt ),
430+ Size : int64 (len (dt )),
431+ }
432+
433+ descJSON , err := json .Marshal (sourceDesc )
434+ require .NoError (t , err )
435+ descPath := filepath .Join (dir , "source-descriptor.json" )
436+ err = os .WriteFile (descPath , descJSON , 0o644 )
437+ require .NoError (t , err )
438+
439+ target := registry + "/buildx/imtools-file:from-file"
440+ cmd = buildxCmd (sb , withArgs ("imagetools" , "create" , "--file" , descPath , "-t" , target ))
441+ dt , err = cmd .CombinedOutput ()
442+ require .NoError (t , err , string (dt ))
443+
444+ cmd = buildxCmd (sb , withArgs ("imagetools" , "inspect" , target , "--raw" ))
445+ dt , err = cmd .CombinedOutput ()
446+ require .NoError (t , err , string (dt ))
447+
448+ var idx ocispecs.Index
449+ err = json .Unmarshal (dt , & idx )
450+ require .NoError (t , err )
451+ require .Equal (t , images .MediaTypeDockerSchema2ManifestList , idx .MediaType )
452+ require .Len (t , idx .Manifests , 1 )
453+ require .Equal (t , sourceDesc .Digest , idx .Manifests [0 ].Digest )
454+
455+ cmd = buildxCmd (sb , withArgs ("imagetools" , "inspect" , target + "@" + string (idx .Manifests [0 ].Digest ), "--raw" ))
456+ dt , err = cmd .CombinedOutput ()
457+ require .NoError (t , err , string (dt ))
458+
459+ var copiedManifest ocispecs.Manifest
460+ err = json .Unmarshal (dt , & copiedManifest )
461+ require .NoError (t , err )
462+ require .Equal (t , sourceManifest .Config .Digest , copiedManifest .Config .Digest )
463+ require .Equal (t , len (sourceManifest .Layers ), len (copiedManifest .Layers ))
464+ }
465+
401466// testImagetoolsAnnotation verifies index and manifest annotations added by imagetools create.
402467func testImagetoolsAnnotation (t * testing.T , sb integration.Sandbox ) {
403468 if ! isDockerContainerWorker (sb ) {
0 commit comments