Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,7 @@ The directory layout conforms to OCI Image Spec v1.0.
* `src=<path>`: source directory for cache importer
* `tag=<tag>`: specify custom tag of image to read from local index (default: `latest`)
* `digest=sha256:<sha256digest>`: specify explicit digest of the manifest list to import
* `lazy=<true|false>`: when `true`, imported cache layers are not eagerly extracted but loaded on demand (default: `false`). This is useful for ephemeral/daemonless `buildkitd` setups where each build uses its own daemon instance, avoiding unnecessary extraction overhead for cached builds.

#### GitHub Actions cache (experimental)

Expand Down
21 changes: 17 additions & 4 deletions cache/remotecache/local/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const (
attrDigest = "digest"
attrSrc = "src"
attrDest = "dest"
attrLazy = "lazy"
attrImageManifest = "image-manifest"
attrOCIMediatypes = "oci-mediatypes"
contentStoreIDPrefix = "local:"
Expand Down Expand Up @@ -63,7 +64,7 @@ func ResolveCacheExporterFunc(sm *session.Manager) remotecache.ResolveCacheExpor
}

csID := contentStoreIDPrefix + store
cs, err := getContentStore(ctx, sm, g, csID)
cs, err := getContentStore(ctx, sm, g, csID, false)
if err != nil {
return nil, err
}
Expand All @@ -83,8 +84,16 @@ func ResolveCacheImporterFunc(sm *session.Manager) remotecache.ResolveCacheImpor
if store == "" {
return nil, ocispecs.Descriptor{}, errors.New("local cache importer requires src")
}
lazy := false
if v, ok := attrs[attrLazy]; ok {
b, err := strconv.ParseBool(v)
if err != nil {
return nil, ocispecs.Descriptor{}, errors.Wrapf(err, "failed to parse %s", attrLazy)
}
lazy = b
}
csID := contentStoreIDPrefix + store
cs, err := getContentStore(ctx, sm, g, csID)
cs, err := getContentStore(ctx, sm, g, csID, lazy)
if err != nil {
return nil, ocispecs.Descriptor{}, err
}
Expand All @@ -102,7 +111,7 @@ func ResolveCacheImporterFunc(sm *session.Manager) remotecache.ResolveCacheImpor
}
}

func getContentStore(ctx context.Context, sm *session.Manager, g session.Group, storeID string) (content.Store, error) {
func getContentStore(ctx context.Context, sm *session.Manager, g session.Group, storeID string, lazy bool) (content.Store, error) {
// TODO: to ensure correct session is detected, new api for finding if storeID is supported is needed
sessionID := g.SessionIterator().NextSession()
if sessionID == "" {
Expand All @@ -116,7 +125,11 @@ func getContentStore(ctx context.Context, sm *session.Manager, g session.Group,
if err != nil {
return nil, err
}
return &unlazyProvider{sessioncontent.NewCallerStore(caller, storeID), g}, nil
cs := sessioncontent.NewCallerStore(caller, storeID)
if lazy {
return cs, nil
}
return &unlazyProvider{cs, g}, nil
}

type unlazyProvider struct {
Expand Down
1 change: 1 addition & 0 deletions docs/reference/buildctl.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,3 +253,4 @@ For example:

* `--import-cache type=registry,ref=example.com/foo/bar` - import into the cache from an OCI image.
* `--import-cache type=local,src=path/to/dir` - import into the cache from a directory local to where `buildctl` is running.
* `--import-cache type=local,src=path/to/dir,lazy=true` - import with lazy layer loading (layers are not eagerly extracted; useful for ephemeral/daemonless buildkitd).