...

Source file src/edge-infra.dev/pkg/f8n/devinfra/jack/plugin/triage_issue/issue.go

Documentation: edge-infra.dev/pkg/f8n/devinfra/jack/plugin/triage_issue

     1  package triageissue
     2  
     3  import (
     4  	"net/http"
     5  	"regexp"
     6  	"strconv"
     7  	"strings"
     8  
     9  	"github.com/google/go-github/v47/github"
    10  
    11  	"edge-infra.dev/pkg/f8n/devinfra/jack/constants"
    12  	guestservices "edge-infra.dev/pkg/f8n/devinfra/jack/guest_services"
    13  	"edge-infra.dev/pkg/f8n/devinfra/jack/plugin"
    14  )
    15  
    16  var (
    17  	// LabelApplied is a check to see if triage/needs-issue is already present on the PR
    18  	labelApplied bool
    19  	check        bool
    20  )
    21  
    22  const ghURL = "https://github.com/"
    23  
    24  // checkForIssueInPR triggered when the PR is created. The function will scan the body and determine
    25  // if the triage/needs-issue needs to be included or removed
    26  func checkForIssueInPR(hp plugin.HandlerParams, event github.PullRequestEvent) error {
    27  	// if a bot added a label we don't want to handle it twice
    28  	if event.GetSender().GetType() == constants.Bot {
    29  		return nil
    30  	}
    31  
    32  	body := event.GetPullRequest().GetBody()
    33  
    34  	linkNum, _ := guestservices.ParsePRIssueLinkBody(body)
    35  	labelCheck := labelCheck(body, linkNum)
    36  
    37  	switch {
    38  	case labelCheck:
    39  		hp.Log.Info("adding needs-issue label")
    40  		newLabels := []string{constants.TriageIssueLabel}
    41  		labelApplied = true
    42  		_, _, err := hp.Client.Issues().AddLabelsToIssue(hp.Ctx, hp.Org, hp.Repo, event.PullRequest.GetNumber(), newLabels)
    43  		if err != nil {
    44  			return err
    45  		}
    46  	case !labelCheck:
    47  		_, err := http.Get(ghURL + constants.Address + linkNum)
    48  		if err != nil {
    49  			return err
    50  		}
    51  		hp.Log.Info("removing needs issue label")
    52  		labelApplied = false
    53  		err = removeTriageLabel(hp, event)
    54  		if err != nil {
    55  			return err
    56  		}
    57  		err = addIssueNumberToTitle(hp, event, linkNum, event.GetPullRequest().GetTitle())
    58  		if err != nil {
    59  			return err
    60  		}
    61  	}
    62  	return nil
    63  }
    64  
    65  // labelCheck returns true when anything in the relevant issue is incorrect
    66  func labelCheck(body, linkNum string) bool {
    67  	_, err := strconv.Atoi(linkNum)
    68  
    69  	if body == "" || linkNum == "" || linkNum == "ISSUE_NUMBER_HERE" || linkNum[0:1] == "0" || err != nil {
    70  		check = true
    71  	} else {
    72  		check = false
    73  	}
    74  	return check
    75  }
    76  
    77  // addLabel is triggered whenever a user manually adds the triage/needs-issue label
    78  func addLabel(hp plugin.HandlerParams, event github.PullRequestEvent) error {
    79  	// if a bot added a label we don't want to handle it twice
    80  	if event.GetSender().GetType() == constants.Bot {
    81  		return nil
    82  	}
    83  
    84  	hp.Log.Info("add triage/needs_issue")
    85  
    86  	body := event.GetPullRequest().GetBody()
    87  	linkNum, _ := guestservices.ParsePRIssueLinkBody(body)
    88  
    89  	if !labelCheck(body, linkNum) {
    90  		hp.Log.Info("Link exists. Removing label again.")
    91  		return removeLabel(hp, event)
    92  	}
    93  
    94  	if labelCheck(body, linkNum) {
    95  		hp.Log.Info("adding needs-issue label")
    96  		newLabels := []string{constants.TriageIssueLabel}
    97  		labelApplied = true
    98  		_, _, err := hp.Client.Issues().AddLabelsToIssue(hp.Ctx, hp.Org, hp.Repo, event.PullRequest.GetNumber(), newLabels)
    99  		if err != nil {
   100  			return err
   101  		}
   102  	}
   103  
   104  	return nil
   105  }
   106  
   107  // removeLabel is triggered whenever the user manually removes the triage/needs-issue label
   108  func removeLabel(hp plugin.HandlerParams, event github.PullRequestEvent) error {
   109  	// if a bot added a label we don't want to handle it twice
   110  	if event.GetSender().GetType() == constants.Bot {
   111  		return nil
   112  	}
   113  	hp.Log.Info("remove triage/needs_issue")
   114  
   115  	body := event.GetPullRequest().GetBody()
   116  	linkNum, _ := guestservices.ParsePRIssueLinkBody(body)
   117  
   118  	if labelCheck(body, linkNum) {
   119  		hp.Log.Info("Link does not exist. Adding label back")
   120  		return addLabel(hp, event)
   121  	}
   122  
   123  	_, err := http.Get(ghURL + constants.Address + linkNum)
   124  	if err != nil {
   125  		return err
   126  	}
   127  	hp.Log.Info("removing needs-issue label")
   128  	labelApplied = false
   129  	err = removeTriageLabel(hp, event)
   130  	if err != nil {
   131  		return err
   132  	}
   133  	return nil
   134  }
   135  
   136  // editedPRBody is called whenever the main PR comment body is altered.
   137  // It runs through checks to determine how the body was changed and then applies/removes the label.
   138  func editedPRBody(hp plugin.HandlerParams, event github.PullRequestEvent) error {
   139  	// if a bot added a label we don't want to handle it twice
   140  	if event.GetSender().GetType() == constants.Bot {
   141  		return nil
   142  	}
   143  
   144  	body := event.GetPullRequest().GetBody()
   145  	linkNum, _ := guestservices.ParsePRIssueLinkBody(body)
   146  	doesNotHaveIssue := labelCheck(body, linkNum)
   147  
   148  	// LabelApplied returns true if the label is already present on the PR
   149  	// doesNotHaveIssue returns true if there isn't a correct issue in the PR
   150  	switch {
   151  	case labelApplied && !doesNotHaveIssue:
   152  		_, err := http.Get(ghURL + constants.Address + linkNum)
   153  		if err != nil {
   154  			return err
   155  		}
   156  		labelApplied = false
   157  		hp.Log.Info("removing needs-issue label")
   158  		err = removeTriageLabel(hp, event)
   159  		if err != nil {
   160  			return err
   161  		}
   162  		if !isIssueNumberInTitle(event.GetPullRequest().GetTitle()) {
   163  			err = addIssueNumberToTitle(hp, event, linkNum, event.GetPullRequest().GetTitle())
   164  			if err != nil {
   165  				return err
   166  			}
   167  		}
   168  	case !labelApplied && doesNotHaveIssue:
   169  		if labelCheck(body, linkNum) {
   170  			newLabels := []string{constants.TriageIssueLabel}
   171  			labelApplied = true
   172  			hp.Log.Info("adding needs-issue label")
   173  			_, _, err := hp.Client.Issues().AddLabelsToIssue(hp.Ctx, hp.Org, hp.Repo, event.PullRequest.GetNumber(), newLabels)
   174  			if err != nil {
   175  				return err
   176  			}
   177  		}
   178  	case !doesNotHaveIssue:
   179  		// compare the issue number to the title if same no change if different, update
   180  		if compareTitleNumberToBody(event.GetPullRequest().GetTitle(), linkNum) != 0 {
   181  			err := updateIssueNumberInTitle(hp, event, linkNum, event.GetPullRequest().GetTitle())
   182  			if err != nil {
   183  				return err
   184  			}
   185  		}
   186  	}
   187  	return nil
   188  }
   189  
   190  // remove the triage issue label if it exists in the prs labels
   191  func removeTriageLabel(hp plugin.HandlerParams, pre github.PullRequestEvent) error {
   192  	for _, x := range pre.PullRequest.Labels {
   193  		if x.GetName() == constants.TriageIssueLabel {
   194  			_, err := hp.Client.Issues().RemoveLabelForIssue(hp.Ctx, hp.Org, hp.Repo, pre.PullRequest.GetNumber(), constants.TriageIssueLabel)
   195  			if err != nil {
   196  				return err
   197  			}
   198  			break
   199  		}
   200  	}
   201  
   202  	return nil
   203  }
   204  
   205  // append issue number to title
   206  func addIssueNumberToTitle(hp plugin.HandlerParams, pre github.PullRequestEvent, linkNum string, title string) error {
   207  	githubIssueBody := &github.IssueRequest{Title: github.String(linkNum + ": " + title)}
   208  	_, _, err := hp.Client.Issues().Edit(hp.Ctx, hp.Org, hp.Repo, pre.PullRequest.GetNumber(), githubIssueBody)
   209  	if err != nil {
   210  		return err
   211  	}
   212  	return nil
   213  }
   214  
   215  // append issue number to title
   216  func updateIssueNumberInTitle(hp plugin.HandlerParams, pre github.PullRequestEvent, linkNum string, title string) error {
   217  	r := regexp.MustCompile(`(\d+):\s*(.*)`)
   218  	matches := r.FindStringSubmatch(title)
   219  	githubIssueBody := &github.IssueRequest{Title: github.String(linkNum + ": " + matches[2])}
   220  	_, _, err := hp.Client.Issues().Edit(hp.Ctx, hp.Org, hp.Repo, pre.PullRequest.GetNumber(), githubIssueBody)
   221  	if err != nil {
   222  		return err
   223  	}
   224  	return nil
   225  }
   226  
   227  // checks if an issue number already exists within the title
   228  func isIssueNumberInTitle(title string) bool {
   229  	r := regexp.MustCompile(`[0-9]+:`)
   230  	return len(r.FindStringSubmatch(title)) > 0
   231  }
   232  
   233  func compareTitleNumberToBody(title string, linkNum string) int {
   234  	r := regexp.MustCompile(`(\d+):\s*(.*)`)
   235  	matches := r.FindStringSubmatch(title)
   236  	return strings.Compare(matches[1], linkNum)
   237  }
   238  

View as plain text