diff --git a/README.md b/README.md index 1583db2..eb73589 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,7 @@ Head to the [releases page](https://github.com/rickschubert/jira-ticket/releases ## Setup - Copy the file [.jiraticketcreator](https://github.com/rickschubert/jira-ticket/blob/master/.jiraticketcreator) into your home directory (`~`). Fill in your Jira user name, user ID, API Key and base URL. You can find out [how to create an API Key here](https://confluence.atlassian.com/cloud/api-tokens-938839638.html). You can see your user ID if you set yourself as a reporter of an issue in Jira and then inspect the network request that has been made. -# How to run it - +# Creating a new ticket * Option A: Run `./jira-ticket [shortcut]` to parse a complete Jira ticket *from your clipboard*, which assumes the following format: ``` @@ -35,6 +34,10 @@ What shortcuts you can use is determined by the `SHORTCUTS` section in your `~/. } ``` +## Flags +- `--self-assign` or `--self`: assigns the created Jira ticket to yourself +- `--sdet-bot`: Create a tray known issue notification for that new Jira ticket + # Development - `go get` gets all dependencies, using go modules - Run all the tests with `make test` diff --git a/jira/jira.go b/jira/jira.go index e09ae0f..919a83e 100644 --- a/jira/jira.go +++ b/jira/jira.go @@ -49,7 +49,7 @@ type paragraphContent struct { type content struct { Type string `json:"type"` - Content []paragraphContent `json:"content"` + Content []paragraphContent `json:"content,omitempty"` } type ticketDescription struct { @@ -191,7 +191,7 @@ func CreateNewTicket(input CreateNewticketInput) NewTicket { utils.HandleErrorStrictly(err) if resp.StatusCode() != 201 { - panic(fmt.Sprintf("We were expecting status code 201 but instead received %v. The response says:\n\n%v", resp.StatusCode(), resp)) + panic(fmt.Sprintf("We were expecting status code 201 but instead received %v when creating the ticket. The response says:\n\n%v", resp.StatusCode(), resp)) } var ticket NewTicket diff --git a/jira/selfAssign.go b/jira/selfAssign.go new file mode 100644 index 0000000..49450f7 --- /dev/null +++ b/jira/selfAssign.go @@ -0,0 +1,35 @@ +package jira + +import ( + "encoding/json" + "fmt" + + "github.com/rickschubert/jira-ticket/constants" + "github.com/rickschubert/jira-ticket/utils" +) + +type assignTicketPostBody struct { + AccountId string `json:"accountId"` +} + +func SelfAssignTicket(ticketInfo NewTicket) { + settings := constants.GetSettings() + postBody := assignTicketPostBody{ + AccountId: settings.UserId, + } + + inputJson, errMarshalling := json.MarshalIndent(postBody, "", " ") + utils.HandleErrorStrictly(errMarshalling) + + resp, err := requestClient.R(). + SetBasicAuth(settings.UserName, settings.ApiKey). + SetHeader("Content-Type", "application/json"). + SetHeader("Accept", "application/json"). + SetBody(string(inputJson)). + Put(fmt.Sprintf("%s/rest/api/3/issue/%s/assignee", settings.JiraBaseUrl, ticketInfo.Key)) + utils.HandleErrorStrictly(err) + + if resp.StatusCode() != 204 { + panic(fmt.Sprintf("We were expecting status code 204 but instead received %v when self-assigning the ticket. The response says:\n\n%v", resp.StatusCode(), resp)) + } +} diff --git a/main.go b/main.go index 57a061f..ac7487c 100644 --- a/main.go +++ b/main.go @@ -29,7 +29,7 @@ type knownIssuesWorkflowInputSchema struct { } func openLinkInBrowser(link string) { - color.Green(fmt.Sprintf("Your new ticket has been successfully created! The link is %s \nWe will now try to open it for you in the browser. (Probably doesn't work on Windows.)", link)) + color.Green(fmt.Sprintf("Your new ticket has been successfully created! The link is %s \nWe will now try to open the new ticket for you in the browser. (Probably doesn't work on Windows.)", link)) cmd := exec.Command("open", link) cmd.Run() } @@ -40,6 +40,7 @@ type cliArgs struct { ticketDescription string parseFromClipboard bool createKnownSDETBugNotification bool + selfAssign bool } func shouldUseClipboardContentAsDescription(args []string) bool { @@ -102,6 +103,12 @@ func getTicketDescription(args []string) string { } } +func shouldSelfAssignTicket(args []string) bool { + _, foundShort := utils.Find(args, "--self") + _, foundLong := utils.Find(args, "--self-assign") + return foundShort || foundLong +} + func validateCommandLineArguments() cliArgs { var cliArgumentsPassed = cliArgs{} @@ -115,6 +122,7 @@ func validateCommandLineArguments() cliArgs { cliArgumentsPassed.ticketDescription = getTicketDescription(args) cliArgumentsPassed.parseFromClipboard = shouldUseClipboardContentAsDescription(args) cliArgumentsPassed.createKnownSDETBugNotification = shouldCreateKnownSDETBugNotification(args) + cliArgumentsPassed.selfAssign = shouldSelfAssignTicket(args) return cliArgumentsPassed } @@ -205,28 +213,36 @@ func createKnownSdetBugNotification(bugInfo knownIssuesWorkflowInputSchema) { color.Green("We have sent off a new SDET notification for this, thanks!") } -func main() { - cliArgsPassed := validateCommandLineArguments() - clipboardContent := getClipboardContent() - +func getNewTicketInput(cliArgsPassed cliArgs, clipboardContent string) jira.CreateNewticketInput { var newTicketInfo jira.CreateNewticketInput newTicketInfo.Labels = cliArgsPassed.project.Labels newTicketInfo.ProjectId = cliArgsPassed.project.Id newTicketInfo.IssueType = cliArgsPassed.project.IssueType + title, description := getTicketTitleAndDescription(cliArgsPassed, clipboardContent) + newTicketInfo.Title = title + newTicketInfo.Description = description + + return newTicketInfo +} + +func main() { + cliArgsPassed := validateCommandLineArguments() + clipboardContent := getClipboardContent() if cliArgsPassed.parseFromClipboard { showClipboardAndAskIfOkay(clipboardContent) } - title, description := getTicketTitleAndDescription(cliArgsPassed, clipboardContent) - newTicketInfo.Title = title - newTicketInfo.Description = description + newTicketInput := getNewTicketInput(cliArgsPassed, clipboardContent) + ticketInfo := jira.CreateNewTicket(newTicketInput) + if cliArgsPassed.selfAssign { + jira.SelfAssignTicket(ticketInfo) + } - ticketInfo := jira.CreateNewTicket(newTicketInfo) openLinkInBrowser(ticketInfo.Link) if cliArgsPassed.createKnownSDETBugNotification { - bugInfo := collectInformationToCreateKnownSdetBugNotification(ticketInfo.Key, newTicketInfo.Title, newTicketInfo.Description) + bugInfo := collectInformationToCreateKnownSdetBugNotification(ticketInfo.Key, newTicketInput.Title, newTicketInput.Description) createKnownSdetBugNotification(bugInfo) } } diff --git a/validatingPassedArguments_test.go b/validatingPassedArguments_test.go index 46b9c17..8adc543 100644 --- a/validatingPassedArguments_test.go +++ b/validatingPassedArguments_test.go @@ -37,6 +37,7 @@ func (suite *testSuite) TestArgsRegularInvokingAndAttachingClipboardContentToDes parseFromClipboard: false, ticketTitle: "this will be the title", createKnownSDETBugNotification: false, + selfAssign: false, } os.Args = []string{"jira-ticket", "embedded", "this will be the title"} @@ -56,6 +57,7 @@ func (suite *testSuite) TestArgsRegularInvoking() { parseFromClipboard: false, ticketTitle: "this will be the title", createKnownSDETBugNotification: false, + selfAssign: false, } os.Args = []string{"jira-ticket", "embedded", "this will be the title"} @@ -75,12 +77,49 @@ func (suite *testSuite) TestArgsShouldCreateKnownSDETNotification() { parseFromClipboard: true, ticketTitle: "", createKnownSDETBugNotification: true, + selfAssign: false, } os.Args = []string{"jira-ticket", "embedded", "--sdet-bot"} actual := validateCommandLineArguments() assert.Equal(suite.T(), expected, actual) } +func (suite *testSuite) TestArgsShouldCreateKnownSDETNotificationAndSelfAssign() { + expected := cliArgs{ + project: constants.Project{ + Shortcut: "embedded", + Id: "10059", + IssueType: "10004", + Labels: []string(nil), + }, + parseFromClipboard: true, + ticketTitle: "", + createKnownSDETBugNotification: true, + selfAssign: true, + } + os.Args = []string{"jira-ticket", "embedded", "--sdet-bot", "--self"} + actual := validateCommandLineArguments() + assert.Equal(suite.T(), expected, actual) +} + +func (suite *testSuite) TestArgsShouldCreateKnownSDETNotificationAndSelfAssignLong() { + expected := cliArgs{ + project: constants.Project{ + Shortcut: "embedded", + Id: "10059", + IssueType: "10004", + Labels: []string(nil), + }, + parseFromClipboard: true, + ticketTitle: "", + createKnownSDETBugNotification: true, + selfAssign: true, + } + os.Args = []string{"jira-ticket", "embedded", "--sdet-bot", "--self-assign"} + actual := validateCommandLineArguments() + assert.Equal(suite.T(), expected, actual) +} + func (suite *testSuite) TestArgsShouldParseFullTicketFromClipboard() { expected := cliArgs{ project: constants.Project{ @@ -92,6 +131,7 @@ func (suite *testSuite) TestArgsShouldParseFullTicketFromClipboard() { parseFromClipboard: true, ticketTitle: "", createKnownSDETBugNotification: false, + selfAssign: false, } os.Args = []string{"jira-ticket", "embedded"} actual := validateCommandLineArguments() @@ -109,6 +149,7 @@ func (suite *testSuite) TestArgsShouldParseFullTicketFromClipboardAndCreateKnown parseFromClipboard: true, ticketTitle: "", createKnownSDETBugNotification: true, + selfAssign: false, } os.Args = []string{"jira-ticket", "embedded", "--sdet-bot"} actual := validateCommandLineArguments() @@ -126,6 +167,7 @@ func (suite *testSuite) TestArgsShouldParseFullTicketFromClipboardAndCreateKnown parseFromClipboard: true, ticketTitle: "", createKnownSDETBugNotification: true, + selfAssign: false, } os.Args = []string{"jira-ticket", "embedded", "--sdet-bot"} actual := validateCommandLineArguments() @@ -143,6 +185,7 @@ func (suite *testSuite) TestTicketTitleAndDescriptionRetrievalWithoutTakingClipb Labels: []string(nil), }, createKnownSDETBugNotification: false, + selfAssign: false, } clipboardContent := "" title, description := getTicketTitleAndDescription(cliArgumentsRetrieved, clipboardContent) @@ -161,6 +204,7 @@ func (suite *testSuite) TestParsingTicketTitleAndDescriptionFromClipboard() { Labels: []string(nil), }, createKnownSDETBugNotification: false, + selfAssign: false, } clipboardContent := "This will be the title\n\nThis will be the description" title, description := getTicketTitleAndDescription(cliArgumentsRetrieved, clipboardContent)