Sunday, October 12, 2014

GitHub API exercises: location and reputation

Location, location, language

So I've found myself in need of location-specific GitHub users lookup. No problem, right? ?q=location:{location} and off we pop. Not so, friends. While GitHub's search serves based on its own notion of priority, what if I'm looking for Romania-based devs who primarily contribute to Haskell repositories? No, but bear with me: it's 30 minutes of work for someone versed in GH's API. Until Friday, I wasn't one of those. Now I'm 2% closer.

What I'm dealing with so far is this:

  1. Make a request to GH for {location}
  2. For each result, make a request to GH for {user}
  3. Make a request for {user/repos}
  4. For each result, grab language
  5. Count language
  6. Output the biggest result
Straightforward, if I'm not concerned about the user contributing a .css file to a Ruby repo. Let's save that for later.

So of course I could go with this approach, cache those JSONs and filter them at my own chaotic will. Check for changes on a leisurely schedule. Go on my merry way.

Prestige index

What are some relevant metrics of a user's contributions on GH? In an ideal case we're dealing with an open-source contributor whose best works are public. 
  • Number of owned repositories [OR]
  • Number of stars on ORs
  • Number of issues on ORs
  • Number of pull requests on ORs
  • Number of repositories committed to [CR]
  • Number of commits to CRs
  • Number of forks merged into CRs
  • Number of followers
I'm not including activity into this because I'm not a sociologist. 
What is the relationship? I would say that resolved issues on OR are a solid metric; also, forks of highly-popular repos being merged into the master. I'm certainly missing a ton of things here, but let's say that we're looking for a 0 to 10 score as our final output: how do we put these together?

My initial approach was highly unsatisfactory. At some point, this happened in my calculate-score-per-repo function:

crunchIt.prototype.getScore = function() {
    return this.ns*(this.nf/this.nw);
}

ns = number of stars
nf = number of forks
nw = number of watchers

Naturally I got mathslapped and cowered in a corner, shamed. Who cares about the ratio of forks and watchers? And why should it have the ability to reduce the score of a well-starred repo?

I was wrong and I am ashamed.

So, now I am looking for an actually reasonable way to do this. 

Disclaimer: the 'prestige index' is an exercise meant to give some sort of reasonable result for active GH contributors. Even when it's done it will not be a value judgment.