Created
August 4, 2015 15:19
-
-
Save ralphbean/2787025c1ee164abb731 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" Calculate "dev to release" leadtime. | |
Prints out statistics about the time between the first commit of a new feature | |
and the tag where that feature gets released. | |
Ideally, we'd like to compute the time between first commit and deployment to | |
production, but we don't have an easy way to reliably access logs of when | |
things were deployed against when they were committed in git. | |
A quick script for my talk on technical debt at Flock 2015. | |
:Author: Ralph Bean | |
:License: LGPLv2+ | |
Example output:: | |
00136296 trac-fedmsg-plugin 1 day, 13:51:36.750000 | |
00206261 pagure 2 days, 9:17:41.111111 | |
00245100 mote 2 days, 20:05:00.692308 | |
00352005 copr 4 days, 1:46:45.962121 | |
00372609 fedmsg-atomic-composer 4 days, 7:30:09.333333 | |
00451242 pkgdb2 5 days, 5:20:42.313433 | |
00481212 fedora-releng-dash 5 days, 13:40:12.142857 | |
00617381 anitya 7 days, 3:29:41 | |
00849204 fedmsg_meta_fedora_infrastructure 9 days, 19:53:24.013699 | |
01156537 fmn.rules 13 days, 9:15:37.148148 | |
01202462 mirrormanager2 13 days, 22:01:02.111111 | |
01238799 tahrir-api 14 days, 8:06:39.736842 | |
01360000 fmn.lib 15 days, 17:46:40.095238 | |
01441767 fmn.consumer 16 days, 16:29:27.869565 | |
01567893 the-new-hotness 18 days, 3:31:33.181818 | |
01672438 datanommer 19 days, 8:33:58.333333 | |
01677784 github2fedmsg 19 days, 10:03:04.500000 | |
01709390 fedocal 19 days, 18:49:50.424242 | |
01748422 fmn.web 20 days, 5:40:22.913043 | |
02043473 fedmsg 23 days, 15:37:53.052632 | |
02254484 pkgwat.api 26 days, 2:14:44.500000 | |
02759818 tahrir 31 days, 22:36:58.354839 | |
02899894 gnome-shell-extension-fedmsg 33 days, 13:31:34.200000 | |
02955532 blockerbugs 34 days, 4:58:52.421053 | |
03284851 bodhi 38 days, 0:27:31.955224 | |
03343189 fedora-tagger 38 days, 16:39:49.388889 | |
03578008 pyrasite 41 days, 9:53:28.666667 | |
03621579 resultsdb_api 41 days, 21:59:39 | |
03759724 fas 43 days, 12:22:04.271186 | |
03798244 packagedb-cli 43 days, 23:04:04.608696 | |
03929364 bugzilla2fedmsg 45 days, 11:29:24.250000 | |
04025004 resultsdb_frontend 46 days, 14:03:24.428571 | |
04462099 datagrepper 51 days, 15:28:19.769231 | |
04478169 resultsdb 51 days, 19:56:09.142857 | |
04558950 nuancier 52 days, 18:22:30.437500 | |
05383642 fedbadges 62 days, 7:27:22.909091 | |
05793006 python-fedora 67 days, 1:10:06.916667 | |
05825923 supybot-fedora 67 days, 10:18:43.333333 | |
07118009 pkgwat.cli 82 days, 9:13:29 | |
07859622 koji 90 days, 23:13:42.592593 | |
08186664 sigul 94 days, 18:04:24.888889 | |
09974324 fedora-packages 115 days, 10:38:44.875000 | |
15651235 kitchen 181 days, 3:33:55.250000 | |
""" | |
import datetime | |
import os | |
import sys | |
import arrow | |
import pygit2 | |
project = sys.argv[-1] | |
repo = pygit2.Repository(os.path.expanduser("~/devel/" + project)) | |
verbose = False | |
refs = repo.listall_references() | |
prefix = 'refs/tags/' | |
refs = [r for r in refs if r.startswith(prefix)] | |
tags = [repo.lookup_reference(r) for r in refs] | |
tags.sort(key=lambda t: t.get_object().commit_time) | |
def find_first_commit(tag, tags): | |
tag_commits = [t.get_object().id for t in tags] | |
last = tag.get_object() | |
walker = repo.walk(tag.target, pygit2.GIT_SORT_TOPOLOGICAL) | |
walker.next() | |
for commit in walker: | |
if commit.id in tag_commits: | |
return last | |
if not commit.message.startswith('Merge '): | |
last = commit | |
return last | |
deltas = [] | |
# Throw out the first one... since we rely on looking backwards to the | |
# preceding tag.. the first tag will never have that and will skew the average. | |
for tag in tags[1:]: | |
date_released = arrow.get(tag.get_object().commit_time) | |
first_commit = find_first_commit(tag, tags) | |
date_committed = arrow.get(first_commit.commit_time) | |
delta = date_released - date_committed | |
deltas.append(delta.total_seconds()) | |
if verbose: | |
print "%i, %s, %i, %s" % ( | |
tag.get_object().commit_time, | |
tag.name, | |
delta.total_seconds(), | |
delta) | |
#print "# max", max(deltas) | |
#print "# min", min(deltas) | |
if not deltas: | |
print "%012d" % 0, project, 'no tagged releases found...' | |
else: | |
average = sum(deltas) / len(deltas) | |
print "%012d" % average, project, "%s" % datetime.timedelta(seconds=average) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment