Refactor JIRA service to use gem
This commit is contained in:
parent
2fc359a506
commit
f4bc18d237
7 changed files with 313 additions and 145 deletions
3
Gemfile
3
Gemfile
|
@ -161,6 +161,9 @@ gem 'connection_pool', '~> 2.0'
|
|||
# HipChat integration
|
||||
gem 'hipchat', '~> 1.5.0'
|
||||
|
||||
# JIRA integration
|
||||
gem 'jira-ruby', '~> 0.1.17'
|
||||
|
||||
# Flowdock integration
|
||||
gem 'gitlab-flowdock-git-hook', '~> 1.0.1'
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ module ServiceParams
|
|||
:add_pusher, :send_from_committer_email, :disable_diffs,
|
||||
:external_wiki_url, :notify, :color,
|
||||
:server_host, :server_port, :default_irc_uri, :enable_ssl_verification,
|
||||
:jira_issue_transition_id]
|
||||
:jira_issue_transition_id, :url, :project_key]
|
||||
|
||||
# Parameters to ignore if no value is specified
|
||||
FILTER_BLANK_PARAMS = [:password]
|
||||
|
|
|
@ -1,15 +1,35 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: services
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# type :string(255)
|
||||
# title :string(255)
|
||||
# project_id :integer
|
||||
# created_at :datetime
|
||||
# updated_at :datetime
|
||||
# active :boolean default(FALSE), not null
|
||||
# properties :text
|
||||
# template :boolean default(FALSE)
|
||||
# push_events :boolean default(TRUE)
|
||||
# issues_events :boolean default(TRUE)
|
||||
# merge_requests_events :boolean default(TRUE)
|
||||
# tag_push_events :boolean default(TRUE)
|
||||
# note_events :boolean default(TRUE), not null
|
||||
# build_events :boolean default(FALSE), not null
|
||||
#
|
||||
require 'jira'
|
||||
|
||||
class JiraService < IssueTrackerService
|
||||
include HTTParty
|
||||
include Gitlab::Routing.url_helpers
|
||||
include Gitlab::Application.routes.url_helpers
|
||||
|
||||
DEFAULT_API_VERSION = 2
|
||||
|
||||
prop_accessor :username, :password, :api_url, :jira_issue_transition_id,
|
||||
:title, :description, :project_url, :issues_url, :new_issue_url
|
||||
prop_accessor :username, :password, :url, :project_key,
|
||||
:jira_issue_transition_id, :title, :description
|
||||
|
||||
validates :api_url, presence: true, url: true, if: :activated?
|
||||
|
||||
before_validation :set_api_url, :set_jira_issue_transition_id
|
||||
before_validation :set_jira_issue_transition_id
|
||||
|
||||
before_update :reset_password
|
||||
|
||||
|
@ -20,14 +40,34 @@ class JiraService < IssueTrackerService
|
|||
|
||||
def reset_password
|
||||
# don't reset the password if a new one is provided
|
||||
if api_url_changed? && !password_touched?
|
||||
if url_changed? && !password_touched?
|
||||
self.password = nil
|
||||
end
|
||||
end
|
||||
|
||||
def options
|
||||
url = URI.parse(self.url)
|
||||
{
|
||||
:username => self.username,
|
||||
:password => self.password,
|
||||
:site => URI.join(url, '/').to_s,
|
||||
:context_path => url.path,
|
||||
:auth_type => :basic,
|
||||
:read_timeout => 120,
|
||||
:use_ssl => url.scheme == 'https'
|
||||
}
|
||||
end
|
||||
|
||||
def client
|
||||
@client ||= ::JIRA::Client.new(options)
|
||||
end
|
||||
|
||||
def jira_project
|
||||
@jira_project ||= client.Project.find(project_key)
|
||||
end
|
||||
|
||||
def help
|
||||
'Setting `project_url`, `issues_url` and `new_issue_url` will '\
|
||||
'allow a user to easily navigate to the Jira issue tracker. See the '\
|
||||
'See the ' \
|
||||
'[integration doc](http://doc.gitlab.com/ce/integration/external-issue-tracker.html) '\
|
||||
'for details.'
|
||||
end
|
||||
|
@ -53,12 +93,25 @@ class JiraService < IssueTrackerService
|
|||
end
|
||||
|
||||
def fields
|
||||
super.push(
|
||||
{ type: 'text', name: 'api_url', placeholder: 'https://jira.example.com/rest/api/2' },
|
||||
[
|
||||
{ type: 'text', name: 'url', title: 'URL', placeholder: 'https://jira.example.com' },
|
||||
{ type: 'text', name: 'project_key', placeholder: 'PROJ' },
|
||||
{ type: 'text', name: 'username', placeholder: '' },
|
||||
{ type: 'password', name: 'password', placeholder: '' },
|
||||
{ type: 'text', name: 'jira_issue_transition_id', placeholder: '2' }
|
||||
)
|
||||
]
|
||||
end
|
||||
|
||||
def project_url
|
||||
"#{url}/issues/?jql=project=#{project_key}"
|
||||
end
|
||||
|
||||
def issues_url
|
||||
"#{url}/browse/:id"
|
||||
end
|
||||
|
||||
def new_issue_url
|
||||
"#{url}/secure/CreateIssue.jspa"
|
||||
end
|
||||
|
||||
def execute(push, issue = nil)
|
||||
|
@ -72,7 +125,7 @@ class JiraService < IssueTrackerService
|
|||
end
|
||||
|
||||
def create_cross_reference_note(mentioned, noteable, author)
|
||||
issue_name = mentioned.id
|
||||
issue_key = mentioned.id
|
||||
project = self.project
|
||||
noteable_name = noteable.class.name.underscore.downcase
|
||||
noteable_id = if noteable.is_a?(Commit)
|
||||
|
@ -94,53 +147,25 @@ class JiraService < IssueTrackerService
|
|||
},
|
||||
entity: {
|
||||
name: noteable_name.humanize.downcase,
|
||||
url: entity_url,
|
||||
title: noteable.title
|
||||
url: entity_url
|
||||
}
|
||||
}
|
||||
|
||||
add_comment(data, issue_name)
|
||||
add_comment(data, issue_key)
|
||||
end
|
||||
|
||||
def test_settings
|
||||
return unless api_url.present?
|
||||
result = JiraService.get(
|
||||
jira_api_test_url,
|
||||
headers: {
|
||||
'Content-Type' => 'application/json',
|
||||
'Authorization' => "Basic #{auth}"
|
||||
}
|
||||
)
|
||||
return unless api_utrl.present?
|
||||
# Test settings by getting the project
|
||||
jira_project
|
||||
|
||||
case result.code
|
||||
when 201, 200
|
||||
Rails.logger.info("#{self.class.name} SUCCESS #{result.code}: Successfully connected to #{api_url}.")
|
||||
true
|
||||
else
|
||||
Rails.logger.info("#{self.class.name} ERROR #{result.code}: #{result.parsed_response}")
|
||||
false
|
||||
end
|
||||
rescue Errno::ECONNREFUSED => e
|
||||
Rails.logger.info "#{self.class.name} ERROR: #{e.message}. API URL: #{api_url}."
|
||||
rescue Errno::ECONNREFUSED, JIRA::HTTPError => e
|
||||
Rails.logger.info "#{self.class.name} Test ERROR: #{url} - #{e.message}"
|
||||
false
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def build_api_url_from_project_url
|
||||
server = URI(project_url)
|
||||
default_ports = [["http", 80], ["https", 443]].include?([server.scheme, server.port])
|
||||
server_url = "#{server.scheme}://#{server.host}"
|
||||
server_url.concat(":#{server.port}") unless default_ports
|
||||
"#{server_url}/rest/api/#{DEFAULT_API_VERSION}"
|
||||
rescue
|
||||
"" # looks like project URL was not valid
|
||||
end
|
||||
|
||||
def set_api_url
|
||||
self.api_url = build_api_url_from_project_url if self.api_url.blank?
|
||||
end
|
||||
|
||||
def set_jira_issue_transition_id
|
||||
self.jira_issue_transition_id ||= "2"
|
||||
end
|
||||
|
@ -149,7 +174,7 @@ class JiraService < IssueTrackerService
|
|||
commit_id = if entity.is_a?(Commit)
|
||||
entity.id
|
||||
elsif entity.is_a?(MergeRequest)
|
||||
entity.diff_head_sha
|
||||
entity.last_commit.id
|
||||
end
|
||||
commit_url = build_entity_url(:commit, commit_id)
|
||||
|
||||
|
@ -161,69 +186,47 @@ class JiraService < IssueTrackerService
|
|||
end
|
||||
|
||||
def transition_issue(issue)
|
||||
message = {
|
||||
transition: {
|
||||
id: jira_issue_transition_id
|
||||
}
|
||||
}
|
||||
send_message(close_issue_url(issue.iid), message.to_json)
|
||||
issue = client.Issue.find(issue.iid)
|
||||
issue.transitions.build.save(transition: { id: jira_issue_transition_id })
|
||||
end
|
||||
|
||||
def add_issue_solved_comment(issue, commit_id, commit_url)
|
||||
comment = {
|
||||
body: "Issue solved with [#{commit_id}|#{commit_url}]."
|
||||
}
|
||||
|
||||
send_message(comment_url(issue.iid), comment.to_json)
|
||||
comment = "Issue solved with [#{commit_id}|#{commit_url}]."
|
||||
send_message(issue.iid, comment)
|
||||
end
|
||||
|
||||
def add_comment(data, issue_name)
|
||||
url = comment_url(issue_name)
|
||||
def add_comment(data, issue_key)
|
||||
user_name = data[:user][:name]
|
||||
user_url = data[:user][:url]
|
||||
entity_name = data[:entity][:name]
|
||||
entity_url = data[:entity][:url]
|
||||
entity_title = data[:entity][:title]
|
||||
project_name = data[:project][:name]
|
||||
|
||||
message = {
|
||||
body: %Q{[#{user_name}|#{user_url}] mentioned this issue in [a #{entity_name} of #{project_name}|#{entity_url}]:\n'#{entity_title}'}
|
||||
}
|
||||
message = "[#{user_name}|#{user_url}] mentioned this issue in [a #{entity_name} of #{project_name}|#{entity_url}]."
|
||||
|
||||
unless existing_comment?(issue_name, message[:body])
|
||||
send_message(url, message.to_json)
|
||||
end
|
||||
# unless existing_comment?(issue_name, message[:body])
|
||||
send_message(issue_key, message)
|
||||
# end
|
||||
end
|
||||
|
||||
def auth
|
||||
require 'base64'
|
||||
Base64.urlsafe_encode64("#{self.username}:#{self.password}")
|
||||
end
|
||||
|
||||
def send_message(url, message)
|
||||
def send_message(issue_key, message)
|
||||
return unless api_url.present?
|
||||
result = JiraService.post(
|
||||
url,
|
||||
body: message,
|
||||
headers: {
|
||||
'Content-Type' => 'application/json',
|
||||
'Authorization' => "Basic #{auth}"
|
||||
}
|
||||
)
|
||||
issue = client.Issue.find(issue_key)
|
||||
issue.comments.build.save!(body: message)
|
||||
|
||||
message = case result.code
|
||||
when 201, 200, 204
|
||||
"#{self.class.name} SUCCESS #{result.code}: Successfully posted to #{url}."
|
||||
when 401
|
||||
"#{self.class.name} ERROR 401: Unauthorized. Check the #{self.username} credentials and JIRA access permissions and try again."
|
||||
else
|
||||
"#{self.class.name} ERROR #{result.code}: #{result.parsed_response}"
|
||||
end
|
||||
# message = case result.code
|
||||
# when 201, 200, 204
|
||||
# "#{self.class.name} SUCCESS #{result.code}: Successfully posted to #{url}."
|
||||
# when 401
|
||||
# "#{self.class.name} ERROR 401: Unauthorized. Check the #{self.username} credentials and JIRA access permissions and try again."
|
||||
# else
|
||||
# "#{self.class.name} ERROR #{result.code}: #{result.parsed_response}"
|
||||
# end
|
||||
|
||||
Rails.logger.info(message)
|
||||
message
|
||||
rescue URI::InvalidURIError, Errno::ECONNREFUSED => e
|
||||
Rails.logger.info "#{self.class.name} ERROR: #{e.message}. Hostname: #{url}."
|
||||
Rails.logger.info "#{self.class.name} Send message ERROR: #{url} - #{e.message}"
|
||||
end
|
||||
|
||||
def existing_comment?(issue_name, new_comment)
|
||||
|
@ -267,16 +270,4 @@ class JiraService < IssueTrackerService
|
|||
)
|
||||
)
|
||||
end
|
||||
|
||||
def close_issue_url(issue_name)
|
||||
"#{self.api_url}/issue/#{issue_name}/transitions"
|
||||
end
|
||||
|
||||
def comment_url(issue_name)
|
||||
"#{self.api_url}/issue/#{issue_name}/comment"
|
||||
end
|
||||
|
||||
def jira_api_test_url
|
||||
"#{self.api_url}/myself"
|
||||
end
|
||||
end
|
||||
|
|
52
db/migrate/20160122231710_migrate_jira_to_gem.rb
Normal file
52
db/migrate/20160122231710_migrate_jira_to_gem.rb
Normal file
|
@ -0,0 +1,52 @@
|
|||
class MigrateJiraToGem < ActiveRecord::Migration
|
||||
def change
|
||||
reversible do |dir|
|
||||
select_all("SELECT id, properties FROM services WHERE services.type IN ('JiraService')").each do |service|
|
||||
id = service['id']
|
||||
properties = JSON.parse(service['properties'])
|
||||
properties_was = properties.clone
|
||||
|
||||
dir.up do
|
||||
# Migrate `project_url` to `project_key`
|
||||
# Ignore if `project_url` doesn't have jql project query with project key
|
||||
if properties['project_url'].present?
|
||||
jql = properties['project_url'].match('project=([A-Za-z]*)')
|
||||
properties['project_key'] = jql.captures.first if jql
|
||||
end
|
||||
|
||||
# Migrate `api_url` to `url`
|
||||
if properties['api_url'].present?
|
||||
url = properties['api_url'].match('(.*)\/rest\/api')
|
||||
properties['url'] = url.captures.first if url
|
||||
end
|
||||
|
||||
# Delete now unnecessary properties
|
||||
properties.delete('api_url')
|
||||
properties.delete('project_url')
|
||||
properties.delete('new_issue_url')
|
||||
properties.delete('issues_url')
|
||||
end
|
||||
|
||||
dir.down do
|
||||
# Rebuild old properties based on sane defaults
|
||||
if properties['url'].present?
|
||||
properties['api_url'] = "#{properties['url']}/rest/api/2"
|
||||
properties['project_url'] =
|
||||
"#{properties['url']}/issues/?jql=project=#{properties['project_key']}"
|
||||
properties['issues_url'] = "#{properties['url']}/browse/:id"
|
||||
properties['new_issue_url'] = "#{properties['url']}/secure/CreateIssue.jspa"
|
||||
end
|
||||
|
||||
# Delete the new properties
|
||||
properties.delete('url')
|
||||
properties.delete('project_key')
|
||||
end
|
||||
|
||||
# Update changes properties
|
||||
if properties != properties_was
|
||||
execute("UPDATE services SET properties = '#{quote_string(properties.to_json)}' WHERE id = #{id}")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -5,57 +5,36 @@ trackers and external authentication.
|
|||
|
||||
See the documentation below for details on how to configure these services.
|
||||
|
||||
- [Jira](../project_services/jira.md) Integrate with the JIRA issue tracker
|
||||
- [JIRA](jira.md) Integrate with the JIRA issue tracker
|
||||
- [External issue tracker](external-issue-tracker.md) Redmine, JIRA, etc.
|
||||
- [LDAP](ldap.md) Set up sign in via LDAP
|
||||
- [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, GitLab.com, Google, Bitbucket, Facebook, Shibboleth, SAML, Crowd and Azure
|
||||
- [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, GitLab, and Google via OAuth.
|
||||
- [SAML](saml.md) Configure GitLab as a SAML 2.0 Service Provider
|
||||
- [CAS](cas.md) Configure GitLab to sign in using CAS
|
||||
- [Slack](slack.md) Integrate with the Slack chat service
|
||||
- [OAuth2 provider](oauth_provider.md) OAuth2 application creation
|
||||
- [Gmail actions buttons](gmail_action_buttons_for_gitlab.md) Adds GitLab actions to messages
|
||||
- [reCAPTCHA](recaptcha.md) Configure GitLab to use Google reCAPTCHA for new users
|
||||
- [Akismet](akismet.md) Configure Akismet to stop spam
|
||||
- [Koding](../administration/integration/koding.md) Configure Koding to use IDE integration
|
||||
|
||||
GitLab Enterprise Edition contains [advanced Jenkins support][jenkins].
|
||||
|
||||
[jenkins]: http://docs.gitlab.com/ee/integration/jenkins.html
|
||||
|
||||
|
||||
## Project services
|
||||
|
||||
Integration with services such as Campfire, Flowdock, Gemnasium, HipChat,
|
||||
Pivotal Tracker, and Slack are available in the form of a [Project Service][].
|
||||
You can find these within GitLab in the Services page under Project Settings if
|
||||
you are at least a master on the project.
|
||||
Project Services are a bit like plugins in that they allow a lot of freedom in
|
||||
adding functionality to GitLab. For example there is also a service that can
|
||||
send an email every time someone pushes new commits.
|
||||
|
||||
Because GitLab is open source we can ship with the code and tests for all
|
||||
plugins. This allows the community to keep the plugins up to date so that they
|
||||
always work in newer GitLab versions.
|
||||
|
||||
For an overview of what projects services are available without logging in,
|
||||
please see the [project_services directory][projects-code].
|
||||
|
||||
[jenkins]: http://doc.gitlab.com/ee/integration/jenkins.html
|
||||
[Project Service]: ../project_services/project_services.md
|
||||
|
||||
## SSL certificate errors
|
||||
|
||||
When trying to integrate GitLab with services that are using self-signed certificates,
|
||||
it is very likely that SSL certificate errors will occur on different parts of the
|
||||
application, most likely Sidekiq. There are 2 approaches you can take to solve this:
|
||||
|
||||
1. Add the root certificate to the trusted chain of the OS.
|
||||
1. If using Omnibus, you can add the certificate to GitLab's trusted certificates.
|
||||
|
||||
**OS main trusted chain**
|
||||
|
||||
This [resource](http://kb.kerio.com/product/kerio-connect/server-configuration/ssl-certificates/adding-trusted-root-certificates-to-the-server-1605.html)
|
||||
has all the information you need to add a certificate to the main trusted chain.
|
||||
|
||||
This [answer](http://superuser.com/questions/437330/how-do-you-add-a-certificate-authority-ca-to-ubuntu)
|
||||
at SuperUser also has relevant information.
|
||||
|
||||
**Omnibus Trusted Chain**
|
||||
|
||||
It is enough to concatenate the certificate to the main trusted certificate:
|
||||
|
||||
```bash
|
||||
cat jira.pem >> /opt/gitlab/embedded/ssl/certs/cacert.pem
|
||||
```
|
||||
|
||||
After that restart GitLab with:
|
||||
|
||||
```bash
|
||||
sudo gitlab-ctl restart
|
||||
```
|
||||
[projects-code]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/app/models/project_services
|
||||
|
|
BIN
doc/integration/img/jira_service_page.png
Normal file
BIN
doc/integration/img/jira_service_page.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 44 KiB |
|
@ -1,3 +1,146 @@
|
|||
# GitLab JIRA integration
|
||||
# GitLab Jira integration
|
||||
|
||||
This document was moved under [project_services/jira](../project_services/jira.md).
|
||||
GitLab can be configured to interact with Jira. Configuration happens via
|
||||
username and password. Connecting to a Jira server via CAS is not possible.
|
||||
|
||||
Each project can be configured to connect to a different Jira instance, see the
|
||||
[configuration](#configuration) section. If you have one Jira instance you can
|
||||
pre-fill the settings page with a default template. To configure the template
|
||||
see the [Services Templates][services-templates] document.
|
||||
|
||||
Once the project is connected to Jira, you can reference and close the issues
|
||||
in Jira directly from GitLab.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Referencing Jira Issues from GitLab](#referencing-jira-issues)
|
||||
* [Closing Jira Issues from GitLab](#closing-jira-issues)
|
||||
* [Configuration](#configuration)
|
||||
|
||||
### Referencing Jira Issues
|
||||
|
||||
When GitLab project has Jira issue tracker configured and enabled, mentioning
|
||||
Jira issue in GitLab will automatically add a comment in Jira issue with the
|
||||
link back to GitLab. This means that in comments in merge requests and commits
|
||||
referencing an issue, eg. `PROJECT-7`, will add a comment in Jira issue in the
|
||||
format:
|
||||
|
||||
```
|
||||
USER mentioned this issue in LINK_TO_THE_MENTION
|
||||
```
|
||||
|
||||
* `USER` A user that mentioned the issue. This is the link to the user profile in GitLab.
|
||||
* `LINK_TO_THE_MENTION` Link to the origin of mention with a name of the entity where Jira issue was mentioned.
|
||||
Can be commit or merge request.
|
||||
|
||||
![example of mentioning or closing the Jira issue](img/jira_issue_reference.png)
|
||||
|
||||
---
|
||||
|
||||
### Closing Jira Issues
|
||||
|
||||
Jira issues can be closed directly from GitLab by using trigger words, eg.
|
||||
`Resolves PROJECT-1`, `Closes PROJECT-1` or `Fixes PROJECT-1`, in commits and
|
||||
merge requests. When a commit which contains the trigger word in the commit
|
||||
message is pushed, GitLab will add a comment in the mentioned Jira issue.
|
||||
|
||||
For example, for project named `PROJECT` in Jira, we implemented a new feature
|
||||
and created a merge request in GitLab.
|
||||
|
||||
This feature was requested in Jira issue `PROJECT-7`. Merge request in GitLab
|
||||
contains the improvement and in merge request description we say that this
|
||||
merge request `Closes PROJECT-7` issue.
|
||||
|
||||
Once this merge request is merged, the Jira issue will be automatically closed
|
||||
with a link to the commit that resolved the issue.
|
||||
|
||||
![A Git commit that causes the Jira issue to be closed](img/jira_merge_request_close.png)
|
||||
|
||||
---
|
||||
|
||||
![The GitLab integration user leaves a comment on Jira](img/jira_service_close_issue.png)
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
### Configuring JIRA
|
||||
|
||||
We need to create a user in JIRA which will have access to all projects that
|
||||
need to integrate with GitLab. Login to your JIRA instance as admin and under
|
||||
Administration go to User Management and create a new user.
|
||||
|
||||
As an example, we'll create a user named `gitlab` and add it to `jira-developers`
|
||||
group.
|
||||
|
||||
**It is important that the user `gitlab` has write-access to projects in JIRA**
|
||||
|
||||
### Configuring GitLab
|
||||
|
||||
JIRA configuration in GitLab is done via a project's **Services**.
|
||||
|
||||
#### GitLab 7.8 and up with JIRA v6.x
|
||||
|
||||
See next section.
|
||||
|
||||
#### GitLab 7.8 and up
|
||||
|
||||
_The currently supported JIRA versions are v6.x and v7.x._
|
||||
|
||||
To enable JIRA integration in a project, navigate to the project's
|
||||
**Settings > Services > JIRA**.
|
||||
|
||||
Fill in the required details on the page as described in the table below.
|
||||
|
||||
| Field | Description |
|
||||
| ----- | ----------- |
|
||||
| `URL` | The base URL to the JIRA project which is being linked to this GitLab project. Ex. https://jira.example.com |
|
||||
| `Project key` | The short, all capital letter identifier for your JIRA project. |
|
||||
| `Username` | The username of the user created in [configuring JIRA step](#configuring-jira). |
|
||||
| `Password` |The password of the user created in [configuring JIRA step](#configuring-jira). |
|
||||
| `Jira issue transition` | This is the ID of a transition that moves issues to a closed state. You can find this number under JIRA workflow administration ([see screenshot](img/jira_workflow_screenshot.png)). By default, this ID is `2` (in the example image, this is `2` as well) |
|
||||
|
||||
After saving the configuration, your GitLab project will be able to interact
|
||||
with the linked JIRA project.
|
||||
|
||||
![Jira service page](img/jira_service_page.png)
|
||||
|
||||
---
|
||||
|
||||
#### GitLab 6.x-7.7 with JIRA v6.x
|
||||
|
||||
_**Note:** GitLab versions 7.8 and up contain various integration improvements.
|
||||
We strongly recommend upgrading._
|
||||
|
||||
In `gitlab.yml` enable the JIRA issue tracker section by
|
||||
[uncommenting these lines][jira-gitlab-yml]. This will make sure that all
|
||||
issues within GitLab are pointing to the JIRA issue tracker.
|
||||
|
||||
After you set this, you will be able to close issues in JIRA by a commit in
|
||||
GitLab.
|
||||
|
||||
Go to your project's **Settings** page and fill in the project name for the
|
||||
JIRA project:
|
||||
|
||||
![Set the JIRA project name in GitLab to 'NEW'](img/jira_project_name.png)
|
||||
|
||||
---
|
||||
|
||||
You can also enable the JIRA service that will allow you to interact with JIRA
|
||||
issues. Go to the **Settings > Services > JIRA** and:
|
||||
|
||||
1. Tick the active check box to enable the service
|
||||
1. Supply the URL to JIRA server, for example http://jira.example.com
|
||||
1. Supply the username of a user we created under `Configuring JIRA` section,
|
||||
for example `gitlab`
|
||||
1. Supply the password of the user
|
||||
1. Optional: supply the JIRA API version, default is version `2`
|
||||
1. Optional: supply the JIRA issue transition ID (issue transition to closed).
|
||||
This is dependent on JIRA settings, default is `2`
|
||||
1. Hit save
|
||||
|
||||
|
||||
![Jira services page](img/jira_service.png)
|
||||
|
||||
[services-templates]: ../project_services/services_templates.md
|
||||
[jira-gitlab-yml]: https://gitlab.com/subscribers/gitlab-ee/blob/6-8-stable-ee/config/gitlab.yml.example#L111-115
|
||||
|
|
Loading…
Reference in a new issue