Replace the tinder gem by bare HTTP requests

This commit is contained in:
Thomas Balthazar 2016-08-10 12:25:01 +02:00
parent 551ffc0a4d
commit fb748daf53
7 changed files with 147 additions and 26 deletions

View file

@ -1,6 +1,7 @@
Please view this file on the master branch, on stable branches it's out of date. Please view this file on the master branch, on stable branches it's out of date.
v 8.11.0 (unreleased) v 8.11.0 (unreleased)
- Remove the http_parser.rb dependency by removing the tinder gem. !5758 (tbalthazar)
- Fix don't pass a local variable called `i` to a partial. !20510 (herminiotorres) - Fix don't pass a local variable called `i` to a partial. !20510 (herminiotorres)
- Fix rename `add_users_into_project` and `projects_ids`. !20512 (herminiotorres) - Fix rename `add_users_into_project` and `projects_ids`. !20512 (herminiotorres)
- Fix the title of the toggle dropdown button. !5515 (herminiotorres) - Fix the title of the toggle dropdown button. !5515 (herminiotorres)

View file

@ -163,9 +163,6 @@ gem 'redis-rails', '~> 4.0.0'
gem 'redis', '~> 3.2' gem 'redis', '~> 3.2'
gem 'connection_pool', '~> 2.0' gem 'connection_pool', '~> 2.0'
# Campfire integration
gem 'tinder', '~> 1.10.0'
# HipChat integration # HipChat integration
gem 'hipchat', '~> 1.5.0' gem 'hipchat', '~> 1.5.0'

View file

@ -335,7 +335,6 @@ GEM
activesupport (>= 2) activesupport (>= 2)
nokogiri (~> 1.4) nokogiri (~> 1.4)
htmlentities (4.3.4) htmlentities (4.3.4)
http_parser.rb (0.5.3)
httparty (0.13.7) httparty (0.13.7)
json (~> 1.8) json (~> 1.8)
multi_xml (>= 0.5.2) multi_xml (>= 0.5.2)
@ -672,7 +671,6 @@ GEM
redis-namespace (>= 1.5.2) redis-namespace (>= 1.5.2)
rufus-scheduler (>= 2.0.24) rufus-scheduler (>= 2.0.24)
sidekiq (>= 4.0.0) sidekiq (>= 4.0.0)
simple_oauth (0.1.9)
simplecov (0.12.0) simplecov (0.12.0)
docile (~> 1.1.0) docile (~> 1.1.0)
json (>= 1.8, < 3) json (>= 1.8, < 3)
@ -742,21 +740,8 @@ GEM
tilt (2.0.5) tilt (2.0.5)
timecop (0.8.1) timecop (0.8.1)
timfel-krb5-auth (0.8.3) timfel-krb5-auth (0.8.3)
tinder (1.10.1)
eventmachine (~> 1.0)
faraday (~> 0.9.0)
faraday_middleware (~> 0.9)
hashie (>= 1.0)
json (~> 1.8.0)
mime-types
multi_json (~> 1.7)
twitter-stream (~> 0.1)
turbolinks (2.5.3) turbolinks (2.5.3)
coffee-rails coffee-rails
twitter-stream (0.1.16)
eventmachine (>= 0.12.8)
http_parser.rb (~> 0.5.1)
simple_oauth (~> 0.1.4)
tzinfo (1.2.2) tzinfo (1.2.2)
thread_safe (~> 0.1) thread_safe (~> 0.1)
u2f (0.2.1) u2f (0.2.1)
@ -981,7 +966,6 @@ DEPENDENCIES
teaspoon-jasmine (~> 2.2.0) teaspoon-jasmine (~> 2.2.0)
test_after_commit (~> 0.4.2) test_after_commit (~> 0.4.2)
thin (~> 1.7.0) thin (~> 1.7.0)
tinder (~> 1.10.0)
turbolinks (~> 2.5.0) turbolinks (~> 2.5.0)
u2f (~> 0.2.1) u2f (~> 0.2.1)
uglifier (~> 2.7.2) uglifier (~> 2.7.2)

View file

@ -1,4 +1,6 @@
class CampfireService < Service class CampfireService < Service
include HTTParty
prop_accessor :token, :subdomain, :room prop_accessor :token, :subdomain, :room
validates :token, presence: true, if: :activated? validates :token, presence: true, if: :activated?
@ -29,18 +31,53 @@ class CampfireService < Service
def execute(data) def execute(data)
return unless supported_events.include?(data[:object_kind]) return unless supported_events.include?(data[:object_kind])
room = gate.find_room_by_name(self.room) self.class.base_uri base_uri
return true unless room
message = build_message(data) message = build_message(data)
speak(self.room, message, auth)
room.speak(message)
end end
private private
def gate def base_uri
@gate ||= Tinder::Campfire.new(subdomain, token: token) @base_uri ||= "https://#{subdomain}.campfirenow.com"
end
def auth
# use a dummy password, as explained in the Campfire API doc:
# https://github.com/basecamp/campfire-api#authentication
@auth ||= {
basic_auth: {
username: token,
password: 'X'
}
}
end
# Post a message into a room, returns the message Hash in case of success.
# Returns nil otherwise.
# https://github.com/basecamp/campfire-api/blob/master/sections/messages.md#create-message
def speak(room_name, message, auth)
room = rooms(auth).find { |r| r["name"] == room_name }
return nil unless room
path = "/room/#{room["id"]}/speak.json"
body = {
body: {
message: {
type: 'TextMessage',
body: message
}
}
}
res = self.class.post(path, auth.merge(body))
res.code == 201 ? res : nil
end
# Returns a list of rooms, or [].
# https://github.com/basecamp/campfire-api/blob/master/sections/rooms.md#get-rooms
def rooms(auth)
res = self.class.get("/rooms.json", auth)
res.code == 200 ? res["rooms"] : []
end end
def build_message(push) def build_message(push)

View file

@ -0,0 +1,22 @@
{
"rooms": [
{
"name": "test-room",
"locked": false,
"created_at": "2009/01/07 20:43:11 +0000",
"updated_at": "2009/03/18 14:31:39 +0000",
"topic": "The room topic\n",
"id": 123,
"membership_limit": 4
},
{
"name": "another room",
"locked": true,
"created_at": "2009/03/18 14:30:42 +0000",
"updated_at": "2013/01/27 14:14:27 +0000",
"topic": "Comment, ideas, GitHub notifications for eCommittee App",
"id": 456,
"membership_limit": 4
}
]
}

View file

@ -0,0 +1,22 @@
{
"rooms": [
{
"name": "test-room-not-found",
"locked": false,
"created_at": "2009/01/07 20:43:11 +0000",
"updated_at": "2009/03/18 14:31:39 +0000",
"topic": "The room topic\n",
"id": 123,
"membership_limit": 4
},
{
"name": "another room",
"locked": true,
"created_at": "2009/03/18 14:30:42 +0000",
"updated_at": "2013/01/27 14:14:27 +0000",
"topic": "Comment, ideas, GitHub notifications for eCommittee App",
"id": 456,
"membership_limit": 4
}
]
}

View file

@ -39,4 +39,62 @@ describe CampfireService, models: true do
it { is_expected.not_to validate_presence_of(:token) } it { is_expected.not_to validate_presence_of(:token) }
end end
end end
describe "#execute" do
let(:user) { create(:user) }
let(:project) { create(:project) }
before do
@campfire_service = CampfireService.new
allow(@campfire_service).to receive_messages(
project_id: project.id,
project: project,
service_hook: true,
token: 'verySecret',
subdomain: 'project-name',
room: 'test-room'
)
@sample_data = Gitlab::PushDataBuilder.build_sample(project, user)
@rooms_url = 'https://verySecret:X@project-name.campfirenow.com/rooms.json'
@headers = { 'Content-Type' => 'application/json; charset=utf-8' }
end
it "calls Campfire API to get a list of rooms and speak in a room" do
# make sure a valid list of rooms is returned
body = File.read(Rails.root + 'spec/fixtures/project_services/campfire/rooms.json')
WebMock.stub_request(:get, @rooms_url).to_return(
body: body,
status: 200,
headers: @headers
)
# stub the speak request with the room id found in the previous request's response
speak_url = 'https://verySecret:X@project-name.campfirenow.com/room/123/speak.json'
WebMock.stub_request(:post, speak_url)
@campfire_service.execute(@sample_data)
expect(WebMock).to have_requested(:get, @rooms_url).once
expect(WebMock).to have_requested(:post, speak_url).with(
body: /#{project.path}.*#{@sample_data[:before]}.*#{@sample_data[:after]}/
).once
end
it "calls Campfire API to get a list of rooms but shouldn't speak in a room" do
# return a list of rooms that do not contain a room named 'test-room'
body = File.read(Rails.root + 'spec/fixtures/project_services/campfire/rooms2.json')
WebMock.stub_request(:get, @rooms_url).to_return(
body: body,
status: 200,
headers: @headers
)
# we want to make sure no request is sent to the /speak endpoint, here is a basic
# regexp that matches this endpoint
speak_url = 'https://verySecret:X@project-name.campfirenow.com/room/.*/speak.json'
@campfire_service.execute(@sample_data)
expect(WebMock).to have_requested(:get, @rooms_url).once
expect(WebMock).not_to have_requested(:post, /#{speak_url}/)
end
end
end end