Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

minor: Added DueDate support for creating Jira #185

Merged
merged 1 commit into from
Dec 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ dist/
jira-ticket-for-new-vulns*
ErrorsFile*
listOfTicketCreated*
.DS_Store
.idea/
21 changes: 13 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Aimed to be executed at regular interval or with a trigger of your choice (webho
**This repository is in maintenance mode, no new features are being developed. Bug & security fixes will continue to be delivered. Open source contributions are welcome for small features & fixes (no breaking changes)**

## Installation
You can either download the binaries fron the from [the release page](https://github.com/snyk-tech-services/jira-tickets-for-new-vulns/releases)
You can either download the binaries from the [the release page](https://github.com/snyk-tech-services/jira-tickets-for-new-vulns/releases)
or
Use `go install github.com/snyk-tech-services/jira-tickets-for-new-vulns@latest`

Expand Down Expand Up @@ -115,6 +115,12 @@ Use `go install github.com/snyk-tech-services/jira-tickets-for-new-vulns@latest`

*Example*: `--labels=app-1234`

- `--dueDate` *optional*

Set [Jira ticket labels](https://confluence.atlassian.com/jirasoftwareserver/editing-and-collaborating-on-issues-939938928.html)

*Example*: `--dueDate=2022-12-01`
-
- `--priorityScoreThreshold` *optional*

Your minimum [Snyk priority score](https://docs.snyk.io/features/fixing-and-prioritizing-issues/starting-to-fix-vulnerabilities/snyk-priority-score) threshold. Can be a number between `0` and `1000`.
Expand Down Expand Up @@ -183,12 +189,12 @@ The tool does not support IAC project. It will open issue only for code and open
Option to get the JIRA ticket priority set based on issue severity.
Defaults map to:

Issue severity | JIRA Priority
----- | -----
critical | Highest
high | High
medium | Medium
low | Low
| Issue severity | JIRA priority |
|:----------------:|:-------------:|
| critical | Highest |
| high | High |
| medium | Medium |
| low | Low |

Use `SNYK_JIRA_PRIORITY_FOR_XXX_VULN` env var to override the default an set your value.
> *Example*:
Expand Down Expand Up @@ -319,4 +325,3 @@ Notes:
Using the config file above, running `./snyk-jira-sync-macOs --Org=1234 --configFile=./path/to/folder --token=123`
the org ID used by the tool will be `1234` and not `a1b2c3de-99b1-4f3f-bfdb-6ee4b4990513`
- See 'Extended options' for default values

4 changes: 2 additions & 2 deletions end_to_end_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func TestEndToEndFunc(t *testing.T) {
os.Args = append(os.Args, "--jiraProjectID=123")
os.Args = append(os.Args, "--api="+server.URL)

// Keeping the line below => useful for debug but print too much things
// Keeping the line below => useful for debug but print too many things
// os.Args = append(os.Args, "-debug=true")

// Get the console output
Expand All @@ -48,7 +48,7 @@ func TestEndToEndFunc(t *testing.T) {
assert.True(t, found)

// check if the json is valid
file, err := ioutil.ReadFile(path)
file, err := os.ReadFile(path)
if err != nil {
panic(err)
}
Expand Down
5 changes: 5 additions & 0 deletions jira.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type Field struct {
Assignees *Assignee `json:"assignee,omitempty"`
Priority *PriorityType `json:"priority,omitempty"`
Labels []string `json:"labels,omitempty"`
DueDate string `json:"dueDate,omitempty"`

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be => DueDate string json:"due**d**ate,omitempty" D small letter

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to be different for you. I've been running like this for months and it matched our Jira Cloud due date field.

}

// Assignee is the account ID of the Jira user to assign tickets to
Expand Down Expand Up @@ -130,6 +131,10 @@ func openJiraTicket(flags flags, projectInfo jsn.Json, vulnForJira interface{},
jiraTicket.Fields.Labels = strings.Split(flags.optionalFlags.labels, ",")
}

if flags.optionalFlags.dueDate != "" {
jiraTicket.Fields.DueDate = flags.optionalFlags.dueDate
}

if flags.optionalFlags.assigneeID != "" {
var assignee Assignee
assignee.AccountId = flags.optionalFlags.assigneeID
Expand Down
56 changes: 56 additions & 0 deletions jira_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1047,3 +1047,59 @@ func TestOpenJiraTicketError50xAndRetryFunc(t *testing.T) {

return
}

// Test openJiraTickets function
func TestOpenJiraTicketWithDueDateFunc(t *testing.T) {
assert := assert.New(t)
server := HTTPResponseCheckOpenJiraTickets("/v1/org/123/project/12345678-1234-1234-1234-123456789012/issue/SNYK-JS-MINIMIST-559764/jira-issue")

defer server.Close()

projectInfo, _ := jsn.NewJson(readFixture("./fixtures/project.json"))
vulnsForJira := make(map[string]interface{})
err := json.Unmarshal(readFixture("./fixtures/vulnsForJira.json"), &vulnsForJira)
if err != nil {
panic(err)
}

// setting mandatory options
Mf := MandatoryFlags{}
Mf.orgID = "123"
Mf.endpointAPI = server.URL
Mf.apiToken = "123"
Mf.jiraProjectID = "123"
Mf.jiraProjectKey = ""

// setting optional options
Of := optionalFlags{}
Of.severity = ""
Of.priorityScoreThreshold = 0
Of.issueType = ""
Of.debug = false
Of.jiraTicketType = "Bug"
Of.assigneeID = ""
Of.labels = ""
Of.dueDate = "2029-01-01"
Of.priorityIsSeverity = false
Of.projectID = ""
Of.maturityFilterString = ""
Of.dryRun = false
Of.ifUpgradeAvailableOnly = false

flags := flags{}
flags.mandatoryFlags = Mf
flags.optionalFlags = Of

// setting debug
cD := debug{}
cD.setDebug(false)

numberIssueCreated, jiraResponse, NotCreatedIssueId, tickets := openJiraTickets(flags, projectInfo, vulnsForJira, cD)

assert.Equal("", NotCreatedIssueId)
assert.NotNil(tickets)
assert.Equal(string(readFixture("./fixtures/results/jiraTicketsOpeningResults")), jiraResponse)
fmt.Println("numberIssueCreated :", numberIssueCreated)

return
}
17 changes: 15 additions & 2 deletions utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ func (Of *optionalFlags) setOptionalFlags(debugPtr bool, dryRunPtr bool, v viper
Of.maturityFilterString = v.GetString("snyk.maturityFilter")
Of.assigneeID = v.GetString("jira.assigneeID")
Of.labels = v.GetString("jira.labels")
Of.dueDate = v.GetString("jira.dueDate")
Of.priorityIsSeverity = v.GetBool("jira.priorityIsSeverity")
Of.priorityScoreThreshold = v.GetInt("snyk.priorityScoreThreshold")
Of.debug = debugPtr
Expand Down Expand Up @@ -156,8 +157,9 @@ func (opt *flags) setOption(args []string) {
fs.String("severity", "low", "Optional. Your severity threshold")
fs.String("maturityFilter", "", "Optional. include only maturity level(s) separated by commas [mature,proof-of-concept,no-known-exploit,no-data]")
fs.String("type", "all", "Optional. Your issue type (all|vuln|license)")
fs.String("assigneeId", "", "Optional. The Jira user accountId to assign issues to.")
fs.String("assigneeId", "", "Optional. The Jira user accountId to assign issues to")
fs.String("labels", "", "Optional. Jira ticket labels")
fs.String("dueDate", "", "Optional. The built-in Due Date field")
fs.Bool("priorityIsSeverity", false, "Boolean. Use issue severity as priority")
fs.Int("priorityScoreThreshold", 0, "Optional. Your min priority score threshold [INT between 0 and 1000]")
debugPtr = fs.Bool("debug", false, "Optional. Boolean. enable debug mode")
Expand All @@ -166,7 +168,11 @@ func (opt *flags) setOption(args []string) {
fs.Bool("ifUpgradeAvailableOnly", false, "Optional. Boolean. Opens tickets only for upgradable issues")
fs.Bool("ifAutoFixableOnly", false, "Optional. Boolean. Opens tickets for issues that are fixable (no effect when using ifUpgradeAvailableOnly)")
configFilePtr = fs.String("configFile", "", "Optional. Config file path. Use config file to set parameters")
fs.Parse(args)
errParse := fs.Parse(args)
if errParse != nil {
log.Println("*** ERROR *** Error parsing command line arguments: ", errParse.Error())
os.Exit(1)
}

// Have to set one by one because the name in the config file doesn't correspond to the flag name
// This can be done at any time
Expand All @@ -186,6 +192,7 @@ func (opt *flags) setOption(args []string) {
v.BindPFlag("jira.assigneeID", fs.Lookup("assigneeId"))
v.BindPFlag("jira.labels", fs.Lookup("labels"))
v.BindPFlag("jira.cveInTitle", fs.Lookup("cveInTitle"))
v.BindPFlag("jira.dueDate", fs.Lookup("dueDate"))
v.BindPFlag("jira.priorityIsSeverity", fs.Lookup("priorityIsSeverity"))
v.BindPFlag("snyk.priorityScoreThreshold", fs.Lookup("priorityScoreThreshold"))
v.BindPFlag("snyk.ifUpgradeAvailableOnly", fs.Lookup("ifUpgradeAvailableOnly"))
Expand Down Expand Up @@ -676,6 +683,12 @@ func checkJiraValue(JiraValues interface{}) (bool, map[string]interface{}) {
log.Printf("*** ERROR *** Please check the format config file, %s is of type %s when it should be a string", key, reflect.TypeOf(value).String())
return false, nil
}
case "dueDate":
valueType := reflect.TypeOf(value).String()
if valueType != "string" {
log.Printf("*** ERROR *** Please check the format config file, %s is of type %s when it should be a string", key, reflect.TypeOf(value).String())
return false, nil
}
case "priorityIsSeverity":
valueType := reflect.TypeOf(value).String()
if valueType != "bool" {
Expand Down
1 change: 1 addition & 0 deletions utils_def.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type optionalFlags struct {
maturityFilterString string
assigneeID string
labels string
dueDate string
priorityIsSeverity bool
priorityScoreThreshold int
debug bool
Expand Down