Skip to content

Commit

Permalink
implement publish
Browse files Browse the repository at this point in the history
Signed-off-by: Nicolas De Loof <[email protected]>
  • Loading branch information
ndeloof committed Sep 20, 2023
1 parent 805541b commit 5ca35c8
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 4 deletions.
118 changes: 115 additions & 3 deletions pkg/compose/publish.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,136 @@ package compose

import (
"context"
"encoding/json"
"os"

"github.com/compose-spec/compose-go/types"
"github.com/distribution/reference"
"github.com/docker/buildx/util/imagetools"
"github.com/docker/compose/v2/pkg/api"
"github.com/docker/compose/v2/pkg/progress"
"github.com/opencontainers/go-digest"
"github.com/opencontainers/image-spec/specs-go"
v1 "github.com/opencontainers/image-spec/specs-go/v1"
)

func (s *composeService) Publish(ctx context.Context, project *types.Project, repository string, options api.PublishOptions) error {
return progress.RunWithTitle(ctx, func(ctx context.Context) error {
return s.publish(ctx, project, repository, options)
}, s.stdinfo(), "Publishing")
}

func (s *composeService) publish(ctx context.Context, project *types.Project, repository string, options api.PublishOptions) error {
err := s.Push(ctx, project, api.PushOptions{})
if err != nil {
return err
}

_, err = reference.ParseDockerRef(repository)
w := progress.ContextWriter(ctx)

named, err := reference.ParseDockerRef(repository)
if err != nil {
return err
}

resolver := imagetools.New(imagetools.Opt{
Auth: s.configFile(),
})

var layers []v1.Descriptor
for _, file := range project.ComposeFiles {
f, err := os.ReadFile(file)
if err != nil {
return err
}

w.Event(progress.Event{
ID: file,
Text: "publishing",
Status: progress.Working,
})
layer := v1.Descriptor{
MediaType: "application/vnd.docker.compose.file+yaml",
Digest: digest.FromString(string(f)),
Size: int64(len(f)),
Annotations: map[string]string{
"com.docker.compose": api.ComposeVersion,
},
}
layers = append(layers, layer)
err = resolver.Push(ctx, named, layer, f)
if err != nil {
w.Event(progress.Event{
ID: file,
Text: "publishing",
Status: progress.Error,
})

return err
}

w.Event(progress.Event{
ID: file,
Text: "published",
Status: progress.Done,
})
}

emptyConfig, err := json.Marshal(v1.ImageConfig{})
if err != nil {
return err
}
configDescriptor := v1.Descriptor{
MediaType: "application/vnd.docker.compose.project",
Digest: digest.FromBytes(emptyConfig),
Size: int64(len(emptyConfig)),
Annotations: map[string]string{
"com.docker.compose.version": api.ComposeVersion,
},
}
err = resolver.Push(ctx, named, configDescriptor, emptyConfig)
if err != nil {
return err
}

imageManifest, err := json.Marshal(v1.Manifest{
Versioned: specs.Versioned{SchemaVersion: 2},
MediaType: v1.MediaTypeImageManifest,
ArtifactType: "application/vnd.docker.compose.project",
Config: configDescriptor,
Layers: layers,
})
if err != nil {
return err
}

// TODO publish project.ComposeFiles
w.Event(progress.Event{
ID: repository,
Text: "publishing",
Status: progress.Working,
})

return api.ErrNotImplemented
err = resolver.Push(ctx, named, v1.Descriptor{
MediaType: v1.MediaTypeImageManifest,
Digest: digest.FromString(string(imageManifest)),
Size: int64(len(imageManifest)),
Annotations: map[string]string{
"com.docker.compose.version": api.ComposeVersion,
},
ArtifactType: "application/vnd.docker.compose.project",
}, imageManifest)
if err != nil {
w.Event(progress.Event{
ID: repository,
Text: "publishing",
Status: progress.Error,
})
return err
}
w.Event(progress.Event{
ID: repository,
Text: "published",
Status: progress.Done,
})
return nil
}
7 changes: 6 additions & 1 deletion pkg/remote/oci.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ type ociRemoteLoader struct {
offline bool
}

const prefix = "oci:"
const prefix = "oci://"

func (g ociRemoteLoader) Accept(path string) bool {
return strings.HasPrefix(path, prefix)
Expand Down Expand Up @@ -117,6 +117,11 @@ func (g ociRemoteLoader) Load(ctx context.Context, path string) (string, error)
if err != nil {
return "", err
}

if descriptor.Config.MediaType != "application/vnd.docker.compose.project" {
return "", fmt.Errorf("%s is not a compose project OCI artifact, but %s", ref.String(), descriptor.Config.MediaType)
}

for i, layer := range descriptor.Layers {
digested, err := reference.WithDigest(ref, layer.Digest)
if err != nil {
Expand Down

0 comments on commit 5ca35c8

Please sign in to comment.