go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/led/ledcmd/get_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 ledcmd 16 17 import ( 18 "context" 19 "fmt" 20 "net/http" 21 22 "google.golang.org/protobuf/types/known/fieldmaskpb" 23 24 bbpb "go.chromium.org/luci/buildbucket/proto" 25 "go.chromium.org/luci/common/errors" 26 "go.chromium.org/luci/common/logging" 27 28 "go.chromium.org/luci/led/job" 29 "go.chromium.org/luci/led/job/jobcreate" 30 ) 31 32 // GetBuildOpts are the options for GetBuild. 33 type GetBuildOpts struct { 34 BuildbucketHost string 35 BuildID int64 36 PinBotID bool 37 PriorityDiff int 38 KitchenSupport job.KitchenSupport 39 RealBuild bool 40 Experiments map[string]bool 41 } 42 43 func getBuildJobName(opts GetBuildOpts) string { 44 return fmt.Sprintf("get-build %d", opts.BuildID) 45 } 46 47 // GetBuild retrieves a job Definition from a Buildbucket build. 48 func GetBuild(ctx context.Context, authClient *http.Client, opts GetBuildOpts) (*job.Definition, error) { 49 logging.Infof(ctx, "getting build definition") 50 51 if opts.RealBuild { 52 return synthesizeBuildFromTemplate(ctx, authClient, opts) 53 } 54 55 bbClient := newBuildbucketClient(authClient, opts.BuildbucketHost) 56 57 answer, err := bbClient.GetBuild(ctx, &bbpb.GetBuildRequest{ 58 Id: opts.BuildID, 59 Mask: &bbpb.BuildMask{ 60 Fields: &fieldmaskpb.FieldMask{ 61 Paths: []string{ 62 "builder", 63 "infra", 64 "input", 65 "scheduling_timeout", 66 "execution_timeout", 67 "grace_period", 68 "exe", 69 "tags", 70 }, 71 }, 72 }, 73 }) 74 if err != nil { 75 return nil, err 76 } 77 78 if answer.Infra.GetBuildbucket().GetAgent().GetOutput() != nil { 79 answer.Infra.Buildbucket.Agent.Output = nil 80 } 81 82 logging.Infof(ctx, "getting build definition: done") 83 84 swarmingTaskID := answer.Infra.Swarming.GetTaskId() 85 swarmingHostname := answer.Infra.Swarming.GetHostname() 86 87 if swarmingTaskID == "" { 88 return nil, errors.New("unable to find swarming task ID on buildbucket task") 89 } 90 if swarmingHostname == "" { 91 return nil, errors.New("unable to find swarming hostname on buildbucket task") 92 } 93 94 return GetFromSwarmingTask(ctx, authClient, answer, GetFromSwarmingTaskOpts{ 95 SwarmingHost: swarmingHostname, 96 TaskID: swarmingTaskID, 97 PinBotID: opts.PinBotID, 98 Name: getBuildJobName(opts), 99 PriorityDiff: opts.PriorityDiff, 100 KitchenSupport: opts.KitchenSupport, 101 }) 102 } 103 104 func synthesizeBuildFromTemplate(ctx context.Context, authClient *http.Client, opts GetBuildOpts) (*job.Definition, error) { 105 bbClient := newBuildbucketClient(authClient, opts.BuildbucketHost) 106 build, err := bbClient.SynthesizeBuild(ctx, &bbpb.SynthesizeBuildRequest{ 107 TemplateBuildId: opts.BuildID, 108 Experiments: opts.Experiments, 109 }) 110 if err != nil { 111 return nil, err 112 } 113 return jobcreate.FromBuild(build, opts.BuildbucketHost, getBuildJobName(opts), opts.PriorityDiff, nil), nil 114 }