blob: eec102fd1aea2e19e52eebeef7c17ceab2460a06 [file] [log] [blame]
// Copyright 2021 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package run
import (
"fmt"
"strings"
"go.chromium.org/luci/common/git/footer"
)
// ExtractOptions computes the Run Options from 1 CL description.
func ExtractOptions(clDescription string) *Options {
modern := footer.ParseMessage(clDescription)
legacy := footer.ParseLegacyMetadata(clDescription)
valuesOf := func(mkey, lkey string) []string {
var out []string
switch k := footer.NormalizeKey(mkey); {
case mkey == "":
case k != mkey:
panic(fmt.Errorf("Use normalized key %q not %q in CV code", k, mkey))
default:
out = append(out, modern[mkey]...)
}
if lkey != "" {
out = append(out, legacy[lkey]...)
}
return out
}
has := func(mkey, lkey, value string) bool {
if l := strings.ToLower(value); l != value {
panic(fmt.Errorf("Use lowercase value %q not %q in CV code", l, value))
}
for _, v := range valuesOf(mkey, lkey) {
if strings.ToLower(v) == value {
return true
}
}
return false
}
isTrue := func(mkey, lkey string) bool { return has(mkey, lkey, "true") }
o := &Options{}
if isTrue("No-Equivalent-Builders", "NO_EQUIVALENT_BUILDERS") {
o.SkipEquivalentBuilders = true
}
if isTrue("Cq-Do-Not-Cancel-Tryjobs", "") {
o.AvoidCancellingTryjobs = true
}
if isTrue("No-Tree-Checks", "NOTREECHECKS") {
o.SkipTreeChecks = true
}
if isTrue("No-Try", "NOTRY") {
o.SkipTryjobs = true
}
if isTrue("No-Presubmit", "NOPRESUBMIT") {
o.SkipPresubmit = true
}
// TODO(tandrii): parse CQ-IncludeTrybots.
return o
}
// MergeOptions merges two Run Options.
//
// Does not modify the passed object, but may return either of them.
func MergeOptions(a, b *Options) *Options {
switch {
case a == nil:
return b
case b == nil:
return a
}
return &Options{
AvoidCancellingTryjobs: a.AvoidCancellingTryjobs || b.AvoidCancellingTryjobs,
SkipTryjobs: a.SkipTryjobs || b.SkipTryjobs,
SkipPresubmit: a.SkipPresubmit || b.SkipPresubmit,
SkipEquivalentBuilders: a.SkipEquivalentBuilders || b.SkipEquivalentBuilders,
SkipTreeChecks: a.SkipTreeChecks || b.SkipTreeChecks,
}
}