Skip to content

Commit

Permalink
set tree_digest in actions
Browse files Browse the repository at this point in the history
as well as setting the root_directory_digest. As required by
bb-storage's CompletenessCheckingBlobAccess.
  • Loading branch information
harrysarson committed Jul 16, 2024
1 parent cfc8493 commit eb1f2ba
Show file tree
Hide file tree
Showing 5 changed files with 295 additions and 34 deletions.
4 changes: 2 additions & 2 deletions pkg/qualifier/qualifier_translator.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func gitCommand(qualifiers map[string]string) func(string) *remoteexecution.Comm
return &remoteexecution.Command{
Arguments: []string{"sh", "-c", script},
OutputPaths: []string{"out"},
OutputDirectoryFormat: remoteexecution.Command_DIRECTORY_ONLY,
OutputDirectoryFormat: remoteexecution.Command_TREE_AND_DIRECTORY,
}
}
}
Expand All @@ -81,7 +81,7 @@ func octetStreamCommand(qualifiers map[string]string) func(string) *remoteexecut
return &remoteexecution.Command{
Arguments: []string{"sh", "-c", script},
OutputPaths: []string{"out"},
OutputDirectoryFormat: remoteexecution.Command_DIRECTORY_ONLY,
OutputDirectoryFormat: remoteexecution.Command_TREE_AND_DIRECTORY,
}
}
}
Expand Down
1 change: 1 addition & 0 deletions pkg/storage/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ go_test(
":storage",
"//internal/mock",
"//pkg/proto/asset",
"//pkg/storage/blobstore",
"@com_github_bazelbuild_remote_apis//build/bazel/remote/asset/v1:asset",
"@com_github_bazelbuild_remote_apis//build/bazel/remote/execution/v2:execution",
"@com_github_buildbarn_bb_storage//pkg/blobstore/buffer",
Expand Down
89 changes: 89 additions & 0 deletions pkg/storage/action_cache_asset_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,22 @@ func NewActionCacheAssetStore(actionCache, contentAddressableStorage blobstore.B
}
}

func (rs *actionCacheAssetStore) assetToDirectory(ctx context.Context, asset *asset.Asset, instance digest.InstanceName) (*remoteexecution.Directory, error) {
digestFunction, err := instance.GetDigestFunction(remoteexecution.DigestFunction_UNKNOWN, len(asset.Digest.GetHash()))
if err != nil {
return nil, err
}
digest, err := digestFunction.NewDigestFromProto(asset.Digest)
if err != nil {
return nil, err
}
directory, err := rs.contentAddressableStorage.Get(ctx, digest).ToProto(&remoteexecution.Directory{}, rs.maximumMessageSizeBytes)
if err != nil {
return nil, err
}
return directory.(*remoteexecution.Directory), nil
}

func (rs *actionCacheAssetStore) actionResultToAsset(ctx context.Context, a *remoteexecution.ActionResult, instance digest.InstanceName) (*asset.Asset, error) {
digest := &remoteexecution.Digest{}
assetType := asset.Asset_DIRECTORY
Expand Down Expand Up @@ -233,10 +249,43 @@ func (rs *actionCacheAssetStore) Put(ctx context.Context, ref *asset.AssetRefere
}

if data.Type == asset.Asset_DIRECTORY {
d, err := rs.assetToDirectory(ctx, data, instance)

if err != nil {
// Users will hit this if they upload an digest referencing an
// arbitary Blob in `PushDirectory` or a digest that does not
// reference any blob at all.
return fmt.Errorf("digest in directory asset does not reference a Directory: %v", err)
}

// If it is a directory, construct a tree from it as tree digest is
// required for action result
tree, err := rs.directoryToTree(ctx, d, instance)
if err != nil {
return err
}
treePb, err := proto.Marshal(tree)
if err != nil {
return err
}
treeDigest, err := ProtoToDigest(tree)
if err != nil {
return err
}
bbTreeDigest, err := digestFunction.NewDigestFromProto(treeDigest)
if err != nil {
return err
}
err = rs.contentAddressableStorage.Put(ctx, bbTreeDigest, buffer.NewCASBufferFromByteSlice(bbTreeDigest, treePb, buffer.UserProvided))
if err != nil {
return err
}

// Use digest as a root directory digest
actionResult.OutputDirectories = []*remoteexecution.OutputDirectory{{
Path: "out",
RootDirectoryDigest: data.Digest,
TreeDigest: treeDigest,
}}
} else if data.Type == asset.Asset_BLOB {
// Use the digest as an output file digest
Expand All @@ -251,6 +300,46 @@ func (rs *actionCacheAssetStore) Put(ctx context.Context, ref *asset.AssetRefere
return rs.actionCache.Put(ctx, bbActionDigest, buffer.NewProtoBufferFromProto(actionResult, buffer.UserProvided))
}

func (rs *actionCacheAssetStore) directoryToTree(ctx context.Context, directory *remoteexecution.Directory, instance digest.InstanceName) (*remoteexecution.Tree, error) {
children := []*remoteexecution.Directory{}
for _, node := range directory.Directories {
nodeChildren, err := rs.directoryNodeToDirectories(ctx, instance, node)
if err != nil {
return nil, err
}
children = append(children, nodeChildren...)
}

return &remoteexecution.Tree{
Root: directory,
Children: children,
}, nil
}

func (rs *actionCacheAssetStore) directoryNodeToDirectories(ctx context.Context, instance digest.InstanceName, node *remoteexecution.DirectoryNode) ([]*remoteexecution.Directory, error) {
digestFunction, err := instance.GetDigestFunction(remoteexecution.DigestFunction_UNKNOWN, len(node.GetDigest().GetHash()))
if err != nil {
return nil, err
}
digest, err := digestFunction.NewDigestFromProto(node.Digest)
if err != nil {
return nil, err
}
directory, err := rs.contentAddressableStorage.Get(ctx, digest).ToProto(&remoteexecution.Directory{}, rs.maximumMessageSizeBytes)
if err != nil {
return nil, err
}
directories := []*remoteexecution.Directory{directory.(*remoteexecution.Directory)}
for _, node := range directory.(*remoteexecution.Directory).Directories {
children, err := rs.directoryNodeToDirectories(ctx, instance, node)
if err != nil {
return nil, err
}
directories = append(directories, children...)
}
return directories, nil
}

func getDefaultTimestamp() *timestamppb.Timestamp {
return timestamppb.New(time.Unix(0, 0))
}
Loading

0 comments on commit eb1f2ba

Please sign in to comment.