diff options
author | Jeremy <jeremy.benoist@gmail.com> | 2014-07-29 17:41:55 +0200 |
---|---|---|
committer | Jeremy <jeremy.benoist@gmail.com> | 2015-02-02 09:59:42 +0100 |
commit | b4d9ceb26fc4bd9125cdbd6796a618415d8f6af7 (patch) | |
tree | ed9c2430731e411e67bb2dbe4679d30cfe3a5504 | |
parent | c47328948b5fff218c68279260a57ab6b03e7423 (diff) | |
download | gitlab-ce-b4d9ceb26fc4bd9125cdbd6796a618415d8f6af7.tar.gz |
Add Asana service
Also add ability to render "service.help" in markdown
-rw-r--r-- | Gemfile | 3 | ||||
-rw-r--r-- | Gemfile.lock | 9 | ||||
-rw-r--r-- | app/models/project.rb | 3 | ||||
-rw-r--r-- | app/models/project_services/asana_service.rb | 103 | ||||
-rw-r--r-- | app/views/projects/services/_form.html.haml | 3 | ||||
-rw-r--r-- | features/project/service.feature | 7 | ||||
-rw-r--r-- | features/steps/project/services.rb | 15 | ||||
-rw-r--r-- | spec/models/asana_service_spec.rb | 62 | ||||
-rw-r--r-- | spec/models/project_spec.rb | 1 |
9 files changed, 203 insertions, 3 deletions
@@ -151,6 +151,9 @@ gem "gemnasium-gitlab-service", "~> 0.2" # Slack integration gem "slack-notifier", "~> 1.0.0" +# Asana integration +gem 'asana', '~> 0.0.6' + # d3 gem "d3_rails", "~> 3.1.4" diff --git a/Gemfile.lock b/Gemfile.lock index 551f16722f2..20a396e2b0b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -23,6 +23,10 @@ GEM activemodel (= 4.1.1) activesupport (= 4.1.1) arel (~> 5.0.0) + activeresource (4.0.0) + activemodel (~> 4.0) + activesupport (~> 4.0) + rails-observers (~> 0.1.1) activesupport (4.1.1) i18n (~> 0.6, >= 0.6.9) json (~> 1.7, >= 1.7.7) @@ -36,6 +40,8 @@ GEM activerecord (>= 2.3.0) rake (>= 0.8.7) arel (5.0.1.20140414130214) + asana (0.0.6) + activeresource (>= 3.2.3) asciidoctor (0.1.4) attr_required (1.0.0) awesome_print (1.2.0) @@ -402,6 +408,8 @@ GEM bundler (>= 1.3.0, < 2.0) railties (= 4.1.1) sprockets-rails (~> 2.0) + rails-observers (0.1.2) + activemodel (~> 4.0) rails_autolink (1.1.6) rails (> 3.1) rails_best_practices (1.14.4) @@ -624,6 +632,7 @@ DEPENDENCIES acts-as-taggable-on addressable annotate (~> 2.6.0.beta2) + asana (~> 0.0.6) asciidoctor (= 0.1.4) awesome_print better_errors diff --git a/app/models/project.rb b/app/models/project.rb index b26c697a7b7..8c6fbfd66ac 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -68,6 +68,7 @@ class Project < ActiveRecord::Base has_one :hipchat_service, dependent: :destroy has_one :flowdock_service, dependent: :destroy has_one :assembla_service, dependent: :destroy + has_one :asana_service, dependent: :destroy has_one :gemnasium_service, dependent: :destroy has_one :slack_service, dependent: :destroy has_one :buildbox_service, dependent: :destroy @@ -359,7 +360,7 @@ class Project < ActiveRecord::Base end def available_services_names - %w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla + %w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla asana emails_on_push gemnasium slack pushover buildbox bamboo teamcity jira redmine custom_issue_tracker) end diff --git a/app/models/project_services/asana_service.rb b/app/models/project_services/asana_service.rb new file mode 100644 index 00000000000..174d69ae3cd --- /dev/null +++ b/app/models/project_services/asana_service.rb @@ -0,0 +1,103 @@ +# == Schema Information +# +# Table name: services +# +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer not null +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# + +require 'asana' + +class AsanaService < Service + prop_accessor :api_key, :restrict_to_branch + validates :api_key, presence: true, if: :activated? + + def title + 'Asana' + end + + def description + 'Asana - Teamwork without email' + end + + def help + 'This service adds commit messages as comments to Asana tasks. Once enabled, commit messages +are checked for Asana task URLs (for example, `https://app.asana.com/0/123456/987654`) or task IDs +starting with # (for example, `#987654`). Every task ID found will get the commit comment added to it. + +You can also close a task with a message containing: `fix #123456`. + +You can find your Api Keys here: http://developer.asana.com/documentation/#api_keys' + end + + def to_param + 'asana' + end + + def fields + [ + { type: 'text', name: 'api_key', placeholder: 'User API token. User must have access to task, all comments will be attributed to this user.' }, + { type: 'text', name: 'restrict_to_branch', placeholder: 'Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches.' } + ] + end + + def execute(push) + Asana.configure do |client| + client.api_key = api_key + end + + user = push[:user_name] + branch = push[:ref].gsub('refs/heads/', '') + + branch_restriction = restrict_to_branch.to_s + + # check the branch restriction is poplulated and branch is not included + if branch_restriction.length > 0 && branch_restriction.index(branch) == nil + return + end + + project_name = project.name_with_namespace + push_msg = user + ' pushed to branch ' + branch + ' of ' + project_name + + push[:commits].each do |commit| + check_commit(' ( ' + commit[:url] + ' ): ' + commit[:message], push_msg) + end + end + + def check_commit(message, push_msg) + task_list = [] + close_list = [] + + message.split("\n").each do |line| + # look for a task ID or a full Asana url + task_list.concat(line.scan(/#(\d+)/)) + task_list.concat(line.scan(/https:\/\/app\.asana\.com\/\d+\/\d+\/(\d+)/)) + # look for a word starting with 'fix' followed by a task ID + close_list.concat(line.scan(/(fix\w*)\W*#(\d+)/i)) + end + + # post commit to every taskid found + task_list.each do |taskid| + task = Asana::Task.find(taskid[0]) + + if task + task.create_story(text: push_msg + ' ' + message) + end + end + + # close all tasks that had 'fix(ed/es/ing) #:id' in them + close_list.each do |taskid| + task = Asana::Task.find(taskid.last) + + if task + task.modify(completed: true) + end + end + end +end diff --git a/app/views/projects/services/_form.html.haml b/app/views/projects/services/_form.html.haml index 1151f22c7e8..ba270880881 100644 --- a/app/views/projects/services/_form.html.haml +++ b/app/views/projects/services/_form.html.haml @@ -19,7 +19,8 @@ - if @service.help.present? .bs-callout - = @service.help + = preserve do + = markdown @service.help .form-group = f.label :active, "Active", class: "control-label" diff --git a/features/project/service.feature b/features/project/service.feature index 85939a5c9ca..d0600aca010 100644 --- a/features/project/service.feature +++ b/features/project/service.feature @@ -72,4 +72,9 @@ Feature: Project Services And I click jetBrains TeamCity CI service link And I fill jetBrains TeamCity CI settings Then I should see jetBrains TeamCity CI service settings saved - + + Scenario: Activate Asana service + When I visit project "Shop" services page + And I click Asana service link + And I fill Asana settings + Then I should see Asana service settings saved diff --git a/features/steps/project/services.rb b/features/steps/project/services.rb index 09e86447058..9e8b7cf1e89 100644 --- a/features/steps/project/services.rb +++ b/features/steps/project/services.rb @@ -16,6 +16,7 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps page.should have_content 'Pushover' page.should have_content 'Atlassian Bamboo' page.should have_content 'JetBrains TeamCity' + page.should have_content 'Asana' end step 'I click gitlab-ci service link' do @@ -102,6 +103,20 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps find_field('Token').value.should == 'verySecret' end + step 'I click Asana service link' do + click_link 'Asana' + end + + step 'I fill Asana settings' do + check 'Active' + fill_in 'Api key', with: 'verySecret' + click_button 'Save' + end + + step 'I should see Asana service settings saved' do + find_field('Api key').value.should == 'verySecret' + end + step 'I click email on push service link' do click_link 'Emails on push' end diff --git a/spec/models/asana_service_spec.rb b/spec/models/asana_service_spec.rb new file mode 100644 index 00000000000..4d4968e80ff --- /dev/null +++ b/spec/models/asana_service_spec.rb @@ -0,0 +1,62 @@ +# == Schema Information +# +# Table name: services +# +# id :integer not null, primary key +# type :string(255) +# title :string(255) +# project_id :integer not null +# created_at :datetime +# updated_at :datetime +# active :boolean default(FALSE), not null +# properties :text +# + +require 'spec_helper' + +describe AsanaService, models: true do + describe 'Associations' do + it { should belong_to :project } + it { should have_one :service_hook } + end + + describe 'Validations' do + context 'active' do + before do + subject.active = true + end + + it { should validate_presence_of :api_key } + end + end + + describe 'Execute' do + let(:user) { create(:user) } + let(:project) { create(:project) } + + before do + @asana = AsanaService.new + @asana.stub( + project: project, + project_id: project.id, + service_hook: true, + api_key: 'verySecret' + ) + end + + it 'should call Asana service to created a story' do + Asana::Task.should_receive(:find).with('123456').once + # Asana::Task.should_receive(:create_story).with('pushed related to #123456').once + + @asana.check_commit('related to #123456', 'pushed') + end + + it 'should call Asana service to created a story and close a task' do + Asana::Task.should_receive(:find).with('456789').twice + # Asana::Task.should_receive(:create_story).with('pushed related to #456789').once + # Asana::Task.should_receive(:modify).with(completed: true).once + + @asana.check_commit('fix #456789', 'pushed') + end + end +end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 092c02d552e..035fdab849e 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -51,6 +51,7 @@ describe Project do it { should have_one(:forked_project_link).dependent(:destroy) } it { should have_one(:slack_service).dependent(:destroy) } it { should have_one(:pushover_service).dependent(:destroy) } + it { should have_one(:asana_service).dependent(:destroy) } end describe 'Mass assignment' do |