Skip to content
This repository was archived by the owner on Jul 19, 2025. It is now read-only.

Commit e9cf22d

Browse files
committed
Merge pull request #21 from codeclimate/pb-asana
Add Asana
2 parents 31d73d1 + c2081f4 commit e9cf22d

File tree

3 files changed

+159
-30
lines changed

3 files changed

+159
-30
lines changed

lib/cc/services/asana.rb

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
class CC::Service::Asana < CC::Service
2+
class Config < CC::Service::Config
3+
attribute :api_key, String, label: "API key"
4+
5+
attribute :workspace_id, String, label: "Workspace ID"
6+
7+
attribute :project_id, String, label: "Project ID",
8+
description: "(optional)"
9+
10+
attribute :assignee, String, label: "Assignee",
11+
description: "Assignee email address (optional)"
12+
13+
validates :api_key, presence: true
14+
validates :workspace_id, presence: true
15+
end
16+
17+
self.title = "Asana"
18+
self.description = "Create tasks in Asana"
19+
self.issue_tracker = true
20+
21+
def receive_test
22+
create_task("Test task from Code Climate")
23+
end
24+
25+
def receive_quality
26+
title = "Refactor #{constant_name} from #{rating} on Code Climate"
27+
28+
create_task("#{title} - #{details_url}")
29+
end
30+
31+
def receive_vulnerability
32+
formatter = CC::Formatters::TicketFormatter.new(self)
33+
title = formatter.format_vulnerability_title
34+
35+
create_task("#{title} - #{details_url}")
36+
end
37+
38+
private
39+
40+
def create_task(name)
41+
params = {
42+
data: { workspace: config.workspace_id, name: name }
43+
}
44+
45+
if config.project_id.present?
46+
# Note this is undocumented, found via trial & error
47+
params[:data][:projects] = [config.project_id]
48+
end
49+
50+
if config.assignee.present?
51+
params[:data][:assignee] = config.assignee
52+
end
53+
54+
http.headers["Content-Type"] = "application/json"
55+
http.basic_auth(config.api_key, "")
56+
57+
url = "https://app.asana.com/api/1.0/tasks"
58+
res = http_post(url, params.to_json)
59+
60+
body = JSON.parse(res.body)
61+
62+
id = body['data']['id']
63+
url = "https://app.asana.com/0/#{config.workspace_id}/#{id}"
64+
65+
{ id: id, url: url }
66+
end
67+
68+
end

service_test.rb

Lines changed: 49 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,17 @@
44
#
55
# Usage:
66
#
7-
# bundle exec ruby service_test.rb
7+
# $ <SERVICE>_<CONFIG_ATTR_1>="..." \
8+
# <SERVICE>_<CONFIG_ATTR_2>="..." \
9+
# ... ... bundle exec ruby service_test.rb
810
#
9-
# Environment variables used:
11+
# Example:
1012
#
11-
# REPO_NAME Defaults to "App"
12-
# SLACK_WEBHOOK_URL Slack is not tested unless set
13-
# FLOWDOCK_API_TOKEN Flowdock is not tested unless set
13+
# $ SLACK_WEBHOOK_URL="http://..." bundle exec ruby service_test.rb
1414
#
15-
# Example:
15+
# Other Environment variables used:
1616
#
17-
# SLACK_WEBHOOK_URL="http://..." bundle exec ruby service_test.rb
17+
# REPO_NAME Defaults to "App"
1818
#
1919
###
2020
require 'cc/services'
@@ -30,33 +30,52 @@ def call
3030
end
3131
end
3232

33-
def test_service(klass, config)
34-
repo_name = ENV["REPO_NAME"] || "App"
33+
class ServiceTest
34+
def initialize(klass, *params)
35+
@klass = klass
36+
@params = params
37+
end
38+
39+
def test
40+
config = {}
3541

36-
service = klass.new(config, name: :test, repo_name: repo_name)
42+
puts "-"*80
43+
puts @klass
3744

38-
CC::Service::Invocation.new(service) do |i|
39-
i.wrap(WithResponseLogging)
45+
@params.each do |param|
46+
if var = ENV[to_env_var(param)]
47+
config[param] = var
48+
else
49+
puts " -> skipping"
50+
return false
51+
end
52+
end
53+
54+
puts " -> testing"
55+
puts " -> #{config.inspect}"
56+
print " => "
57+
58+
test_service(@klass, config)
4059
end
41-
end
4260

43-
if webhook_url = ENV["SLACK_WEBHOOK_URL"]
44-
puts "Testing Slack..."
45-
test_service(CC::Service::Slack, webhook_url: webhook_url)
46-
end
61+
private
4762

48-
if api_token = ENV["FLOWDOCK_API_TOKEN"]
49-
puts "Testing Flowdock..."
50-
test_service(CC::Service::Flowdock, api_token: api_token)
51-
end
63+
def to_env_var(param)
64+
"#{@klass.to_s.split("::").last}_#{param}".upcase
65+
end
66+
67+
def test_service(klass, config)
68+
repo_name = ENV["REPO_NAME"] || "App"
5269

53-
if (jira_username = ENV["JIRA_USERNAME"]) &&
54-
(jira_password = ENV["JIRA_PASSWORD"]) &&
55-
(jira_domain = ENV["JIRA_DOMAIN"]) &&
56-
(jira_project = ENV["JIRA_PROJECT"])
57-
puts "Testing JIRA"
58-
test_service(CC::Service::Jira, { username: jira_username,
59-
password: jira_password,
60-
domain: jira_domain,
61-
project_id: jira_project })
70+
service = klass.new(config, name: :test, repo_name: repo_name)
71+
72+
CC::Service::Invocation.new(service) do |i|
73+
i.wrap(WithResponseLogging)
74+
end
75+
end
6276
end
77+
78+
ServiceTest.new(CC::Service::Slack, :webhook_url).test
79+
ServiceTest.new(CC::Service::Flowdock, :api_token).test
80+
ServiceTest.new(CC::Service::Jira, :username, :password, :domain, :project_id).test
81+
ServiceTest.new(CC::Service::Asana, :api_key, :workspace_id, :project_id).test

test/asana_test.rb

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
require File.expand_path('../helper', __FILE__)
2+
3+
class TestAsana < CC::Service::TestCase
4+
def test_quality
5+
assert_asana_receives(
6+
event(:quality, to: "D", from: "C"),
7+
"Refactor User from a D on Code Climate - https://codeclimate.com/repos/1/feed"
8+
)
9+
end
10+
11+
def test_vulnerability
12+
assert_asana_receives(
13+
event(:vulnerability, vulnerabilities: [{
14+
"warning_type" => "critical",
15+
"location" => "app/user.rb line 120"
16+
}]),
17+
"New critical issue found in app/user.rb line 120 - https://codeclimate.com/repos/1/feed"
18+
)
19+
end
20+
21+
private
22+
23+
def assert_asana_receives(event_data, name)
24+
@stubs.post '/api/1.0/tasks' do |env|
25+
body = JSON.parse(env[:body])
26+
data = body["data"]
27+
28+
assert_equal "1", data["workspace"]
29+
assert_equal "2", data["projects"].first
30+
assert_equal "[email protected]", data["assignee"]
31+
assert_equal name, data["name"]
32+
33+
[200, {}, '{"data":{"id":{}}}']
34+
end
35+
36+
receive(
37+
CC::Service::Asana,
38+
{ api_key: "abc123", workspace_id: "1", project_id: "2", assignee: "[email protected]" },
39+
event_data
40+
)
41+
end
42+
end

0 commit comments

Comments
 (0)