diff --git a/Gemfile b/Gemfile
index be78831e1fc1db79a1cb5aa82dde98ca4a7fd1dd..e8b1919b0f7477e68352d51d3edb9476eae714a6 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 551f16722f287b22cd1bd7c2e9866c89bac0e6fa..20a396e2b0bcee06e669cea1694ffb9c1bde17fd 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 b26c697a7b71ead3c48b520930364bc1ebf199f2..8c6fbfd66ac13483c0fa452c378f0ad9dbc9061c 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 @@ def build_missing_services
   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 0000000000000000000000000000000000000000..174d69ae3cd82291dd5af0e0afe1867b0dbc33c5
--- /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 1151f22c7e8e78076fba96fd25754c9412b0c01d..ba2708808815678deaabf846a0bc4035a9e68d09 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 85939a5c9ca38e4d16b82d49170a834fc7d144b9..d0600aca010e14f5af75b938311de75e81770673 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 09e86447058eeec741837d73083b82caa3a4461c..9e8b7cf1e891e7e7883e6d45853243793bd02eef 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 0000000000000000000000000000000000000000..4d4968e80ffdd6bcd44ea623c8780d1879ce0dd4
--- /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 092c02d552e099edf51fd09071c54f0413161406..035fdab849efab8df31c9b5c42258aa8f4f434b7 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -51,6 +51,7 @@
     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