Read about our upcoming Code of Conduct on this issue

asana_service.rb 2.86 KB
Newer Older
1
2
# frozen_string_literal: true

Jeremy's avatar
Jeremy committed
3
4
5
6
7
8
9
10
11
12
13
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
14
    s_('AsanaService|Asana - Teamwork without email')
Jeremy's avatar
Jeremy committed
15
16
17
  end

  def help
Jeremy's avatar
Jeremy committed
18
19
20
21
22
    '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.
Jeremy's avatar
Jeremy committed
23
24
25

You can also close a task with a message containing: `fix #123456`.

26
27
You can create a Personal Access Token here:
http://app.asana.com/-/account_api'
Jeremy's avatar
Jeremy committed
28
29
  end

30
  def self.to_param
Jeremy's avatar
Jeremy committed
31
32
33
34
35
    'asana'
  end

  def fields
    [
Jeremy's avatar
Jeremy committed
36
37
38
      {
        type: 'text',
        name: 'api_key',
39
        placeholder: s_('AsanaService|User Personal Access Token. User must have access to task, all comments will be attributed to this user.'),
40
        required: true
Jeremy's avatar
Jeremy committed
41
42
43
44
      },
      {
        type: 'text',
        name: 'restrict_to_branch',
45
        placeholder: s_('AsanaService|Comma-separated list of branches which will be automatically inspected. Leave blank to include all branches.')
Jeremy's avatar
Jeremy committed
46
      }
Jeremy's avatar
Jeremy committed
47
48
49
    ]
  end

50
  def self.supported_events
51
52
53
    %w(push)
  end

54
55
56
57
58
59
60
61
  def client
    @_client ||= begin
      Asana::Client.new do |c|
        c.authentication :access_token, api_key
      end
    end
  end

Douwe Maan's avatar
Douwe Maan committed
62
  def execute(data)
63
    return unless supported_events.include?(data[:object_kind])
64

65
    # check the branch restriction is poplulated and branch is not included
66
    branch = Gitlab::Git.ref_name(data[:ref])
Jeremy's avatar
Jeremy committed
67
    branch_restriction = restrict_to_branch.to_s
68
    if branch_restriction.present? && branch_restriction.index(branch).nil?
Jeremy's avatar
Jeremy committed
69
70
71
      return
    end

72
    user = data[:user_name]
73
    project_name = project.full_name
Jeremy's avatar
Jeremy committed
74

Douwe Maan's avatar
Douwe Maan committed
75
    data[:commits].each do |commit|
76
      push_msg = s_("AsanaService|%{user} pushed to branch %{branch} of %{project_name} ( %{commit_url} ):") % { user: user, branch: branch, project_name: project_name, commit_url: commit[:url] }
77
      check_commit(commit[:message], push_msg)
Jeremy's avatar
Jeremy committed
78
79
80
81
    end
  end

  def check_commit(message, push_msg)
82
83
84
85
86
87
88
    # matches either:
    # - #1234
    # - https://app.asana.com/0/0/1234
    # optionally preceded with:
    # - fix/ed/es/ing
    # - close/s/d
    # - closing
89
    issue_finder = %r{(fix\w*|clos[ei]\w*+)?\W*(?:https://app\.asana\.com/\d+/\d+/(\d+)|#(\d+))}i
90
91
92
93
94

    message.scan(issue_finder).each do |tuple|
      # tuple will be
      # [ 'fix', 'id_from_url', 'id_from_pound' ]
      taskid = tuple[2] || tuple[1]
Jeremy's avatar
Jeremy committed
95

96
97
      begin
        task = Asana::Task.find_by_id(client, taskid)
98
99
100
101
102
103
        task.add_comment(text: "#{push_msg} #{message}")

        if tuple[0]
          task.update(completed: true)
        end
      rescue => e
104
        log_error(e.message)
105
        next
Jeremy's avatar
Jeremy committed
106
107
108
109
      end
    end
  end
end