Skip to content

Commit

Permalink
[GithubService] Add username lookup
Browse files Browse the repository at this point in the history
Adds a lookup for usernames to check to see if they are valid.

- If a valid username is provided, it returns the ID of the user.
- If username is invalid, it sets the key to `nil`

Only valid users will take up an API call, hence the initial
`Net::HTTP.get_response` that is made first.  This might slow down the
call to this method overall, but it saves API calls in case someone is
providing large commit messages with many code examples included (what
this will be used for in a future commit)
  • Loading branch information
NickLaMuro committed Mar 16, 2020
1 parent 903eef8 commit 1173807
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 0 deletions.
19 changes: 19 additions & 0 deletions lib/github_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,21 @@ def refresh_assignees(fq_name)
assignees_cache.delete(fq_name)
end

def username_lookup(username)
if username_lookup_cache.key?(username)
username_lookup_cache[username]
else
username_lookup_cache[username] ||= begin
case Net::HTTP.new("github.com", 443).tap { |h| h.use_ssl = true }.request_head("/#{username}")
when Net::HTTPNotFound then nil # invalid username
when Net::HTTPOK then service.user(username)[:id]
else
raise "Error on GitHub with username lookup"
end
end
end
end

private

def service
Expand Down Expand Up @@ -151,6 +166,10 @@ def assignees_cache
@assignees_cache ||= {}
end

def username_lookup_cache
@username_lookup_cache ||= {}
end

def respond_to_missing?(method_name, include_private = false)
service.respond_to?(method_name, include_private)
end
Expand Down
63 changes: 63 additions & 0 deletions spec/lib/github_service_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
describe GithubService do
describe "#username_lookup" do
let(:lookup_username) { "NickLaMuro" }
let(:lookup_status) { 200 }

before do
# HTTP lookup
stub_request(:head, "https://github.com/#{lookup_username}")
.with(:headers => {'Accept' => '*/*', 'User-Agent' => 'Ruby'})
.to_return(:status => lookup_status, :body => "", :headers => {})
end

after do
lookup_cache.delete(lookup_username)
end

def lookup_cache
described_class.send(:username_lookup_cache)
end

context "for a valid user" do
before do
github_service_add_stub :url => "/users/#{lookup_username}",
:response_body => {'id' => 123}.to_json
end

it "looks up a user and stores the user's ID in the cache" do
expect(described_class.username_lookup(lookup_username)).to eq(123)
expect(lookup_cache).to eq("NickLaMuro" => 123)
end
end

context "for a user that is not found" do
let(:lookup_status) { 404 }

it "looks up a user and stores the user's ID in the cache" do
expect(described_class.username_lookup(lookup_username)).to eq(nil)
expect(lookup_cache).to eq("NickLaMuro" => nil)
end

it "does a lookup call only once" do
http_instance = Net::HTTP.new("github.com", 443)
fake_not_found = Net::HTTPNotFound.new(nil, nil, nil)
expect(Net::HTTP).to receive(:new).and_return(http_instance)
expect(http_instance).to receive(:request_head).once.and_return(fake_not_found)

expect(described_class.username_lookup(lookup_username)).to eq(nil)
expect(described_class.username_lookup(lookup_username)).to eq(nil)
end
end

context "when GitHub is having a bad time..." do
let(:lookup_status) { 500 }

it "looks up a user and does not stores the username in the cache" do
expect do
described_class.username_lookup(lookup_username)
end.to raise_error(RuntimeError, "Error on GitHub with username lookup")
expect(lookup_cache).to eq({})
end
end
end
end

0 comments on commit 1173807

Please sign in to comment.