go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/bisection/internal/config/validate.go (about) 1 // Copyright 2022 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 config implements config validation for LUCI Bisection 16 package config 17 18 import ( 19 configpb "go.chromium.org/luci/bisection/proto/config" 20 luciproto "go.chromium.org/luci/common/proto" 21 "go.chromium.org/luci/config/validation" 22 ) 23 24 func validateTestAnalysisConfig(ctx *validation.Context, testAnalysisConfig *configpb.TestAnalysisConfig) { 25 ctx.Enter("test_analysis_config") 26 defer ctx.Exit() 27 if testAnalysisConfig == nil { 28 ctx.Errorf("missing test analysis config") 29 return 30 } 31 validateGerritConfig(ctx, testAnalysisConfig.GerritConfig) 32 validateBuildConfig(ctx, testAnalysisConfig.BuildConfig) 33 } 34 35 func validateCompileAnalysisConfig(ctx *validation.Context, compileAnalysisConfig *configpb.CompileAnalysisConfig) { 36 ctx.Enter("compile_analysis_config") 37 defer ctx.Exit() 38 if compileAnalysisConfig == nil { 39 ctx.Errorf("missing compile analysis config") 40 return 41 } 42 validateBuildConfig(ctx, compileAnalysisConfig.BuildConfig) 43 validateGerritConfig(ctx, compileAnalysisConfig.GerritConfig) 44 } 45 46 func validateBuildConfig(ctx *validation.Context, cfg *configpb.BuildConfig) { 47 ctx.Enter("build_config") 48 defer ctx.Exit() 49 50 if cfg == nil { 51 ctx.Errorf("missing build config") 52 return 53 } 54 validateBuilder(ctx, cfg.Builder) 55 } 56 57 func validateBuilder(ctx *validation.Context, cfg *configpb.Builder) { 58 ctx.Enter("builder") 59 defer ctx.Exit() 60 if cfg == nil { 61 ctx.Errorf("missing builder config") 62 return 63 } 64 if cfg.Project == "" { 65 ctx.Errorf("missing project") 66 } 67 if cfg.Bucket == "" { 68 ctx.Errorf("missing bucket") 69 } 70 if cfg.Builder == "" { 71 ctx.Errorf("missing builder") 72 } 73 } 74 75 // Validates the settings in a GerritConfig 76 func validateGerritConfig(ctx *validation.Context, cfg *configpb.GerritConfig) { 77 ctx.Enter("gerrit_config") 78 defer ctx.Exit() 79 80 if cfg.CreateRevertSettings == nil { 81 ctx.Errorf("missing config for creating reverts") 82 return 83 } 84 if cfg.SubmitRevertSettings == nil { 85 ctx.Errorf("missing config for submitting reverts") 86 return 87 } 88 validateCulpritAge(ctx, cfg.MaxRevertibleCulpritAge) 89 // TODO (nqmtuan): validate nthsection_config when we have it 90 } 91 92 // Helper to validate the maximum revertible culprit age in a GerritConfig 93 func validateCulpritAge(ctx *validation.Context, age int64) { 94 ctx.Enter("max_revertible_culprit_age") 95 defer ctx.Exit() 96 97 if age <= 0 { 98 ctx.Errorf("invalid - must be positive number of seconds") 99 } 100 } 101 102 // validateProjectConfigRaw deserializes the project-level config message 103 // and passes it through the validator. 104 func validateProjectConfigRaw(ctx *validation.Context, project, content string) *configpb.ProjectConfig { 105 // We don't validate milestone projects. 106 if IsMilestoneProject(project) { 107 return nil 108 } 109 msg := &configpb.ProjectConfig{} 110 if err := luciproto.UnmarshalTextML(content, msg); err != nil { 111 ctx.Errorf("failed to unmarshal as text proto: %s", err) 112 return nil 113 } 114 validateProjectConfig(ctx, msg) 115 return msg 116 } 117 118 func validateProjectConfig(ctx *validation.Context, cfg *configpb.ProjectConfig) { 119 validateTestAnalysisConfig(ctx, cfg.TestAnalysisConfig) 120 validateCompileAnalysisConfig(ctx, cfg.CompileAnalysisConfig) 121 }