@@ -18,24 +18,136 @@ package compose
18
18
19
19
import (
20
20
"context"
21
+ "encoding/json"
22
+ "os"
21
23
22
24
"github.com/compose-spec/compose-go/types"
23
25
"github.com/distribution/reference"
26
+ "github.com/docker/buildx/util/imagetools"
24
27
"github.com/docker/compose/v2/pkg/api"
28
+ "github.com/docker/compose/v2/pkg/progress"
29
+ "github.com/opencontainers/go-digest"
30
+ "github.com/opencontainers/image-spec/specs-go"
31
+ v1 "github.com/opencontainers/image-spec/specs-go/v1"
25
32
)
26
33
27
34
func (s * composeService ) Publish (ctx context.Context , project * types.Project , repository string , options api.PublishOptions ) error {
35
+ return progress .RunWithTitle (ctx , func (ctx context.Context ) error {
36
+ return s .publish (ctx , project , repository , options )
37
+ }, s .stdinfo (), "Publishing" )
38
+ }
39
+
40
+ func (s * composeService ) publish (ctx context.Context , project * types.Project , repository string , options api.PublishOptions ) error {
28
41
err := s .Push (ctx , project , api.PushOptions {})
29
42
if err != nil {
30
43
return err
31
44
}
32
45
33
- _ , err = reference .ParseDockerRef (repository )
46
+ w := progress .ContextWriter (ctx )
47
+
48
+ named , err := reference .ParseDockerRef (repository )
49
+ if err != nil {
50
+ return err
51
+ }
52
+
53
+ resolver := imagetools .New (imagetools.Opt {
54
+ Auth : s .configFile (),
55
+ })
56
+
57
+ var layers []v1.Descriptor
58
+ for _ , file := range project .ComposeFiles {
59
+ f , err := os .ReadFile (file )
60
+ if err != nil {
61
+ return err
62
+ }
63
+
64
+ w .Event (progress.Event {
65
+ ID : file ,
66
+ Text : "publishing" ,
67
+ Status : progress .Working ,
68
+ })
69
+ layer := v1.Descriptor {
70
+ MediaType : "application/vnd.docker.compose.file+yaml" ,
71
+ Digest : digest .FromString (string (f )),
72
+ Size : int64 (len (f )),
73
+ Annotations : map [string ]string {
74
+ "com.docker.compose" : api .ComposeVersion ,
75
+ },
76
+ }
77
+ layers = append (layers , layer )
78
+ err = resolver .Push (ctx , named , layer , f )
79
+ if err != nil {
80
+ w .Event (progress.Event {
81
+ ID : file ,
82
+ Text : "publishing" ,
83
+ Status : progress .Error ,
84
+ })
85
+
86
+ return err
87
+ }
88
+
89
+ w .Event (progress.Event {
90
+ ID : file ,
91
+ Text : "published" ,
92
+ Status : progress .Done ,
93
+ })
94
+ }
95
+
96
+ emptyConfig , err := json .Marshal (v1.ImageConfig {})
97
+ if err != nil {
98
+ return err
99
+ }
100
+ configDescriptor := v1.Descriptor {
101
+ MediaType : "application/vnd.docker.compose.project" ,
102
+ Digest : digest .FromBytes (emptyConfig ),
103
+ Size : int64 (len (emptyConfig )),
104
+ Annotations : map [string ]string {
105
+ "com.docker.compose.version" : api .ComposeVersion ,
106
+ },
107
+ }
108
+ err = resolver .Push (ctx , named , configDescriptor , emptyConfig )
109
+ if err != nil {
110
+ return err
111
+ }
112
+
113
+ imageManifest , err := json .Marshal (v1.Manifest {
114
+ Versioned : specs.Versioned {SchemaVersion : 2 },
115
+ MediaType : v1 .MediaTypeImageManifest ,
116
+ ArtifactType : "application/vnd.docker.compose.project" ,
117
+ Config : configDescriptor ,
118
+ Layers : layers ,
119
+ })
34
120
if err != nil {
35
121
return err
36
122
}
37
123
38
- // TODO publish project.ComposeFiles
124
+ w .Event (progress.Event {
125
+ ID : repository ,
126
+ Text : "publishing" ,
127
+ Status : progress .Working ,
128
+ })
39
129
40
- return api .ErrNotImplemented
130
+ err = resolver .Push (ctx , named , v1.Descriptor {
131
+ MediaType : v1 .MediaTypeImageManifest ,
132
+ Digest : digest .FromString (string (imageManifest )),
133
+ Size : int64 (len (imageManifest )),
134
+ Annotations : map [string ]string {
135
+ "com.docker.compose.version" : api .ComposeVersion ,
136
+ },
137
+ ArtifactType : "application/vnd.docker.compose.project" ,
138
+ }, imageManifest )
139
+ if err != nil {
140
+ w .Event (progress.Event {
141
+ ID : repository ,
142
+ Text : "publishing" ,
143
+ Status : progress .Error ,
144
+ })
145
+ return err
146
+ }
147
+ w .Event (progress.Event {
148
+ ID : repository ,
149
+ Text : "published" ,
150
+ Status : progress .Done ,
151
+ })
152
+ return nil
41
153
}
0 commit comments