Skip to content

Commit

Permalink
WIP on connecting with JIRA
Browse files Browse the repository at this point in the history
  • Loading branch information
mikeweaver committed Sep 16, 2016
1 parent e677588 commit e54ec78
Show file tree
Hide file tree
Showing 6 changed files with 160 additions and 12 deletions.
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,4 @@ end
gem 'hobo_fields'
gem 'delayed_job_active_record'
gem 'daemons'

gem 'jira-ruby', '0.1.17', require: 'jira'
8 changes: 5 additions & 3 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,9 @@ GEM
jbuilder (2.3.2)
activesupport (>= 3.0.0, < 5)
multi_json (~> 1.2)
jira-ruby (0.1.17)
activesupport
oauth (~> 0.4.7)
jquery-rails (4.0.5)
rails-dom-testing (~> 1.0)
railties (>= 4.2.0)
Expand Down Expand Up @@ -146,6 +149,7 @@ GEM
netrc (0.11.0)
nokogiri (1.6.7.1)
mini_portile2 (~> 2.0.0.rc2)
oauth (0.4.7)
parallel (1.6.1)
parser (2.3.0.2)
ast (~> 2.2)
Expand Down Expand Up @@ -282,6 +286,7 @@ DEPENDENCIES
fakefs
hobo_fields
jbuilder (~> 2.0)
jira-ruby (= 0.1.17)
jquery-rails
mutant-rspec
rails (= 4.2.4)
Expand All @@ -297,6 +302,3 @@ DEPENDENCIES
unicorn
web-console (~> 2.0)
webmock

BUNDLED WITH
1.12.5
12 changes: 11 additions & 1 deletion config/initializers/global_settings.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
web_server_url: '',
repositories_to_check_for_conflicts: {},
branches_to_merge: {},
dry_run: false
dry_run: false,
jira: {}
}.freeze

DEFAULT_BRANCH_FILTERS = {
Expand All @@ -36,6 +37,13 @@
only_merge_source_branch_with_tag: ''
}.merge(DEFAULT_BRANCH_FILTERS).merge(DEFAULT_REPOSITORY_SETTINGS).freeze

DEFAULT_JIRA_SETTINGS = {
site: '',
consumer_key: '',
access_token: '',
access_key: ''
}.freeze

class InvalidSettings < StandardError; end


Expand Down Expand Up @@ -84,6 +92,8 @@ def load_global_settings
settings_object.branches_to_merge[branch_name] = auto_merge_settings
end

settings_object.jira = OpenStruct.new(DEFAULT_JIRA_SETTINGS.merge(settings_object.jira))

# cleanup data
settings_object.email_override.downcase!
settings_object.email_filter.collect! { |email| email.downcase }
Expand Down
34 changes: 34 additions & 0 deletions lib/jira/client_wrapper.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
require 'jira'

module JIRA
class ClientWrapper < JIRA::Client
def initialize(settings)
client_options = {
signature_method: 'RSA-SHA1',
consumer_key: settings.consumer_key,
site: settings.site,
context_path: "",
use_ssl: true
}

super(client_options)

@request_client.set_access_token(settings.access_token, settings.access_key)

consumer.http.set_debug_output($stderr)
end

def find_issue(key)
self.Issue.find(key)
rescue JIRA::HTTPError => ex
puts ex.response
puts '****'
if ex.message == 'Not Found'
nil
else
raise
end
end
end
end

75 changes: 68 additions & 7 deletions lib/workers/github_push_hook_handler.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ class GithubPushHookHandler
PENDING_QUEUE = 'pending'
PROCESSING_QUEUE = 'processing'
CONTEXT_NAME = 'JIRA Checker'
PENDING_DESCRIPTION = 'Branch is being examined'
SUCCESS_DESCRIPTION = 'Branch is OK'
STATE_DESCRIPTIONS = {
Github::Api::Status::STATE_PENDING => 'Branch is being examined',
Github::Api::Status::STATE_SUCCESS => 'Branch is OK',
Github::Api::Status::STATE_FAILED => 'Branch was rejected'
}
VALID_JIRA_STATUSES = ['Ready to Deploy']

def initialize(push_hook_payload)
@payload = Github::Api::PushHookPayload.new(push_hook_payload)
Expand All @@ -13,7 +17,7 @@ def initialize(push_hook_payload)
def queue!
Rails.logger.info('Queueing request')
Rails.logger.info(@payload)
set_status_for_repo(Github::Api::Status::STATE_PENDING, PENDING_DESCRIPTION)
set_status_for_repo(Github::Api::Status::STATE_PENDING, STATE_DESCRIPTIONS[Github::Api::Status::STATE_PENDING])
process!
end
handle_asynchronously(:queue!, queue: PENDING_QUEUE)
Expand All @@ -22,14 +26,20 @@ def process!
Rails.logger.info('Processing request')
push = Push.create_from_github_data!(@payload)
# clone repo
git = Git::Git.new(@payload.repository_path)
# diff with master to get list of commits
# save list of orphaned commits
git_commits = git.commits_diff_branch_with_ancestor(@payload.branch_name, ancestor_branch)
# get ticket numbers from commits
ticket_numbers = extract_jira_issue_keys(git_commits)
# lookup tickets in JIRA
# save tickets
jira_issues = get_jira_issues!(ticket_numbers)
# get list of orphaned commits
orphan_commits = commits_without_a_jira_issue_key!(git_commits)
# compute status
push.status = Github::Api::Status::STATE_SUCCESS
push.status = compute_push_status(@payload.branch_name, orphan_commits, ticket_numbers, jira_issues)
push.save!
set_status_for_repo(Github::Api::Status::STATE_SUCCESS, SUCCESS_DESCRIPTION)
# TODO determine description
set_status_for_repo(push.status, STATE_DESCRIPTIONS[push.status])
end
handle_asynchronously(:process!, queue: PROCESSING_QUEUE)

Expand All @@ -47,4 +57,55 @@ def set_status_for_repo(state, description)
'http://moreinfohere.com')
end

def ancestor_branch
'master' # TODO move to setting
end

def jira_project_keys
['STORY', 'TECH', 'WEB'] # TODO move to setting
end

def jira_issue_regex
/(?:^|\s)((?:#{jira_project_keys.join('|')})[- _]\d+)/
end

def extract_jira_issue_keys(commits)
commits.collect do |commit|
if match = message.match(jira_issue_regex)
match.captures[0]
end
end.uniq
end

def commits_without_a_jira_issue_key!(commits)
commits.collect do |commit|
unless message.match(jira_issue_regex)
# TODO implement construction from commit
Commit.create!(commit)
end
end
end

def get_jira_issues!(ticket_numbers)
jira_client = JIRA::ClientWrapper.new(GlobalSettings.jira)
ticket_numbers.collect do |ticket_number|
# TODO construct JIRA issue models
jira_client.find_issue(ticket_number)
end
end

def compute_push_status(branch_name, orphan_commits, ticket_numbers, jira_issues)
# TODO verify that all the ticket numbers have tickets
if tickets_not_ready_to_deploy(jira_issues) || (orphan_commits && !ignore_orphan_commits_for_branches.includes?(branch_name))
Github::Api::Status::STATE_FAILED
else
Github::Api::Status::STATE_SUCCESS
end
end

def jira_issues_with_invalid_statuses(jira_issues)
jira_issues.reject do |jira_issue|
VALID_JIRA_STATUSES.includes?(jira_issue.status)
end
end
end
41 changes: 41 additions & 0 deletions spec/lib/jira/client_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
require 'spec_helper'

describe 'JIRA::ClientWrapper' do

it 'can be created' do
settings = {
site: 'https://www.jira.com',
consumer_key: 'fake_key',
access_token: 'fake_access_token',
access_key: 'fake_access_key'
}
client = JIRA::ClientWrapper.new(OpenStruct.new(settings))
expect(client).to_not be_nil
end

context 'issues' do

before do
settings = {
site: 'https://www.jira.com',
consumer_key: 'fake_key',
access_token: 'fake_access_token',
access_key: 'fake_access_key'
}
@client = JIRA::ClientWrapper.new(OpenStruct.new(settings))
end

it 'can find an issue' do
stub_request(:get, /.*/).to_return(status: 200, body: 'tbd')

expect(@client.find_issue('ISSUE-1234')).to_not be_nil
end

it 'returns nil if the issue does not exist' do
stub_request(:get, /.*/).to_return(status: 404, body: 'Not Found')

expect(@client.find_issue('ISSUE-1234')).to be_nil
end
end

end

0 comments on commit e54ec78

Please sign in to comment.