{"id":1099,"date":"2010-03-12T19:46:11","date_gmt":"2010-03-13T00:46:11","guid":{"rendered":"http:\/\/mikeconley.ca\/blog\/?p=1099"},"modified":"2023-12-20T16:25:17","modified_gmt":"2023-12-20T21:25:17","slug":"reviewboard-extensions-a-state-of-affairs","status":"publish","type":"post","link":"https:\/\/mikeconley.ca\/blog\/2010\/03\/12\/reviewboard-extensions-a-state-of-affairs\/","title":{"rendered":"ReviewBoard Extensions:  A State of Affairs"},"content":{"rendered":"<p>One of my potential research experiments involves augmenting <a href=\"http:\/\/www.reviewboard.org\">ReviewBoard<\/a>, and so, I&#8217;ve been studying the ReviewBoard code.<\/p>\n<p>I want to give ReviewBoard the ability to record certain statistics &#8211; for example, the number of defects in a review request, number of defects found per reviewer, defect density, inspection rate, etc&#8230;<\/p>\n<p>It turns out I&#8217;m not the only one who wants this to happen.\u00a0 <a href=\"http:\/\/groups.google.com\/group\/reviewboard\/browse_thread\/thread\/e224b4afce4a8cfc\/ca948e915c5b979b?lnk=gst&amp;q=metrics#ca948e915c5b979b\">Check out this thread<\/a>.<\/p>\n<p>So it turns out that the devs building ReviewBoard are <a href=\"http:\/\/www.chipx86.com\/blog\/2009\/04\/02\/review-board-summer-of-code-roadmap-and-future-plans\/\">planning on integrating an extension framework<\/a>.\u00a0 Theoretically, users could then write their own extensions to customize ReviewBoard as they see fit.\u00a0 Think WordPress plugins, but for a code review tool.\u00a0 Neat.<\/p>\n<p>According to the above link:<\/p>\n<blockquote><p>A lot of this [extension framework] already exists in a private development branch, and it will be one of our primary focuses as soon as 1.0 goes out.<\/p><\/blockquote>\n<p>However, I found the following quote from <a href=\"http:\/\/groups.google.com\/group\/reviewboard-dev\/browse_thread\/thread\/d6e1d47328eed56d\">a relatively recent mailing list message<\/a>:<\/p>\n<blockquote><p>[with regards to the extensions framework]&#8230;We have to finish building it, testing<br \/>\nit, getting other features we have planned into the release, and performing<br \/>\nthe release. <strong>So, we&#8217;re looking at a year or more<\/strong>. But I don&#8217;t see how we&#8217;d<br \/>\nget the functionality you want short-term.<\/p><\/blockquote>\n<p>Hrmph.\u00a0 My thinking:\u00a0 maybe I can help them with it, and we can crank this puppy out sooner.<\/p>\n<p>So where is this private branch?\u00a0 It actually took a little bit of detective work&#8230;<\/p>\n<h4>Detective Work<\/h4>\n<p>I started by looking at the <a href=\"http:\/\/www.github.com\/reviewboard\/reviewboard\">ReviewBoard repo on Github<\/a>, which I assumed that the extensions branch would fork from.<\/p>\n<p>I was right &#8211; <a href=\"http:\/\/github.com\/reviewboard\/reviewboard\/network\">check out the fork network<\/a>.\u00a0 There&#8217;s <a href=\"http:\/\/github.com\/davidt\/reviewboard\/tree\/extensions\">a branch helpfully labeled &#8220;extensions&#8221;<\/a> forked by <a href=\"http:\/\/www.github.com\/davidt\">davidt<\/a>, one of the ReviewBoard devs.<\/p>\n<p>Two observations:<\/p>\n<ol>\n<li>This fork hasn&#8217;t been updated in about a month<\/li>\n<li><a href=\"http:\/\/github.com\/davidt\/reviewboard\/tree\/extensions\/reviewboard\/extensions\/\">The extensions stuff<\/a> references stuff from <a href=\"http:\/\/www.chipx86.com\/blog\/2008\/02\/29\/django-development-with-djblets\/\">Djblets<\/a> which doesn&#8217;t exist in the <a href=\"http:\/\/github.com\/djblets\/djblets\">Djblets master branch<\/a><\/li>\n<\/ol>\n<p>So I perform the same exercise &#8211; I glance at the <a href=\"http:\/\/github.com\/djblets\/djblets\/network\">Djblets fork network<\/a>, and see the handily named <a href=\"http:\/\/github.com\/davidt\/djblets\/tree\/extensions\">&#8220;extensions&#8221; fork that is in davidt&#8217;s git repo<\/a>.\u00a0 Nice.<\/p>\n<p>Ok, so those are the forks\/branches that I&#8217;m going to grab.<\/p>\n<h4>A Fluke<\/h4>\n<p>So, funny story:\u00a0 I was able to get this &#8220;extension&#8221; version of ReviewBoard working on my work machine.\u00a0 But it was by a complete fluke &#8211; this extension version of Djblets is actually missing some pieces.\u00a0 The only reason it worked for me was because I accidentally ran with the master checkout of Djblets first.\u00a0 This errored out, and also generated a bunch of compiled Python.\u00a0 I then switched to the extensions branch, which <em>left the compiled Python behind<\/em>.\u00a0 The compiled Python filled all of the missing pieces that are in the extensions branch of Djblets, and so it ran.<\/p>\n<p>For a guy who is pretty new to both Git and Django, I found that problem pretty frustrating to track down.\u00a0 Especially when I started writing up the checkout instructions&#8230; big thanks to <a href=\"http:\/\/zuzelvp47uoft.wordpress.com\/\">Zuzel<\/a> for her invaluable (and patient) Django guidance.<\/p>\n<p>Anyhow, if you&#8217;re interested in the steps to <em>failure<\/em>, here they are&#8230;<\/p>\n<h4>Setting Up (for failure)<\/h4>\n<p>I&#8217;m running Ubuntu Karmic.\u00a0 I have Git installed.<\/p>\n<ol>\n<li><a href=\"http:\/\/www.reviewboard.org\/docs\/codebase\/dev\/getting-started\/#gettingstarted\">First of all, this document is invaluable<\/a><\/li>\n<li>Check out <a href=\"http:\/\/django-evolution.googlecode.com\/svn\/trunk\/\">django_evolution from SVN<\/a> to some local directory<\/li>\n<li>Put path to django-evolution into PYTHONPATH (export PYTHONPATH=$PYTHONPATH:\/&#8230;\/django-evolution-read-only\/)<\/li>\n<li>Get Python Setuptools (sudo apt-get install python-setuptools)<\/li>\n<li>With easy_install, get nose, paramiko, recaptcha-client, Sphinx (sudo easy_install nose paramiko recaptcha-client sphinx)<\/li>\n<li>Clone original master Djblets repo (git clone git:\/\/github.com\/djblets\/djblets.git) and CD into djblets directory<\/li>\n<li>Add davidt&#8217;s remote Djblets branch (git remote add davidt git:\/\/github.com\/davidt\/djblets.git)<\/li>\n<li>Fetch davidt&#8217;s repo\u00a0 (git fetch davidt)<\/li>\n<li>Track davidt&#8217;s extension branch for djblets (git branch extensions davidt\/extensions)<\/li>\n<li>In djblets root dir, type:\u00a0 sudo python setup.py develop<\/li>\n<li>This should install Django too.\u00a0 The ReviewBoard install doc says to install from Subversion, but this will do for now.<\/li>\n<li>Clone ReviewBoard git repo (git clone git:\/\/github.com\/reviewboard\/reviewboard.git) and Cd into it<\/li>\n<li>Add davidt&#8217;s remote Reviewboard branch (git remote add davidt git:\/\/github.com\/davidt\/reviewboard.git)<\/li>\n<li>Fetch davidt&#8217;s repo\u00a0 (git fetch davidt)<\/li>\n<li>Track davidt&#8217;s extensions branch of reviewboard (git branch extensions davidt\/extensions)<\/li>\n<li>Switch to extensions branch (git checkout extensions)<\/li>\n<li>So reviewboard\/reviewboard\/extensions should have stuff in it.<\/li>\n<li>python .\/contrib\/internal\/prepare-dev.py<\/li>\n<li>Manually create the directory reviewboard\/reviewboard\/htdocs\/media\/ext.\u00a0 ReviewBoard expects it and will complain if it isn&#8217;t there.<\/li>\n<li>Run .\/contrib\/internal\/devserver.sh<\/li>\n<li>Go to localhost:8080<\/li>\n<\/ol>\n<p>If you&#8217;re like me, you&#8217;ll see an error about &#8220;no module named urls&#8221;.\u00a0 This is because the extension branch of Djblets is missing urls.py in<a href=\"http:\/\/github.com\/davidt\/djblets\/tree\/extensions\/djblets\/log\/\"> its djblets\/log directory<\/a>.\u00a0 As you can see, <a href=\"http:\/\/github.com\/djblets\/djblets\/tree\/master\/djblets\/log\/\">urls.py exists in the master Djblets branch<\/a>.<\/p>\n<p>So I&#8217;ve accidentally got it running.\u00a0 But this version of ReviewBoard I&#8217;ve created is like Frankenstein&#8217;s monster &#8211; it&#8217;s a sad, stitched together monstrosity that should probably never see the light of day.<\/p>\n<p>I tried to merge the master branch of Djblets and ReviewBoard into the extensions branch, and then realized that I had <em>no idea what I was doing<\/em>.\u00a0 The last guy you want doing a merge is a guy who doesn&#8217;t know what he&#8217;s doing.<\/p>\n<p>So that&#8217;s where I stand with it.\u00a0 Kind of a sad affair, really.\u00a0 <a href=\"http:\/\/groups.google.com\/group\/reviewboard-dev\/browse_thread\/thread\/23b911d22cef987c\">I&#8217;ve posted on the ReviewBoard developer mailing list asking for some guidance<\/a>, but all is quiet so far.<\/p>\n<p>In the meantime, I&#8217;ll continue studying the code when I can.\u00a0 The extensions stuff is <em>actually pretty far along, in my opinion<\/em> &#8211; but what do I know, <em>I&#8217;ve never built one<\/em>.\u00a0 I&#8217;ll also take a peek at some other examples of extension frameworks to see what I can learn about implementation (that&#8217;s right &#8211; I&#8217;m talking about you, <a href=\"http:\/\/codex.wordpress.org\/Writing_a_Plugin\">WordPress<\/a>).<\/p>\n<p>I&#8217;ll let you know what I find.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>One of my potential research experiments involves augmenting ReviewBoard, and so, I&#8217;ve been studying the ReviewBoard code. I want to give ReviewBoard the ability to record certain statistics &#8211; for example, the number of defects in a review request, number of defects found per reviewer, defect density, inspection rate, etc&#8230; It turns out I&#8217;m not [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[454,626],"tags":[131,638,636,639,634,637,504,635],"class_list":["post-1099","post","type-post","status-publish","format-standard","hentry","category-code-reviews","category-research-computer-science-technology","tag-extensions","tag-framework","tag-gather","tag-git","tag-metrics","tag-plugins","tag-reviewboard","tag-statistics"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/prmTy-hJ","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/mikeconley.ca\/blog\/wp-json\/wp\/v2\/posts\/1099","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mikeconley.ca\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mikeconley.ca\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mikeconley.ca\/blog\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/mikeconley.ca\/blog\/wp-json\/wp\/v2\/comments?post=1099"}],"version-history":[{"count":12,"href":"https:\/\/mikeconley.ca\/blog\/wp-json\/wp\/v2\/posts\/1099\/revisions"}],"predecessor-version":[{"id":3183,"href":"https:\/\/mikeconley.ca\/blog\/wp-json\/wp\/v2\/posts\/1099\/revisions\/3183"}],"wp:attachment":[{"href":"https:\/\/mikeconley.ca\/blog\/wp-json\/wp\/v2\/media?parent=1099"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mikeconley.ca\/blog\/wp-json\/wp\/v2\/categories?post=1099"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mikeconley.ca\/blog\/wp-json\/wp\/v2\/tags?post=1099"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}