go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/bisection/culpritaction/revertculprit/commitrevert.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 revertculprit 16 17 import ( 18 "context" 19 "time" 20 21 "go.chromium.org/luci/bisection/internal/config" 22 "go.chromium.org/luci/bisection/internal/gerrit" 23 "go.chromium.org/luci/bisection/internal/rotationproxy" 24 "go.chromium.org/luci/bisection/model" 25 bisectionpb "go.chromium.org/luci/bisection/proto/v1" 26 27 "go.chromium.org/luci/common/errors" 28 "go.chromium.org/luci/common/logging" 29 gerritpb "go.chromium.org/luci/common/proto/gerrit" 30 ) 31 32 // canCommit returns: 33 // - whether a revert for the culprit CL can be committed; 34 // - the reason a revert should not be committed if applicable; and 35 // - the error if one occurred. 36 func canCommit(ctx context.Context, culprit *gerritpb.ChangeInfo, culpritModel *model.Suspect, project string) (bool, string, error) { 37 // TODO(beining@): remove this when revert CL support has been added for test failure. 38 if culpritModel.AnalysisType == bisectionpb.AnalysisType_TEST_FAILURE_ANALYSIS { 39 return false, "LUCI Bisection has not yet support auto-commit of revert CL for test failure", nil 40 } 41 // Get gerrit config. 42 gerritConfig, err := config.GetGerritCfgForSuspect(ctx, culpritModel, project) 43 if err != nil { 44 return false, "", errors.Annotate(err, "error get gerrit config").Err() 45 } 46 47 // Check if the culprit was committed recently 48 maxAge := time.Duration(gerritConfig.MaxRevertibleCulpritAge) * time.Second 49 if !gerrit.IsRecentSubmit(ctx, culprit, maxAge) { 50 // culprit was not submitted recently, so the revert should not be 51 // automatically submitted 52 return false, "the target of this revert was not committed recently", nil 53 } 54 55 // Check if LUCI Bisection's Gerrit config allows revert submission 56 canSubmit, reason, err := config.CanSubmitRevert(ctx, gerritConfig) 57 if err != nil { 58 return false, "", errors.Annotate(err, "error checking Submit Revert configs").Err() 59 } 60 if !canSubmit { 61 // cannot submit revert based on config 62 return false, reason, nil 63 } 64 65 // We can only proceed to commit if it is a confirmed culprit 66 // This is for the case that a we may create a revert on verification error of an 67 // nthsection suspect. But we definitely don't want to auto submit the revert. 68 if culpritModel.VerificationStatus != model.SuspectVerificationStatus_ConfirmedCulprit { 69 return false, "the suspect is not verified", nil 70 } 71 return true, "", nil 72 } 73 74 // commitRevert attempts to bot-commit the given revert. 75 // Note: this should only be called according to the service-wide configuration 76 // data for LUCI Bisection, i.e. 77 // - Gerrit actions are enabled 78 // - Submitting reverts is enabled 79 // - the daily limit of submitted reverts has not yet been reached 80 // - the culprit is not yet older than the maximum revertible culprit age 81 func commitRevert(ctx context.Context, gerritClient *gerrit.Client, 82 culpritModel *model.Suspect, revert *gerritpb.ChangeInfo) error { 83 // CC on-call arborists 84 ccEmails, err := rotationproxy.GetOnCallEmails(ctx, 85 culpritModel.GitilesCommit.Project) 86 if err != nil { 87 // non-critical, just log the error 88 err = errors.Annotate(err, "failed getting accounts to CC on bot-commit").Err() 89 logging.Errorf(ctx, err.Error()) 90 } 91 92 _, err = gerritClient.CommitRevert(ctx, revert, 93 "LUCI Bisection is automatically submitting this revert.", ccEmails) 94 return err 95 }