go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/cv/internal/userhtml/cl_submission.go (about) 1 // Copyright 2021 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 userhtml 16 17 import ( 18 "fmt" 19 "strings" 20 21 "go.chromium.org/luci/cv/internal/common" 22 "go.chromium.org/luci/cv/internal/run" 23 "go.chromium.org/luci/cv/internal/run/eventpb" 24 ) 25 26 // StringifySubmissionSuccesses composes a message indicating the urls of the 27 // CLs that were just submitted, and the number of pending CLs. 28 func StringifySubmissionSuccesses(allCls []*run.RunCL, v *run.LogEntry_CLSubmitted) string { 29 var sb strings.Builder 30 currentlySubmitted := common.MakeCLIDs(v.NewlySubmittedCls...) 31 clidToURL := makeURLMap(allCls) 32 switch len(currentlySubmitted) { 33 case 0: 34 sb.WriteString("No CLs were submitted successfully") 35 case 1: 36 _, _ = fmt.Fprintf(&sb, "CL %s was submitted successfully", clidToURL[currentlySubmitted[0]]) 37 default: 38 _, _ = fmt.Fprintf(&sb, "%d CLs were submitted successfully:", len(currentlySubmitted)) 39 for _, clid := range currentlySubmitted { 40 _, _ = fmt.Fprintf(&sb, "\n * %s", clidToURL[clid]) 41 } 42 } 43 if left := len(allCls) - int(v.TotalSubmitted); left > 0 { 44 _, _ = fmt.Fprintf(&sb, "\n%d out of %d CLs are still pending", left, len(allCls)) 45 } 46 return sb.String() 47 } 48 49 // StringifySubmissionFailureReason makes a human-readable message detailing 50 // the reason for the failure of this submission. 51 func StringifySubmissionFailureReason(allCls []*run.RunCL, sc *eventpb.SubmissionCompleted) string { 52 var sb strings.Builder 53 if sc.GetFailureReason() != nil { 54 switch sc.GetFailureReason().(type) { 55 case *eventpb.SubmissionCompleted_Timeout: 56 return "Timeout" 57 case *eventpb.SubmissionCompleted_ClFailures: 58 clidToURL := makeURLMap(allCls) 59 msg, err := sFormatCLSubmissionFailures(clidToURL, sc.GetClFailures()) 60 if err != nil { 61 panic(err) 62 } 63 sb.WriteString(msg) 64 } 65 } 66 return sb.String() 67 } 68 69 func listify(cls []string) string { 70 var sb strings.Builder 71 for i, v := range cls { 72 if i == len(cls)-1 && len(cls) > 1 { 73 sb.WriteString(" and ") 74 } else if i > 0 { 75 sb.WriteString(", ") 76 } 77 sb.WriteString(v) 78 } 79 sb.WriteString(" ") 80 return sb.String() 81 } 82 83 // sFormatCLSubmissionFailures returns a string with the messages for cl submission failures. 84 func sFormatCLSubmissionFailures(clidToURL map[common.CLID]string, fs *eventpb.SubmissionCompleted_CLSubmissionFailures) (string, error) { 85 var sb strings.Builder 86 for i, f := range fs.GetFailures() { 87 if i > 0 { 88 sb.WriteRune('\n') 89 } 90 if _, err := fmt.Fprintf(&sb, "CL %s failed to be submitted due to '%s'", clidToURL[common.CLID(f.GetClid())], f.GetMessage()); err != nil { 91 return "", err 92 } 93 } 94 return sb.String(), nil 95 } 96 97 func makeURLMap(cls []*run.RunCL) map[common.CLID]string { 98 ret := make(map[common.CLID]string, len(cls)) 99 for _, cl := range cls { 100 ret[cl.ID] = cl.ExternalID.MustURL() 101 } 102 return ret 103 }