@@ -305,18 +305,42 @@ func NewIndexBuilder(contentStore content.Store, blobStore orascontent.Storage,
305305 }, nil
306306}
307307
308+ // BuildAndPush builds a SOCI index, pushes and labels the artifacts, and returns the SOCI index.
309+ func (b * IndexBuilder ) BuildAndPush (ctx context.Context , blobStore store.Store , img images.Image ) (* IndexWithMetadata , error ) {
310+ sociIndexWithMetadata , done , err := b .Build (ctx , blobStore , img )
311+ if err != nil {
312+ return nil , err
313+ }
314+ defer done (ctx )
315+
316+ err = WriteSociIndex (ctx , sociIndexWithMetadata , blobStore , b .ArtifactsDb )
317+ if err != nil {
318+ return nil , err
319+ }
320+ return sociIndexWithMetadata , nil
321+ }
322+
308323// Build builds a soci index for `img` and return the index with metadata.
309- func (b * IndexBuilder ) Build (ctx context.Context , img images.Image ) (* IndexWithMetadata , error ) {
324+ // To prevent garbage collection of the zTOCs pushed by this command,
325+ // we obtain a lease from containerd and also return it.
326+ // It is the responsibility of the caller to terminate the lease.
327+ // Ideally the lease ends after labelling and pushing the index and related zTOCs.
328+ func (b * IndexBuilder ) Build (ctx context.Context , blobStore store.Store , img images.Image ) (* IndexWithMetadata , store.CleanupFunc , error ) {
310329 // we get manifest descriptor before calling images.Manifest, since after calling
311330 // images.Manifest, images.Children will error out when reading the manifest blob (this happens on containerd side)
312331 imgManifestDesc , err := GetImageManifestDescriptor (ctx , b .contentStore , img .Target , platforms .OnlyStrict (b .config .platform ))
313332 if err != nil {
314- return nil , err
333+ return nil , nil , err
315334 }
316335 manifest , err := images .Manifest (ctx , b .contentStore , img .Target , platforms .OnlyStrict (b .config .platform ))
317336
318337 if err != nil {
319- return nil , err
338+ return nil , nil , err
339+ }
340+
341+ ctx , done , err := blobStore .BatchOpen (ctx )
342+ if err != nil {
343+ return nil , nil , err
320344 }
321345
322346 // attempt to build a ztoc for each layer
@@ -357,8 +381,8 @@ func (b *IndexBuilder) Build(ctx context.Context, img images.Image) (*IndexWithM
357381 for _ , err := range errs {
358382 errWrap = fmt .Errorf ("%w; %v" , errWrap , err )
359383 }
360-
361- return nil , errWrap
384+ done ( ctx )
385+ return nil , nil , errWrap
362386 }
363387
364388 ztocsDesc := make ([]ocispec.Descriptor , 0 , len (sociLayersDesc ))
@@ -369,7 +393,8 @@ func (b *IndexBuilder) Build(ctx context.Context, img images.Image) (*IndexWithM
369393 }
370394
371395 if len (ztocsDesc ) == 0 {
372- return nil , ErrEmptyIndex
396+ done (ctx )
397+ return nil , nil , ErrEmptyIndex
373398 }
374399
375400 annotations := map [string ]string {
@@ -388,7 +413,7 @@ func (b *IndexBuilder) Build(ctx context.Context, img images.Image) (*IndexWithM
388413 Platform : & b .config .platform ,
389414 ImageDigest : img .Target .Digest ,
390415 CreatedAt : time .Now (),
391- }, nil
416+ }, done , nil
392417}
393418
394419// buildSociLayer builds a ztoc for an image layer (`desc`) and returns ztoc descriptor.
0 commit comments