1515package docker
1616
1717import (
18+ "archive/tar"
19+ "bytes"
1820 "context"
1921 "fmt"
2022 "io"
2123 "os"
24+ "runtime"
25+ "strings"
2226
2327 "go.opentelemetry.io/otel"
2428 "golang.org/x/sync/errgroup"
@@ -38,6 +42,7 @@ import (
3842 "github.com/docker/docker/pkg/stdcopy"
3943 v1 "github.com/google/go-containerregistry/pkg/v1"
4044 "github.com/google/go-containerregistry/pkg/v1/empty"
45+ "github.com/google/go-containerregistry/pkg/v1/tarball"
4146 image_spec "github.com/opencontainers/image-spec/specs-go/v1"
4247)
4348
@@ -366,9 +371,97 @@ type dockerLoader struct {
366371 cli * client.Client
367372}
368373
374+ // filterXattrsForMacOS creates a wrapped layer that filters known problematic xattrs
375+ func filterXattrsForMacOS (ctx context.Context , originalLayer v1.Layer ) (v1.Layer , error ) {
376+ log := clog .FromContext (ctx )
377+ log .Debugf ("Filtering problematic xattrs for MacOS compatibility" )
378+
379+ rc , err := originalLayer .Uncompressed ()
380+ if err != nil {
381+ return nil , err
382+ }
383+ defer rc .Close ()
384+
385+ // Create a buffer for the new layer content
386+ var buf bytes.Buffer
387+
388+ // Process the tar file, filtering xattrs
389+ tr := tar .NewReader (rc )
390+ tw := tar .NewWriter (& buf )
391+
392+ for {
393+ hdr , err := tr .Next ()
394+ if err == io .EOF {
395+ break
396+ }
397+ if err != nil {
398+ return nil , err
399+ }
400+
401+ // Filter out problematic xattrs
402+ if hdr .PAXRecords != nil {
403+ filteredPAXRecords := make (map [string ]string )
404+ for k , v := range hdr .PAXRecords {
405+ // Filter known problematic xattrs
406+ if strings .HasPrefix (k , "SCHILY.xattr.com.apple." ) ||
407+ strings .HasPrefix (k , "SCHILY.xattr.com.docker." ) {
408+ log .Debugf ("Filtering xattr %s for file %s" , k , hdr .Name )
409+ continue
410+ }
411+ filteredPAXRecords [k ] = v
412+ }
413+ hdr .PAXRecords = filteredPAXRecords
414+ }
415+
416+ if err := tw .WriteHeader (hdr ); err != nil {
417+ return nil , err
418+ }
419+
420+ if hdr .Typeflag == tar .TypeReg {
421+ if _ , err := io .Copy (tw , tr ); err != nil {
422+ return nil , err
423+ }
424+ }
425+ }
426+
427+ if err := tw .Close (); err != nil {
428+ return nil , err
429+ }
430+
431+ // Create a new layer from the filtered content
432+ layerReader := func () (io.ReadCloser , error ) {
433+ return io .NopCloser (bytes .NewReader (buf .Bytes ())), nil
434+ }
435+
436+ // Create a new layer from the opener function
437+ layer , err := tarball .LayerFromOpener (layerReader )
438+ if err != nil {
439+ return nil , err
440+ }
441+
442+ return layer , nil
443+ }
444+
369445func (d * dockerLoader ) LoadImage (ctx context.Context , layer v1.Layer , arch apko_types.Architecture , bc * apko_build.Context ) (string , error ) {
370446 ctx , span := otel .Tracer ("melange" ).Start (ctx , "docker.LoadImage" )
371447 defer span .End ()
448+
449+ log := clog .FromContext (ctx )
450+
451+ // Detect MacOS platform
452+ isMacOS := runtime .GOOS == "darwin"
453+ if isMacOS {
454+ log .Debug ("Detected MacOS platform, using modified image loading approach" )
455+
456+ // Filter known problematic xattrs on MacOS
457+ filteredLayer , err := filterXattrsForMacOS (ctx , layer )
458+ if err != nil {
459+ log .Warnf ("Failed to filter xattrs for MacOS compatibility: %v" , err )
460+ log .Warn ("Continuing with original layer, but this may cause errors" )
461+ } else {
462+ layer = filteredLayer
463+ }
464+ }
372465
373466 creationTime , err := bc .GetBuildDateEpoch ()
374467 if err != nil {
@@ -380,10 +473,23 @@ func (d *dockerLoader) LoadImage(ctx context.Context, layer v1.Layer, arch apko_
380473 return "" , err
381474 }
382475
476+ // Try to load the image
383477 ref , err := apko_oci .LoadImage (ctx , img , []string {"melange:latest" })
384- if err != nil {
478+ if err != nil && isMacOS {
479+ // On MacOS, if loading fails, we might still have xattr errors
480+ log .Warnf ("Initial image load failed on MacOS: %v" , err )
481+
482+ // If we're on MacOS and still got an error, provide a helpful error message
483+ if strings .Contains (err .Error (), "xattr" ) {
484+ return "" , fmt .Errorf ("unable to handle MacOS xattr issues: %w\n " +
485+ "Consider using the QEMU runner instead with MELANGE_EXTRA_OPTS=\" --runner=qemu\" " , err )
486+ } else {
487+ return "" , err
488+ }
489+ } else if err != nil {
385490 return "" , err
386491 }
492+
387493 return ref .String (), nil
388494}
389495
@@ -408,4 +514,4 @@ func (d *dockerLoader) RemoveImage(ctx context.Context, ref string) error {
408514 }
409515
410516 return nil
411- }
517+ }
0 commit comments