Ensure `JIRA::Resource::Issue` responds to `resolution` before calling it
Symptoms
When using JIRA integration, merging an MR mentioning a JIRA issue, should mark the JIRA issue as closed.
But doing so don't work, and causes the following:
- the branch is actually merged, multiple times
- the merge request stays
open
, even if the branch has been merged
This reported issue tells the same story: https://gitlab.com/gitlab-org/gitlab-ce/issues/33636
Causes
To automatically close the issue, GitLab relies on a call to issue.resolution
method to avoid commenting multiple times on an already resolved issue.
See https://gitlab.com/gitlab-org/gitlab-ce/blob/07a4cf41841478f1f48d715d2b3f3bd533363150/app/models/project_services/jira_service.rb#L107
This method actually returns the value of an attribute named resolution
that should be part of JIRA API responses.
More precisely, it should be part of the fields
hash returned by JIRA to
describe an issue (see https://confluence.atlassian.com/adminjiraserver071/issue-fields-and-statuses-802592413.html#Issuefieldsandstatuses-ResolutionIssueresolutions).
It's job is to expose the issue status: it has been resolved, or not.
The jira-ruby gem used by GitLab to consume JIRA API is actually doing
a "mapping" of those fields (camelCased, dynamically generated, ...), to let you
call them as methods, thanks to a method_missing
(https://github.com/sumoheavy/jira-ruby/blob/master/lib/jira/resource/issue.rb#L110-L125)
On our case, issue.resolution
raises an error undefined method 'resolution' for #<JIRA::Resource::Issue:0x007fb7ff6816e0>
in ProcessCommitWorker
job that does the Git merge, and then closes related issues, so it triggers the call to close the JIRA issue, before changing the status of the MR to merged
.
That's why the branch is merged, but MR status isn't changed. It's merged multiple
times as the job is automatically retried.
The error is raised, as there is no resolution
field in our JIRA API responses!
I joked of course, saying it's probably an option in JIRA, but it's the case actually
While inspecting JIRA API responses, there is nothing returned named resolution
(or anything else giving a hint if the issue is closed/resolved or not).
Possible solution
Anyway, as it's a configurable thing, I think GitLab shouldn't expect it to be always present. Depending on JIRA configs, it might be present or not.
To avoid breaking the hard way and causing multiple merges, I think an additionnal check with issue.respond_to?(:resolution)
worth it.
A respond_to?
method doing the same fields mapping to methods is provided by the jira-ruby gem I guess for this kind of cases. (see https://github.com/sumoheavy/jira-ruby/blob/master/lib/jira/resource/issue.rb#L102-L108).
I think a better approach would be to wrap everything in a begin rescue
block and log any error than could happen while dealing with an external service, but I'm not that familiar with GitLab's code to know what you guys used to do and what sounds better.
WDYT?