Introduce a model to abstract SCM service integration

[finishes #80208778]
Assuming I'm understanding you correctly and the difference is all based on the argument that is passed, I mean doing something like:
```ruby
def retrieve_from_github(resource, default=nil)
  @github_results ||= {}
  return @github_results[resource] if @github_results.keys.include?(resource)

  result = github_client.send(resource)
  @github_results[resource] = result
  block_given? ? yield(result) : result
end
```
I don't know how this object gets used, though. If it's an object that's available in templates, it would be surprising to me if I hit `#email` twice and found out I'd called a third-party API twice.