Skip to content

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 😬 https://confluence.atlassian.com/adminjiraserver071/defining-resolution-field-values-802592402.html

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?

Merge request reports