package triageissue import ( "fmt" "net/http" "strings" "github.com/google/go-github/v47/github" "edge-infra.dev/pkg/f8n/devinfra/jack/constants" guestservices "edge-infra.dev/pkg/f8n/devinfra/jack/guest_services" "edge-infra.dev/pkg/f8n/devinfra/jack/plugin" ) func init() { plugin.RegisterIssueCommentHandler(constants.PluginPRIssue, handlePRComment) plugin.RegisterPullRequestHandler(constants.PluginPRIssue, handlePR) } func handlePRComment(hp plugin.HandlerParams, ice github.IssueCommentEvent) { hp.Log.WithName(constants.PluginPRIssue) if ice.GetAction() != "created" { return } if !ice.GetIssue().IsPullRequest() { return } prBody := ice.Issue.GetBody() prComment := ice.Comment.GetBody() // if the new comment doesnt have the relevant command exit if !strings.Contains(prComment, "/link") { return } issueCommand := guestservices.GetCommandsFromPRBody(prComment, "link") //LinkNum needed to isolate the relevant link in the PR body that will be changed //LastIndex is the where the linkNum is located //CommentSplit parses the comment body to separate the link //CommentLink stores the link from commentSplit linkNum, _ := guestservices.ParsePRIssueLinkBody(prBody) lastIndex := strings.LastIndex(prBody, linkNum) commentSplit := strings.SplitN(prComment, "#", -1) if len(commentSplit) < 2 { hp.Log.Info("comment doesnt have enough info to link an issue ignoring") return } commentLink := commentSplit[1] // if there is an issue command to remove issue, add label if len(issueCommand.RemoveIssue) > 0 { // Editing the PR body to include ISSUE_NUMBER_HERE at the end of the link prBody = prBody[:lastIndex] + strings.Replace(prBody[lastIndex:], linkNum, "ISSUE_NUMBER_HERE", 1) edited := github.IssueRequest{Body: &prBody} _, _, err := hp.Client.Issues().Edit(hp.Ctx, hp.Org, hp.Repo, ice.Issue.GetNumber(), &edited) if err != nil { return } // Adding the needs-issue label hp.Log.Info(fmt.Sprintf("attempting to add %s", constants.TriageIssueLabel)) newLabels := []string{constants.TriageIssueLabel} _, _, err = hp.Client.Issues().AddLabelsToIssue(hp.Ctx, hp.Org, hp.Repo, ice.Issue.GetNumber(), newLabels) if err != nil { return } labelApplied = true return } // if there is an issue command to add issue, remove label if len(issueCommand.AddIssue) > 0 { // Verifying that the new link works _, err := http.Get(ghURL + constants.Address + commentLink) if err != nil { return } // Editing the PR body to include the new link prBody = prBody[:lastIndex] + strings.Replace(prBody[lastIndex:], linkNum, commentLink, 1) edited := github.IssueRequest{Body: &prBody} _, _, err = hp.Client.Issues().Edit(hp.Ctx, hp.Org, hp.Repo, ice.Issue.GetNumber(), &edited) if err != nil { return } // Removing the needs-issue label hp.Log.Info(fmt.Sprintf("attempting to remove %s", constants.TriageIssueLabel)) _, err = hp.Client.Issues().RemoveLabelForIssue(hp.Ctx, hp.Org, hp.Repo, ice.Issue.GetNumber(), constants.TriageIssueLabel) if err != nil { return } labelApplied = false return } } // handlePR checks the log for four specific responses. // Anytime those responses appear, the appropriate function will be called. func handlePR(hp plugin.HandlerParams, pre github.PullRequestEvent) { hp.Log.WithName(constants.PluginPRIssue) action := pre.GetAction() switch action { case "opened": if err := checkForIssueInPR(hp, pre); err != nil { hp.Log.Error(err, "Issue: Failed to check for issue in PR") return } case "labeled": if err := addLabel(hp, pre); err != nil { hp.Log.Error(err, "Issue: Failed to add triage-issue label") return } case "unlabeled": if err := removeLabel(hp, pre); err != nil { hp.Log.Error(err, "Issue: Failed to remove triage-issue label") return } case "edited": if err := editedPRBody(hp, pre); err != nil { hp.Log.Error(err, "Issue: Failed to handle edited PR body") return } } }