// VerifyBugs takes a list of bugzilla bug IDs and for each bug changes the bug status to VERIFIED if bug was reviewed and
// lgtm'd by the bug's QA Contect
VerifyBugs takes a list of bugzilla bug IDs and for each bug changes the bug status to VERIFIED if bug was reviewed and
lgtm'd by the bug's QA Contect
// VerifyBugs takes a list of bugzilla bug IDs and for each bug changes the bug status to VERIFIED if bug was reviewed and // lgtm ' d by the bug ' s QA Contect
func (c *Verifier) VerifyBugs(bugs []int, tagName string) []error {
	tagSemVer, err := releasecontroller.SemverParseTolerant(tagName)
	if err != nil {
		return []error{fmt.Errorf("failed to parse tag `%s` semver: %w", tagName, err)}
	}
	tagRelease := releasecontroller.SemverToMajorMinor(tagSemVer)
	bzPRs, errs := getPRs(bugs, c.bzClient)
	for bugID, extPRs := range bzPRs {
		bug, err := c.bzClient.GetBug(bugID)
		if err != nil {
			errs = append(errs, fmt.Errorf("Unable to get bugzilla number %d: %v", bugID, err))
			continue
		}
		if len(bug.TargetRelease) == 0 || bug.TargetRelease[0] == "---" {
			klog.Warningf("Bug %d does not have a target release", bug.ID)
			continue
		}
		bugSplitVer := strings.Split(bug.TargetRelease[0], ".")
		if len(bugSplitVer) < 2 {
			errs = append(errs, fmt.Errorf("Bug %d: length of target release `%s` after split by `.` is less than 2", bug.ID, bug.TargetRelease[0]))
			continue
		}
		bugRelease := fmt.Sprintf("%s.%s", bugSplitVer[0], bugSplitVer[1])
		if bugRelease != tagRelease {
			klog.Infof("Bug %d is in different release (%s) than tag %s", bug.ID, bugRelease, tagName)
			continue
		}
		var success bool
		message := fmt.Sprintf("Bugfix included in accepted release %s", tagName)
		var unlabeledPRs []pr
		var bugErrs []error
		if bug.Status != "ON_QA" {
			if bug.Status == "VERIFIED" {
				klog.V(4).Infof("Bug %d already in VERIFIED status", bug.ID)
				continue
			} else {
				bugErrs = append(bugErrs, fmt.Errorf("Bug is not in ON_QA status"))
			}
		} else {
			for _, extPR := range extPRs {
				labels, err := c.ghClient.GetIssueLabels(extPR.org, extPR.repo, extPR.prNum)
				if err != nil {
					newErr := fmt.Errorf("Unable to get labels for github pull %s/%s#%d: %v", extPR.org, extPR.repo, extPR.prNum, err)
					errs = append(errs, newErr)
					bugErrs = append(bugErrs, newErr)
				}
				var hasLabel bool
				for _, label := range labels {
					if label.Name == "qe-approved" {
						hasLabel = true
						break
					}
				}
				if !hasLabel {
					unlabeledPRs = append(unlabeledPRs, extPR)
				}
			}
		}
		if len(unlabeledPRs) > 0 || len(bugErrs) > 0 {
			message = fmt.Sprintf("%s\nBug will not be automatically moved to VERIFIED for the following reasons:", message)
			for _, extPR := range unlabeledPRs {
				message = fmt.Sprintf("%s\n- PR %s/%s#%d not approved by QA contact", message, extPR.org, extPR.repo, extPR.prNum)
			}
			for _, err := range bugErrs {
				message = fmt.Sprintf("%s\n- %s", message, err)
			}
			message = fmt.Sprintf("%s\n\nThis bug must now be manually moved to VERIFIED", message)
			if bug.QAContactDetail != nil {
				message = fmt.Sprintf("%s by %s", message, bug.QAContactDetail.Name)
			}
		} else {
			success = true
		}
		if success {
			message = fmt.Sprintf("%s\nAll linked GitHub PRs have been approved by a QA contact; updating bug status to VERIFIED", message)
		}
		if message != "" {
			comments, err := c.bzClient.GetComments(bugID)
			if err != nil {
				errs = append(errs, fmt.Errorf("Failed to get comments on bug %d: %v", bug.ID, err))
				continue
			}
			var alreadyCommented bool
			for _, comment := range comments {
				if comment.Text == message && (comment.Creator == "openshift-bugzilla-robot" || comment.Creator == "openshift-bugzilla-robot@redhat.com") {
					alreadyCommented = true
					break
				}
			}
			if !alreadyCommented {
				if _, err := c.bzClient.CreateComment(&bugzilla.CommentCreate{ID: bugID, Comment: message, IsPrivate: true}); err != nil {
					errs = append(errs, fmt.Errorf("Failed to comment on bug %d: %v", bug.ID, err))
				}
			}
		}
		if success {
			klog.V(4).Infof("Updating bug %d (current status %s) to VERIFIED status", bug.ID, bug.Status)
			if err := c.bzClient.UpdateBug(bug.ID, bugzilla.BugUpdate{Status: "VERIFIED"}); err != nil {
				errs = append(errs, fmt.Errorf("Failed to update status for bug %d: %v", bug.ID, err))
			}
		} else {
			klog.V(4).Infof("Bug %d (current status %s) not approved by QA contact", bug.ID, bug.Status)
		}
	}
	return errs
}
func ( c * Verifier ) VerifyBugs ( bugs [ ] int , tagName string ) [ ] error { tagSemVer , err := releasecontroller . SemverParseTolerant ( tagName ) if err != nil { return [ ] error { fmt . Errorf ( " " , tagName , err ) } } tagRelease := releasecontroller . SemverToMajorMinor ( tagSemVer ) bzPRs , errs := getPRs ( bugs , c . bzClient ) for bugID , extPRs := range bzPRs { bug , err := c . bzClient . GetBug ( bugID ) if err != nil { errs = append ( errs , fmt . Errorf ( " " , bugID , err ) ) continue } if len ( bug . TargetRelease ) == 0 || bug . TargetRelease [ 0 ] == " " { klog . Warningf ( " " , bug . ID ) continue } bugSplitVer := strings . Split ( bug . TargetRelease [ 0 ] , " " ) if len ( bugSplitVer ) < 2 { errs = append ( errs , fmt . Errorf ( " " , bug . ID , bug . TargetRelease [ 0 ] ) ) continue } bugRelease := fmt . Sprintf ( " " , bugSplitVer [ 0 ] , bugSplitVer [ 1 ] ) if bugRelease != tagRelease { klog . Infof ( " " , bug . ID , bugRelease , tagName ) continue } var success bool message := fmt . Sprintf ( " " , tagName ) var unlabeledPRs [ ] pr var bugErrs [ ] error if bug . Status != " " { if bug . Status == " " { klog . V ( 4 ) . Infof ( " " , bug . ID ) continue } else { bugErrs = append ( bugErrs , fmt . Errorf ( " " ) ) } } else { for _ , extPR := range extPRs { labels , err := c . ghClient . GetIssueLabels ( extPR . org , extPR . repo , extPR . prNum ) if err != nil { newErr := fmt . Errorf ( " " , extPR . org , extPR . repo , extPR . prNum , err ) errs = append ( errs , newErr ) bugErrs = append ( bugErrs , newErr ) } var hasLabel bool for _ , label := range labels { if label . Name == " " { hasLabel = true break } } if ! hasLabel { unlabeledPRs = append ( unlabeledPRs , extPR ) } } } if len ( unlabeledPRs ) > 0 || len ( bugErrs ) > 0 { message = fmt . Sprintf ( " \n " , message ) for _ , extPR := range unlabeledPRs { message = fmt . Sprintf ( " \n " , message , extPR . org , extPR . repo , extPR . prNum ) } for _ , err := range bugErrs { message = fmt . Sprintf ( " \n " , message , err ) } message = fmt . Sprintf ( " \n \n " , message ) if bug . QAContactDetail != nil { message = fmt . Sprintf ( " " , message , bug . QAContactDetail . Name ) } } else { success = true } if success { message = fmt . Sprintf ( " \n " , message ) } if message != " " { comments , err := c . bzClient . GetComments ( bugID ) if err != nil { errs = append ( errs , fmt . Errorf ( " " , bug . ID , err ) ) continue } var alreadyCommented bool for _ , comment := range comments { if comment . Text == message && ( comment . Creator == " " || comment . Creator == " " ) { alreadyCommented = true break } } if ! alreadyCommented { if _ , err := c . bzClient . CreateComment ( & bugzilla . CommentCreate { ID : bugID , Comment : message , IsPrivate : true } ) ; err != nil { errs = append ( errs , fmt . Errorf ( " " , bug . ID , err ) ) } } } if success { klog . V ( 4 ) . Infof ( " " , bug . ID , bug . Status ) if err := c . bzClient . UpdateBug ( bug . ID , bugzilla . BugUpdate { Status : " " } ) ; err != nil { errs = append ( errs , fmt . Errorf ( " " , bug . ID , err ) ) } } else { klog . V ( 4 ) . Infof ( " " , bug . ID , bug . Status ) } } return errs }
VerifyBugs takes a list of bugzilla bug IDs and for each bug changes the bug status to VERIFIED if bug was reviewed and
lgtm'd by the bug's QA Contect
VerifyBugs takes a list of bugzilla bug IDs and for each bug changes the bug status to VERIFIED if bug was reviewed and lgtm ' d by the bug ' s QA Contect
// bugzilla usually denotes unset target releases with `---` // the format for target release is always `int.int.{0,z}` // bugfix included in different release than target; ignore // In case bug has already been moved to VERIFIED, completely ignore // Sometimes the QAContactDetail is nil; if not nil, include name of QA contact in message