summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy <jeremy.benoist@gmail.com>2014-07-29 17:41:55 +0200
committerJeremy <jeremy.benoist@gmail.com>2015-02-02 09:59:42 +0100
commitb4d9ceb26fc4bd9125cdbd6796a618415d8f6af7 (patch)
treeed9c2430731e411e67bb2dbe4679d30cfe3a5504
parentc47328948b5fff218c68279260a57ab6b03e7423 (diff)
downloadgitlab-ce-b4d9ceb26fc4bd9125cdbd6796a618415d8f6af7.tar.gz
Add Asana service
Also add ability to render "service.help" in markdown
-rw-r--r--Gemfile3
-rw-r--r--Gemfile.lock9
-rw-r--r--app/models/project.rb3
-rw-r--r--app/models/project_services/asana_service.rb103
-rw-r--r--app/views/projects/services/_form.html.haml3
-rw-r--r--features/project/service.feature7
-rw-r--r--features/steps/project/services.rb15
-rw-r--r--spec/models/asana_service_spec.rb62
-rw-r--r--spec/models/project_spec.rb1
9 files changed, 203 insertions, 3 deletions
diff --git a/Gemfile b/Gemfile
index be78831e1fc..e8b1919b0f7 100644
--- a/Gemfile
+++ b/Gemfile
@@ -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