diff --git a/examples/jiralert.yml b/examples/jiralert.yml index da9b0b8..1a35b7a 100644 --- a/examples/jiralert.yml +++ b/examples/jiralert.yml @@ -25,6 +25,12 @@ defaults: reopen_duration: 0h # Static label that will be added to the JIRA ticket alongisde the JIRALERT{...} or ALERT{...} label static_labels: ["custom"] + # Other projects are the projects to search for existing issues for the given alerts if + # the main project does not have it. If no issue was found in, the main projects will + # be used to create a new one. If the old issue is found in one of the other projects + # (first found is used in case of duplicates) that old project's issue will be used for + # alert updates instead of creating on in the main project. + other_projects: ["OTHER1", "OTHER2"] # Receiver definitions. At least one must be defined. receivers: @@ -56,7 +62,7 @@ receivers: # # Automatically resolve jira issues when alert is resolved. Optional. If declared, ensure state is not an empty string. auto_resolve: - state: 'Done' + state: 'Done' # File containing template definitions. Required. template: jiralert.tmpl diff --git a/pkg/config/config.go b/pkg/config/config.go index 71ba2b8..1813ec6 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -133,6 +133,7 @@ type ReceiverConfig struct { // Required issue fields Project string `yaml:"project" json:"project"` + OtherProjects []string `yaml:"other_projects" json:"other_projects"` IssueType string `yaml:"issue_type" json:"issue_type"` Summary string `yaml:"summary" json:"summary"` ReopenState string `yaml:"reopen_state" json:"reopen_state"` @@ -311,6 +312,9 @@ func (c *Config) UnmarshalYAML(unmarshal func(interface{}) error) error { if len(c.Defaults.StaticLabels) > 0 { rc.StaticLabels = append(rc.StaticLabels, c.Defaults.StaticLabels...) } + if len(c.Defaults.OtherProjects) > 0 { + rc.OtherProjects = append(rc.OtherProjects, c.Defaults.OtherProjects...) + } } if len(c.Receivers) == 0 { diff --git a/pkg/notify/notify.go b/pkg/notify/notify.go index ca98486..26d974f 100644 --- a/pkg/notify/notify.go +++ b/pkg/notify/notify.go @@ -288,8 +288,10 @@ func toGroupTicketLabel(groupLabels alertmanager.KV, hashJiraLabel bool) string return strings.Replace(buf.String(), " ", "", -1) } -func (r *Receiver) search(project, issueLabel string) (*jira.Issue, bool, error) { - query := fmt.Sprintf("project=\"%s\" and labels=%q order by resolutiondate desc", project, issueLabel) +func (r *Receiver) search(projects []string, issueLabel string) (*jira.Issue, bool, error) { + // Search multiple projects in case issue was moved and further alert firings are desired in existing JIRA. + projectList := "'" + strings.Join(projects, "', '") + "'" + query := fmt.Sprintf("project in(%s) and labels=%q order by resolutiondate desc", projectList, issueLabel) options := &jira.SearchOptions{ Fields: []string{"summary", "status", "resolution", "resolutiondate"}, MaxResults: 2, @@ -317,7 +319,15 @@ func (r *Receiver) search(project, issueLabel string) (*jira.Issue, bool, error) } func (r *Receiver) findIssueToReuse(project string, issueGroupLabel string) (*jira.Issue, bool, error) { - issue, retry, err := r.search(project, issueGroupLabel) + projectsToSearch := []string{project} + // In case issue was moved to a different project, include the other configured projects in search (if any). + for _, other := range r.conf.OtherProjects { + if other != project { + projectsToSearch = append(projectsToSearch, other) + } + } + + issue, retry, err := r.search(projectsToSearch, issueGroupLabel) if err != nil { return nil, retry, err } diff --git a/pkg/notify/notify_test.go b/pkg/notify/notify_test.go index 3390f56..15ea758 100644 --- a/pkg/notify/notify_test.go +++ b/pkg/notify/notify_test.go @@ -107,7 +107,7 @@ func (f *fakeJira) Create(issue *jira.Issue) (*jira.Issue, *jira.Response, error // Assuming single label. query := fmt.Sprintf( - "project=\"%s\" and labels=%q order by resolutiondate desc", + "project in('%s') and labels=%q order by resolutiondate desc", issue.Fields.Project.Key, issue.Fields.Labels[0], )