Wednesday, January 8, 2014

How to get statistics about your contributions on a GitHub organization

GitHub, the web-based hosting service for software development projects, lets you check statistics on your contributions on specific projects easily.

You can check, for instance, the statistics on collective.cover just by visiting the following page:

https://github.com/collective/collective.cover/graphs/contributors

GitHub gives you a count of commits and a visual representation of them among time.

If you want to check only the number of commits by author, you could use the git-shortlog command:

(python-2.7)# hvelarde@nanovac (master u=) ~/collective/cover
# git shortlog -s | sort -nr
697 hvelarde
312 Juan Pablo Giménez
91 Héctor Velarde
78 Franco Pellegrini
76 Marcos F. Romero
71 quimera
71 Cleber J Santos
66 Gonzalo Almeida
62 Érico Andrei
61 Silvestre Huens
47 Maurits van Rees
32 Andre Nogueira
30 Kuno Woudt
20 Carlos de la Guardia
13 Tamosauskas
10 Thiago Curvelo
10 Davi Lima
9 Denis Krienbühl
8 tzicatl
8 Rodrigo Ferreira de Souza
8 JeanMichel FRANCOIS
7 Leonardo Rochael Almeida
5 Giorgio Borelli
5 André Nogueira
4 Juan A. Diaz
4 Fulvio Casali
4 Asko Soukka
3 lpmayos
3 Fabiano Weimar dos Santos
3 Espen Moe-Nilssen
3 Davi Lima de Medeiros
2 Takeshi Yamamoto
2 sven
2 Ricardo Bánffy
2 paul
2 Denis Bitouzé
2 Alex Clark
1 root
1 Rodrigo Ristow
1 Paul Roeland
1 Manabu TERADA
1 Malthe Borch
1 Leonardo J. Caballero G
1 Felipe Duardo
1 Emmanuelle Helly
1 adam139
1 Adam
The -s option gives you a summary output and the sort command shows the information sorted in reverse order (-nr).

You could improve this listing by using the .mailmap feature to add commits belonging to the same author using two different email addresses.

Image now that you want to get a list of all your contributions on a specific organization, lets say, the Plone collective.

Enter the GitHub API and github3.py, a Python wrapper for it.

Until today, the Plone collective has more that 1.1k repositories so we need to use the authenticated access to the API to avoid depletion of requests (rate limit allow us to make up to 60 requests per hour for unauthenticated requests and 5,000 for authenticated requests). In this specific example we used 1,171 requests to the API.

>>> user, password = 'hvelarde', 'password'
>>> from github3 import login
>>> g = login(user, password=password)
>>> o = g.organization('collective')
>>> g.ratelimit_remaining
3369
>>> my_stats = []
>>> for r in o.iter_repos():
... for c in r.iter_contributor_statistics():
... if user in repr(c.author):
... my_stats.append((r.name, c.total))
...
>>> g.ratelimit_remaining
2198
>>> len(my_stats)
74
>>> sum([total for repo, total in my_stats])
2975
>>> import operator
>>> my_stats = sorted(my_stats, key=operator.itemgetter(1), reverse=True)
>>> from pprint import pprint
>>> pprint(my_stats)
[(u'collective.cover', 607),
(u'collective.nitf', 456),
(u'collective.polls', 221),
(u'collective.z3cform.widgets', 175),
(u'collective.upload', 139),
(u'collective.newsflash', 97),
(u'collective.elections', 95),
(u'collective.syndication', 84),
(u'collective.weather', 78),
(u'collective.prettydate', 65),
(u'collective.disqus', 62),
(u'collective.newsticker', 59),
(u'collective.behavior.localdiazo', 58),
(u'sc.social.like', 53),
(u'sc.contentrules.groupbydate', 46),
(u'collective.facebook.portlets', 43),
(u'buildout.plonetest', 43),
(u'collective.googlenews', 40),
(u'collective.github.com', 39),
(u'collective.aviary', 33),
(u'collective.facebook.accounts', 32),
(u'collective.twitter.portlets', 31),
(u'collective.portlet.twitter', 26),
(u'Products.ImageEditor', 22),
(u'collective.portlet.calendar', 22),
(u'Products.PloneKeywordManager', 21),
(u'collective.behavior.localregistry', 19),
(u'collective.twitter.accounts', 18),
(u'collective.googleanalytics', 18),
(u'plone.app.imagecropping', 18),
(u'collective.developermanual', 14),
(u'Products.windowZ', 13),
(u'Products.ATGoogleVideo', 13),
(u'ploneawards.contenttypes', 12),
(u'Solgema.fullcalendar', 11),
(u'collective.z3cform.datetimewidget', 10),
(u'Products.EasyNewsletter', 10),
(u'collective.documentviewer', 10),
(u'collective.addthis', 9),
(u'collective.z3cform.datagridfield', 9),
(u'collective.portlet.usertrack', 9),
(u'ploneawards.buildout', 9),
(u'qi.portlet.TagClouds', 8),
(u'collective.lineage', 7),
(u'collective.portlet.pythonscript', 7),
(u'collective.themecustomizer', 7),
(u'collective.routes', 6),
(u'Products.Faq', 6),
(u'dexterity.membrane', 6),
(u'collective.recipe.cmd', 6),
(u'cioppino.twothumbs', 5),
(u'collective.facebook.wall', 5),
(u'templer.core', 5),
(u'collective.recipe.omelette', 5),
(u'example.conference', 4),
(u'collective.formwidget.relationfield', 4),
(u'templer.buildout', 4),
(u'i18ndude', 4),
(u'ploneawards.theme', 4),
(u'ploneawards.policy', 4),
(u'collective.oembed', 3),
(u'collective.twitter.search', 3),
(u'templer.plone', 3),
(u'collective.blog.star', 3),
(u'collective.easytemplate', 3),
(u'collective.timedevents', 3),
(u'collective.stats', 2),
(u'collective.recipe.plonesite', 2),
(u'collective.portlet.relateditems', 2),
(u'templer.plonebuildout', 1),
(u'templer.zope', 1),
(u'templer.silva', 1),
(u'collective.panels', 1),
(u'collective.portlet.tal', 1)]
>>>

Using github3.py we iterate over all of the organization repositories and get information of each one only if my user name is listed among the contributors. We get the results as a list of tuples (repo, total).

After that we sort the list in reverse order using the total commits as the key and make the sum of all commits in general.

As you can see I have contributed to 74 repositories on the Plone collective making 2,975 commits in total.

Not bad, isn't it? :-)

No comments:

Post a Comment