Add Asana service
Also add ability to render "service.help" in markdown
This commit is contained in:
parent
c47328948b
commit
b4d9ceb26f
9 changed files with 203 additions and 3 deletions
3
Gemfile
3
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"
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
103
app/models/project_services/asana_service.rb
Normal file
103
app/models/project_services/asana_service.rb
Normal file
|
@ -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
|
|
@ -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"
|
||||
|
|
|
@ -73,3 +73,8 @@ Feature: Project Services
|
|||
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
|
||||
|
|
|
@ -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
|
||||
|
|
62
spec/models/asana_service_spec.rb
Normal file
62
spec/models/asana_service_spec.rb
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue