go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/buildbucket/appengine/rpc/cancel_build.go (about)

     1  // Copyright 2020 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package rpc
    16  
    17  import (
    18  	"context"
    19  
    20  	"google.golang.org/grpc/codes"
    21  
    22  	"go.chromium.org/luci/common/errors"
    23  	"go.chromium.org/luci/grpc/appstatus"
    24  
    25  	"go.chromium.org/luci/buildbucket/appengine/common"
    26  	"go.chromium.org/luci/buildbucket/appengine/internal/perm"
    27  	"go.chromium.org/luci/buildbucket/appengine/model"
    28  	"go.chromium.org/luci/buildbucket/appengine/tasks"
    29  	"go.chromium.org/luci/buildbucket/bbperms"
    30  	pb "go.chromium.org/luci/buildbucket/proto"
    31  	"go.chromium.org/luci/buildbucket/protoutil"
    32  )
    33  
    34  // validateCancel validates the given request.
    35  func validateCancel(req *pb.CancelBuildRequest) error {
    36  	var err error
    37  	switch {
    38  	case req.GetId() == 0:
    39  		return errors.Reason("id is required").Err()
    40  	case req.SummaryMarkdown == "":
    41  		return errors.Reason("summary_markdown is required").Err()
    42  	case teeErr(validateSummaryMarkdown(req.SummaryMarkdown), &err) != nil:
    43  		return errors.Annotate(err, "summary_markdown").Err()
    44  	}
    45  	return nil
    46  }
    47  
    48  // CancelBuild handles a request to cancel a build. Implements pb.BuildsServer.
    49  func (*Builds) CancelBuild(ctx context.Context, req *pb.CancelBuildRequest) (*pb.Build, error) {
    50  	if err := validateCancel(req); err != nil {
    51  		return nil, appstatus.BadRequest(err)
    52  	}
    53  	m, err := model.NewBuildMask("", req.Fields, req.Mask)
    54  	if err != nil {
    55  		return nil, appstatus.Errorf(codes.InvalidArgument, "invalid mask")
    56  	}
    57  
    58  	bld, err := common.GetBuild(ctx, req.Id)
    59  	if err != nil {
    60  		return nil, err
    61  	}
    62  	if err := perm.HasInBuilder(ctx, bbperms.BuildsCancel, bld.Proto.Builder); err != nil {
    63  		return nil, err
    64  	}
    65  
    66  	redact := func(b *pb.Build) error {
    67  		return perm.RedactBuild(ctx, nil, b)
    68  	}
    69  
    70  	if protoutil.IsEnded(bld.Proto.Status) {
    71  		return bld.ToProto(ctx, m, redact)
    72  	}
    73  
    74  	bld, err = tasks.StartCancel(ctx, req.Id, req.SummaryMarkdown)
    75  	if err != nil {
    76  		return nil, err
    77  	}
    78  	return bld.ToProto(ctx, m, redact)
    79  }