Skip to content
This repository was archived by the owner on Jul 19, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 58 additions & 9 deletions lib/cc/services/github_pull_requests.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,25 @@ class Config < CC::Service::Config
validates :oauth_token, presence: true
end

class ResponseAggregator
def initialize(status_response, comment_response)
@status_response = status_response
@comment_response = comment_response
end

def response
return @status_response if @status_response[:ok] && @comment_response[:ok]
message = if !@status_response[:ok] && !@comment_response[:ok]
"Unable to post comment or update status"
elsif !@status_response[:ok]
"Unable to update status: #{@status_response[:message]}"
elsif !@comment_response[:ok]
"Unable to post comment: #{@comment_response[:message]}"
end
{ ok: false, message: message }
end
end

self.title = "GitHub Pull Requests"
self.description = "Update pull requests on GitHub"

Expand All @@ -26,16 +45,13 @@ class Config < CC::Service::Config
def receive_test
setup_http

http_post(base_status_url("0" * 40), "{}")

rescue HTTPError => ex
if ex.status == 422 # response message: "No commit found for SHA"
{ ok: true, message: "OAuth token is valid" }
else ex.status == 401 # response message: "Bad credentials"
{ ok: false, message: ex.message }
if config.update_status && config.add_comment
ResponseAggregator.new(receive_test_status, receive_test_comment).response
elsif config.update_status
receive_test_status
elsif config.add_comment
receive_test_comment
end
rescue => ex
{ ok: false, message: ex.message }
end

def receive_pull_request
Expand Down Expand Up @@ -75,6 +91,31 @@ def add_comment
end
end

def receive_test_status
http_post(base_status_url("0" * 40), "{}")

rescue HTTPError => ex
if ex.status == 422 # response message: "No commit found for SHA"
{ ok: true, message: "OAuth token is valid" }
else ex.status == 401 # response message: "Bad credentials"
{ ok: false, message: ex.message }
end
rescue => ex
{ ok: false, message: ex.message }
end

def receive_test_comment
response = http_get(user_url)
if response_includes_repo_scope?(response)
{ ok: true, message: "OAuth token is valid" }
else
{ ok: false, message: "OAuth token requires 'repo' scope to post comments." }
end

rescue => ex
{ ok: false, message: ex.message }
end

def comment_present?
response = http_get(comments_url)
comments = JSON.parse(response.body)
Expand All @@ -100,6 +141,10 @@ def comments_url
"#{BASE_URL}/repos/#{github_slug}/issues/#{number}/comments"
end

def user_url
"#{BASE_URL}/user"
end

def github_slug
@payload.fetch("github_slug")
end
Expand All @@ -112,4 +157,8 @@ def number
@payload.fetch("number")
end

def response_includes_repo_scope?(response)
response.headers['x-oauth-scopes'] && response.headers['x-oauth-scopes'].split(/\s*,\s*/).include?("repo")
end

end
4 changes: 2 additions & 2 deletions service_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
# Example:
#
# $ SLACK_WEBHOOK_URL="http://..." bundle exec ruby service_test.rb
# $ GITHUBPULLREQUESTS_OAUTH_TOKEN=06083a4a060d358ca709939b1f00645777661c44 bundle exec ruby service_test.rb
# $ GITHUBPULLREQUESTS_UPDATE_STATUS=false GITHUBPULLREQUESTS_ADD_COMMENT=true GITHUBPULLREQUESTS_OAUTH_TOKEN=06083a4a060d358ca709939b1f00645777661c44 bundle exec ruby service_test.rb
#
# Other Environment variables used:
#
Expand Down Expand Up @@ -80,4 +80,4 @@ def test_service(klass, config, payload)
ServiceTest.new(CC::Service::Flowdock, :api_token).test
ServiceTest.new(CC::Service::Jira, :username, :password, :domain, :project_id).test
ServiceTest.new(CC::Service::Asana, :api_key, :workspace_id, :project_id).test
ServiceTest.new(CC::Service::GitHubPullRequests, :oauth_token).test({ github_slug: "codeclimate/codeclimate" })
ServiceTest.new(CC::Service::GitHubPullRequests, :oauth_token, :update_status, :add_comment).test({ github_slug: "codeclimate/codeclimate" })
62 changes: 57 additions & 5 deletions test/github_pull_requests_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,64 @@ def test_pull_request_status_success
})
end

def test_pull_request_test_success
def test_pull_request_status_test_success
@stubs.post("/repos/pbrisbin/foo/statuses/#{"0" * 40}") { |env| [422, {}, ""] }

assert receive_test({}, { github_slug: "pbrisbin/foo" })[:ok], "Expected test of pull request to be true"
assert receive_test({ update_status: true }, { github_slug: "pbrisbin/foo" })[:ok], "Expected test of pull request to be true"
end

def test_pull_request_test_failure
def test_pull_request_status_test_failure
@stubs.post("/repos/pbrisbin/foo/statuses/#{"0" * 40}") { |env| [401, {}, ""] }

assert !receive_test({}, { github_slug: "pbrisbin/foo" })[:ok], "Expected failed test of pull request"
assert !receive_test({ update_status: true }, { github_slug: "pbrisbin/foo" })[:ok], "Expected failed test of pull request"
end

def test_pull_request_comment_test_success
@stubs.get("/user") { |env| [200, { "x-oauth-scopes" => "gist, user, repo" }, ""] }

assert receive_test({ add_comment: true })[:ok], "Expected test of pull request to be true"
end

def test_pull_request_comment_test_failure_insufficient_permissions
@stubs.get("/user") { |env| [200, { "x-oauth-scopes" => "gist, user" }, ""] }

assert !receive_test({ add_comment: true })[:ok], "Expected failed test of pull request"
end

def test_pull_request_comment_test_failure_bad_token
@stubs.get("/user") { |env| [401, {}, ""] }

assert !receive_test({ add_comment: true })[:ok], "Expected failed test of pull request"
end

def test_pull_request_success_both
@stubs.post("/repos/pbrisbin/foo/statuses/#{"0" * 40}") { |env| [422, {}, ""] }
@stubs.get("/user") { |env| [200, { "x-oauth-scopes" => "gist, user, repo" }, ""] }

assert receive_test({ update_status: true, add_comment: true }, { github_slug: "pbrisbin/foo" })[:ok], "Expected test of pull request to be true"
end

def test_response_aggregator_success
response = aggregrate_response({ok: true, message: "OK"}, {ok: true, message: "OK 2"})
assert_equal response, { ok: true, message: "OK" }
end

def test_response_aggregator_failure_both
response = aggregrate_response({ok: false, message: "Bad Token"}, {ok: false, message: "Bad Stuff"})
assert_equal response, { ok: false, message: "Unable to post comment or update status" }
end

def test_response_aggregator_failure_status
response = aggregrate_response({ok: false, message: "Bad Token"}, {ok: true, message: "OK"})
assert !response[:ok], "Expected invalid response because status response is invalid"
assert_match /Bad Token/, response[:message]
end


def test_response_aggregator_failure_status
response = aggregrate_response({ok: true, message: "OK"}, {ok: false, message: "Bad Stuff"})
assert !response[:ok], "Expected invalid response because comment response is invalid"
assert_match /Bad Stuff/, response[:message]
end

def test_pull_request_comment
Expand Down Expand Up @@ -104,12 +152,16 @@ def receive_pull_request(config, event_data)
)
end

def receive_test(config, event_data)
def receive_test(config, event_data = {})
receive(
CC::Service::GitHubPullRequests,
{ oauth_token: "123" }.merge(config),
{ name: "test" }.merge(event_data)
)
end

def aggregrate_response(status_response, comment_response)
CC::Service::GitHubPullRequests::ResponseAggregator.new(status_response, comment_response).response
end

end