From 62915b246077c2354a51b3ce5db67acba46b5252 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Tue, 7 May 2019 07:23:50 -0700 Subject: [PATCH] MM-15101 Adding /jira transition (#46) * Adding /jira transition * Moving transitionJiraIssue to a better home. --- server/command.go | 19 ++++++++++++++++++- server/issue.go | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/server/command.go b/server/command.go index 16a6612d0..a4449606b 100644 --- a/server/command.go +++ b/server/command.go @@ -13,6 +13,7 @@ import ( const helpText = "###### Mattermost Jira Plugin - Slash Command Help\n" + "* `/jira connect` - Connect your Mattermost account to your Jira account and subscribe to events\n" + "* `/jira disconnect` - Disonnect your Mattermost account from your Jira account\n" + + "* `/jira transition ` - Changes the state of a Jira issue.\n" + "* `/jira instance [add/list/select/delete]` - Manage connected Jira instances\n" + " * `add server ` - Add a Jira Server instance\n" + " * `add cloud` - Add a Jira Cloud instance\n" + @@ -27,7 +28,7 @@ func getCommand() *model.Command { DisplayName: "Jira", Description: "Integration with Jira.", AutoComplete: true, - AutoCompleteDesc: "Available commands: connect, disconnect, help", + AutoCompleteDesc: "Available commands: connect, disconnect, transition, instance, help", AutoCompleteHint: "[command]", } } @@ -49,6 +50,8 @@ func (p *Plugin) ExecuteCommand(c *plugin.Context, commandArgs *model.CommandArg return executeDisconnect(p, c, args), nil case "instance": return executeInstance(p, c, args), nil + case "transition": + return executeTransition(p, c, args, commandArgs.UserId), nil } return responsef("Action %v is not supported.", action), nil @@ -250,6 +253,20 @@ func executeInstanceDelete(p *Plugin, c *plugin.Context, args ...string) *model. return executeInstanceSelect(p, c, "1") } +func executeTransition(p *Plugin, c *plugin.Context, args []string, userId string) *model.CommandResponse { + if len(args) < 2 { + return responsef("Please specify both an issue key and state in the form `/jira transition `") + } + issueKey := args[0] + toState := strings.Join(args[1:], " ") + + if err := p.transitionJiraIssue(userId, issueKey, toState); err != nil { + return responsef("%v", err) + } + + return responsef("Transition completed.") +} + func responsef(format string, args ...interface{}) *model.CommandResponse { return &model.CommandResponse{ ResponseType: model.COMMAND_RESPONSE_TYPE_EPHEMERAL, diff --git a/server/issue.go b/server/issue.go index 6c38dea36..3100a3681 100644 --- a/server/issue.go +++ b/server/issue.go @@ -8,6 +8,7 @@ import ( "encoding/json" "fmt" "net/http" + "strings" "github.com/andygrunwald/go-jira" "github.com/pkg/errors" @@ -179,3 +180,47 @@ func httpAPIGetCreateIssueMetadata(ji Instance, w http.ResponseWriter, r *http.R return http.StatusOK, nil } + +func (p *Plugin) transitionJiraIssue(mmUserId, issueKey, toState string) error { + ji, err := p.LoadCurrentJIRAInstance() + if err != nil { + return err + } + + jiraUser, err := ji.GetPlugin().LoadJIRAUser(ji, mmUserId) + if err != nil { + return err + } + + jiraClient, err := ji.GetJIRAClient(jiraUser) + if err != nil { + return err + } + + transitions, _, err := jiraClient.Issue.GetTransitions(issueKey) + if err != nil { + return fmt.Errorf("We couldn't find the issue key. Please confirm the issue key and try again. You may not have permissions to access this issue.") + } + + if len(transitions) < 1 { + return fmt.Errorf("You do not have the appropriate permissions to perform this action. Please contact your Jira administrator.") + } + + var transitionToUse *jira.Transition + for _, transition := range transitions { + if strings.Contains(strings.ToLower(transition.To.Name), strings.ToLower(toState)) { + transitionToUse = &transition + break + } + } + + if transitionToUse == nil { + return fmt.Errorf("We couldn't find the state. Please use a Jira state such as 'done' and try again.") + } + + if _, err := jiraClient.Issue.DoTransition(issueKey, transitionToUse.ID); err != nil { + return err + } + + return nil +}