go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/led/ledcli/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 ledcli 16 17 import ( 18 "context" 19 "net/http" 20 "strconv" 21 "strings" 22 23 "github.com/maruel/subcommands" 24 25 "go.chromium.org/luci/auth" 26 "go.chromium.org/luci/common/errors" 27 "go.chromium.org/luci/common/flag/stringmapflag" 28 "go.chromium.org/luci/led/job" 29 "go.chromium.org/luci/led/ledcmd" 30 ) 31 32 func getBuildCmd(opts cmdBaseOptions) *subcommands.Command { 33 return &subcommands.Command{ 34 UsageLine: "get-build <buildbucket_build_id>", 35 ShortDesc: "obtain a JobDefinition from a buildbucket build", 36 LongDesc: `Obtains the build's definition from buildbucket and produces a JobDefinition. 37 38 buildbucket_build_id can be specified with "b" prefix like b8962624445013664976, 39 which is useful when copying it from ci.chromium.org URL.`, 40 41 CommandRun: func() subcommands.CommandRun { 42 ret := &cmdGetBuild{} 43 ret.initFlags(opts) 44 return ret 45 }, 46 } 47 } 48 49 type cmdGetBuild struct { 50 cmdBase 51 52 bbHost string 53 pinBotID bool 54 priorityDiff int 55 realBuild bool 56 experiments stringmapflag.Value 57 processedExperiments map[string]bool 58 59 buildID int64 60 } 61 62 func (c *cmdGetBuild) initFlags(opts cmdBaseOptions) { 63 c.Flags.StringVar(&c.bbHost, "B", "cr-buildbucket.appspot.com", 64 "The buildbucket hostname to grab the definition from.") 65 66 c.Flags.BoolVar(&c.pinBotID, "pin-bot-id", false, 67 "Pin the bot id in the generated job Definition's dimensions.") 68 69 c.Flags.IntVar(&c.priorityDiff, "adjust-priority", 10, 70 "Increase or decrease the priority of the generated job. Note: priority works like Unix 'niceness'; Higher values indicate lower priority.") 71 72 c.Flags.BoolVar(&c.realBuild, "real-build", false, 73 "Get a synthesized build using the provided build as template, instead the provided build itself.") 74 75 c.Flags.Var(&c.experiments, "experiment", 76 "Note: only works in real-build mode.\n"+ 77 "(repeatable) enable or disable an experiment. This takes a parameter of `experiment_name=true|false` and "+ 78 "adds/removes the corresponding experiment. Already enabled experiments are left as is unless they "+ 79 "are explicitly disabled.") 80 81 c.cmdBase.initFlags(opts) 82 } 83 84 func (c *cmdGetBuild) jobInput() bool { return false } 85 func (c *cmdGetBuild) positionalRange() (min, max int) { return 1, 1 } 86 87 func (c *cmdGetBuild) validateFlags(ctx context.Context, positionals []string, env subcommands.Env) (err error) { 88 if err := pingHost(c.bbHost); err != nil { 89 return errors.Annotate(err, "buildbucket host").Err() 90 } 91 92 buildIDStr := positionals[0] 93 if strings.HasPrefix(buildIDStr, "b") { 94 // Milo URL structure prefixes buildbucket builds id with "b". 95 buildIDStr = positionals[0][1:] 96 } 97 if c.buildID, err = strconv.ParseInt(buildIDStr, 10, 64); err != nil { 98 return errors.Annotate(err, "bad <buildbucket_build_id>").Err() 99 } 100 if !c.realBuild && len(c.experiments) > 0 { 101 return errors.Reason("setting experiments only works in real-build mode.").Err() 102 } 103 if c.processedExperiments, err = processExperiments(c.experiments); err != nil { 104 return err 105 } 106 return nil 107 } 108 109 func (c *cmdGetBuild) execute(ctx context.Context, authClient *http.Client, _ auth.Options, inJob *job.Definition) (out any, err error) { 110 return ledcmd.GetBuild(ctx, authClient, ledcmd.GetBuildOpts{ 111 BuildbucketHost: c.bbHost, 112 BuildID: c.buildID, 113 PinBotID: c.pinBotID, 114 PriorityDiff: c.priorityDiff, 115 KitchenSupport: c.kitchenSupport, 116 RealBuild: c.realBuild, 117 Experiments: c.processedExperiments, 118 }) 119 } 120 121 func (c *cmdGetBuild) Run(a subcommands.Application, args []string, env subcommands.Env) int { 122 return c.doContextExecute(a, c, args, env) 123 }