@@ -62,18 +62,22 @@ func (p platformParser) DefaultSpec() platforms.Platform {
6262}
6363
6464func Build (ctx context.Context , client * containerd.Client , options types.BuilderBuildOptions ) error {
65- buildctlBinary , buildctlArgs , needsLoading , metaFile , tags , cleanup , err := generateBuildctlArgs (ctx , client , options )
65+ buildCtlArgs , err := generateBuildctlArgs (ctx , client , options )
6666 if err != nil {
6767 return err
6868 }
69- if cleanup != nil {
70- defer cleanup ()
69+ if buildCtlArgs . Cleanup != nil {
70+ defer buildCtlArgs . Cleanup ()
7171 }
7272
73+ buildctlBinary := buildCtlArgs .BuildctlBinary
74+ buildctlArgs := buildCtlArgs .BuildctlArgs
75+
7376 log .L .Debugf ("running %s %v" , buildctlBinary , buildctlArgs )
7477 buildctlCmd := exec .Command (buildctlBinary , buildctlArgs ... )
7578 buildctlCmd .Env = os .Environ ()
7679
80+ needsLoading := buildCtlArgs .NeedsLoading
7781 var buildctlStdout io.Reader
7882 if needsLoading {
7983 buildctlStdout , err = buildctlCmd .StdoutPipe ()
@@ -96,6 +100,8 @@ func Build(ctx context.Context, client *containerd.Client, options types.Builder
96100 if err != nil {
97101 return err
98102 }
103+
104+ // Load the image into the containerd image store
99105 if err = loadImage (ctx , buildctlStdout , options .GOptions .Namespace , options .GOptions .Address , options .GOptions .Snapshotter , options .Stdout , platMC , options .Quiet ); err != nil {
100106 return err
101107 }
@@ -106,7 +112,7 @@ func Build(ctx context.Context, client *containerd.Client, options types.Builder
106112 }
107113
108114 if options .IidFile != "" {
109- id , err := getDigestFromMetaFile (metaFile )
115+ id , err := getDigestFromMetaFile (buildCtlArgs . MetaFile )
110116 if err != nil {
111117 return err
112118 }
@@ -115,6 +121,7 @@ func Build(ctx context.Context, client *containerd.Client, options types.Builder
115121 }
116122 }
117123
124+ tags := buildCtlArgs .Tags
118125 if len (tags ) > 1 {
119126 log .L .Debug ("Found more than 1 tag" )
120127 imageService := client .ImageService ()
@@ -161,11 +168,15 @@ func loadImage(ctx context.Context, in io.Reader, namespace, address, snapshotte
161168 client .Close ()
162169 }()
163170 r := & readCounter {Reader : in }
164- imgs , err := client .Import (ctx , r , containerd .WithDigestRef (archive .DigestTranslator (snapshotter )), containerd .WithSkipDigestRef (func (name string ) bool { return name != "" }), containerd .WithImportPlatform (platMC ))
171+ imgs , err := client .Import (ctx , r ,
172+ containerd .WithDigestRef (archive .DigestTranslator (snapshotter )),
173+ containerd .WithSkipDigestRef (func (name string ) bool { return name != "" }),
174+ containerd .WithImportPlatform (platMC ),
175+ )
165176 if err != nil {
166177 if r .N == 0 {
167178 // Avoid confusing "unrecognized image format"
168- return errors . New ("no image was built" )
179+ return fmt . Errorf ("no image was built: %w" , err )
169180 }
170181 if errors .Is (err , images .ErrEmptyWalk ) {
171182 err = fmt .Errorf ("%w (Hint: set `--platform=PLATFORM` or `--all-platforms`)" , err )
@@ -193,69 +204,82 @@ func loadImage(ctx context.Context, in io.Reader, namespace, address, snapshotte
193204 return nil
194205}
195206
196- func generateBuildctlArgs (ctx context.Context , client * containerd.Client , options types.BuilderBuildOptions ) (buildCtlBinary string ,
197- buildctlArgs []string , needsLoading bool , metaFile string , tags []string , cleanup func (), err error ) {
207+ type BuildctlArgsResult struct {
208+ BuildctlArgs []string
209+ BuildctlBinary string
210+ Cleanup func ()
211+ DestFile string
212+ MetaFile string
213+ NeedsLoading bool // Specifies whether the image needs to be loaded into the containerd image store
214+ Tags []string
215+ }
198216
217+ func generateBuildctlArgs (ctx context.Context , client * containerd.Client , options types.BuilderBuildOptions ) (result BuildctlArgsResult , err error ) {
199218 buildctlBinary , err := buildkitutil .BuildctlBinary ()
200219 if err != nil {
201- return "" , nil , false , "" , nil , nil , err
220+ return result , err
202221 }
222+ result .BuildctlBinary = buildctlBinary
203223
204224 output := options .Output
205225 if output == "" {
206226 info , err := client .Server (ctx )
207227 if err != nil {
208- return "" , nil , false , "" , nil , nil , err
228+ return result , err
209229 }
210230 sharable , err := isImageSharable (options .BuildKitHost , options .GOptions .Namespace , info .UUID , options .GOptions .Snapshotter , options .Platform )
211231 if err != nil {
212- return "" , nil , false , "" , nil , nil , err
232+ return result , err
213233 }
214234 if sharable {
215235 output = "type=image,unpack=true" // ensure the target stage is unlazied (needed for any snapshotters)
216236 } else {
217- output = "type=docker"
237+ // https://github.com/moby/buildkit?tab=readme-ov-file#output
238+ // type=image is the native type for containerd
239+ output = "type=image"
218240 if len (options .Platform ) > 1 {
219241 // For avoiding `error: failed to solve: docker exporter does not currently support exporting manifest lists`
220242 // TODO: consider using type=oci for single-options.Platform build too
221243 output = "type=oci"
222244 }
223- needsLoading = true
224245 }
225246 } else {
226247 if ! strings .Contains (output , "type=" ) {
227248 // should accept --output <DIR> as an alias of --output
228249 // type=local,dest=<DIR>
229250 output = fmt .Sprintf ("type=local,dest=%s" , output )
230251 }
231- if strings .Contains (output , "type=docker" ) || strings .Contains (output , "type=oci" ) {
232- if ! strings .Contains (output , "dest=" ) {
233- needsLoading = true
234- }
252+ }
253+
254+ if strings .Contains (output , "type=docker" ) || strings .Contains (output , "type=oci" ) {
255+ if ! strings .Contains (output , "dest=" ) {
256+ result .NeedsLoading = true
235257 }
236258 }
259+
260+ var tags []string
237261 if tags = strutil .DedupeStrSlice (options .Tag ); len (tags ) > 0 {
238262 ref := tags [0 ]
239263 parsedReference , err := referenceutil .Parse (ref )
240264 if err != nil {
241- return "" , nil , false , "" , nil , nil , err
265+ return result , err
242266 }
243267 output += ",name=" + parsedReference .String ()
244268
245269 // pick the first tag and add it to output
246270 for idx , tag := range tags {
247271 parsedReference , err = referenceutil .Parse (tag )
248272 if err != nil {
249- return "" , nil , false , "" , nil , nil , err
273+ return result , err
250274 }
251275 tags [idx ] = parsedReference .String ()
252276 }
253277 } else if len (tags ) == 0 {
254278 output = output + ",dangling-name-prefix=<none>"
255279 }
280+ result .Tags = tags
256281
257- buildctlArgs = buildkitutil .BuildctlBaseArgs (options .BuildKitHost )
258-
282+ buildctlArgs := buildkitutil .BuildctlBaseArgs (options .BuildKitHost )
259283 buildctlArgs = append (buildctlArgs , []string {
260284 "build" ,
261285 "--progress=" + options .Progress ,
@@ -272,9 +296,9 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option
272296 var err error
273297 dir , err = buildkitutil .WriteTempDockerfile (options .Stdin )
274298 if err != nil {
275- return "" , nil , false , "" , nil , nil , err
299+ return result , err
276300 }
277- cleanup = func () {
301+ result . Cleanup = func () {
278302 os .RemoveAll (dir )
279303 }
280304 } else {
@@ -287,12 +311,12 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option
287311 }
288312 dir , file , err = buildkitutil .BuildKitFile (dir , file )
289313 if err != nil {
290- return "" , nil , false , "" , nil , nil , err
314+ return result , err
291315 }
292316
293317 buildCtx , err := parseContextNames (options .ExtendedBuildContext )
294318 if err != nil {
295- return "" , nil , false , "" , nil , nil , err
319+ return result , err
296320 }
297321
298322 for k , v := range buildCtx {
@@ -307,7 +331,7 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option
307331 if isOCILayout := strings .HasPrefix (v , "oci-layout://" ); isOCILayout {
308332 args , err := parseBuildContextFromOCILayout (k , v )
309333 if err != nil {
310- return "" , nil , false , "" , nil , nil , err
334+ return result , err
311335 }
312336
313337 buildctlArgs = append (buildctlArgs , args ... )
@@ -316,7 +340,7 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option
316340
317341 path , err := filepath .Abs (v )
318342 if err != nil {
319- return "" , nil , false , "" , nil , nil , err
343+ return result , err
320344 }
321345 buildctlArgs = append (buildctlArgs , fmt .Sprintf ("--local=%s=%s" , k , path ))
322346 buildctlArgs = append (buildctlArgs , fmt .Sprintf ("--opt=context:%s=local:%s" , k , k ))
@@ -363,7 +387,7 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option
363387 }
364388 }
365389 } else {
366- return "" , nil , false , "" , nil , nil , fmt .Errorf ("invalid build arg %q" , ba )
390+ return result , fmt .Errorf ("invalid build arg %q" , ba )
367391 }
368392 }
369393
@@ -406,7 +430,7 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option
406430 optAttestType := strings .TrimPrefix (optAttestType , "type=" )
407431 buildctlArgs = append (buildctlArgs , fmt .Sprintf ("--opt=attest:%s=%s" , optAttestType , optAttestAttrs ))
408432 } else {
409- return "" , nil , false , "" , nil , nil , fmt .Errorf ("attestation type not specified" )
433+ return result , fmt .Errorf ("attestation type not specified" )
410434 }
411435 }
412436
@@ -435,11 +459,11 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option
435459 if options .IidFile != "" {
436460 file , err := os .CreateTemp ("" , "buildkit-meta-*" )
437461 if err != nil {
438- return "" , nil , false , "" , nil , cleanup , err
462+ return result , err
439463 }
440464 defer file .Close ()
441- metaFile = file .Name ()
442- buildctlArgs = append (buildctlArgs , "--metadata-file=" + metaFile )
465+ result . MetaFile = file .Name ()
466+ buildctlArgs = append (buildctlArgs , "--metadata-file=" + result . MetaFile )
443467 }
444468
445469 if options .NetworkMode != "" {
@@ -462,7 +486,9 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option
462486 buildctlArgs = append (buildctlArgs , "--opt=add-hosts=" + strings .Join (extraHosts , "," ))
463487 }
464488
465- return buildctlBinary , buildctlArgs , needsLoading , metaFile , tags , cleanup , nil
489+ result .BuildctlArgs = buildctlArgs
490+
491+ return result , nil
466492}
467493
468494func getDigestFromMetaFile (path string ) (string , error ) {
0 commit comments