The Mahara project has just moved to mandatory code reviews for every commit that gets applied to core code.

Here is a description of how Gerrit Code Review, the peer-review system used by Android, was retrofitted into our existing git repository on Gitorious.

(If you want to know more about Gerrit, listen to this FLOSS Weekly interview.)

Replacing existing Gitorious committers with a robot

The first thing to do was to log into Gitorious and remove commit rights from everyone in the main repository. Then I created a new maharabot account with a password-less SSH key (stored under /home/gerrit/.ssh/) and made that new account the sole committer.

This is to ensure that nobody pushes to the repository by mistake since all of these changes would be overwritten by Gerrit.

Basic Gerrit installation

After going through the installation instructions, I logged into the Gerrit admin interface and created a new "mahara" project.

I picked the "merge if necessary" submit action because "cherry-pick" would disable dependency tracking which is quite a handy feature.

Reverse proxy using Nginx

Since we wanted to offer Gerrit over HTTPS, I decided to run it behind an Nginx proxy. This is the Nginx configuration I ended up with:

server {  
     listen 443;  
     add_header Strict-Transport-Security max-age=15768000;  

     ssl on;  
     ssl_certificate  /etc/ssl/certs/;  
     ssl_certificate_key  /etc/ssl/certs/;  

     ssl_session_timeout  5m;  
     ssl_session_cache shared:SSL:1m;  

     ssl_protocols  TLSv1;  
     ssl_ciphers  HIGH:!ADH;  
     ssl_prefer_server_ciphers   on;  

     location / {  
             proxy_set_header X-Forwarded-For $remote_addr;  
             proxy_set_header Host $host;  

Things to note:

  • An HTTP to HTTPS redirection is not provided.

  • The HSTS headers indicates to modern browsers that this URL should only be accessed via HTTPS.

  • Only strong SSL ciphers are enabled.

  • Before proxying requests to Gerrit, Nginx adds a few headers to identify the origin of the request. The Host header in particular must be present otherwise built-in Gerrit redirections will fail.

Mail setup

To enable Gerrit to email reviewers and committers, I installed Postfix and used "" as the "System mail name".

Then I added the following to /home/gerrit/mahara_reviews/etc/gerrit.config:

 email = ""

to fix the From address in outgoing emails.

Init script and cron

Following the installation instructions, I created these symlinks:

ln -s /home/gerrit/mahara_reviews/bin/ /etc/init.d/gerrit  
cd /etc/rc2.d && ln -s ../init.d/gerrit S19gerrit  
cd /etc/rc3.d && ln -s ../init.d/gerrit S19gerrit  
cd /etc/rc4.d && ln -s ../init.d/gerrit S19gerrit  
cd /etc/rc5.d && ln -s ../init.d/gerrit S19gerrit  
cd /etc/rc0.d && ln -s ../init.d/gerrit K21gerrit  
cd /etc/rc1.d && ln -s ../init.d/gerrit K21gerrit  
cd /etc/rc6.d && ln -s ../init.d/gerrit K21gerrit

and put the following settings into /etc/default/gerritcodereview:


to automatically start and stop Gerrit.

I also added a cron job in /etc/cron.d/gitcleanup to ensure that the built-in git repository doesn't get bloated:  
20 4 * * * gerrit GIT_DIR=/home/gerrit/mahara_reviews/git/mahara.git git gc --quiet

Configuration enhancements

To allow images in change requests to be displayed inside the browser, I marked them as safe in /home/gerrit/mahara_reviews/etc/gerrit.config:

[mimetype "image/*"]  
 safe = true

Another thing I did to enhance the review experience was to enable the gitweb repository browser:

apt-get install gitweb

and to make checkouts faster by enabling anonymous Git access:

  canonicalGitUrl = git://  
  scheme = ssh  
  scheme = anon_http  
  scheme = anon_git

which requires that you have a git daemon running and listening on port 9418:

apt-get install git-daemon-run  
ln -s /home/gerrit/mahara_reviews/git/mahara.git /var/cache/git/  
touch /home/gerrit/mahara_reviews/git/mahara.git/git-daemon-export-ok

Finally, I included the Mahara branding in the header and footer of each page by providing valid XHTML fragments in /home/gerrit/mahara_reviews/etc/GerritSiteHeader.html and GerritSiteFooter.html.

Initial import and replication

Once Gerrit was fully working, I performed the initial code import by using my administrator account to push the exiting Gitorious branches to the internal git repository:

git remote add gerrit ssh://  
git push gerrit 1.2_STABLE  
git push gerrit 1.3_STABLE  
git push gerrit master

Note that I had to temporarily disable "Require Change IDs" in the project settings in order to import the old commits which didn't have these.

To replicate the internal Gerrit repository back to Gitorious, I created a new /home/gerrit/mahara_reviews/etc/replication.config file:

[remote "gitorious"]  
 url =${name}.git  
 push = +refs/heads/*:refs/heads/*  
 push = +refs/tags/*:refs/tags/*

(The ${name} variable is required even when you have a single project.)

Contributor instructions

This is how developers can get a working checkout of our code now:

git clone git://  
cd mahara  
git remote add gerrit ssh://  
git fetch gerrit  
scp -p -P 29418 .git/hooks/

and this is how they can submit local changes to Gerrit:

git push gerrit HEAD:refs/for/master

Anybody can submit change requests or comment on them but make sure you do not have the Cookie Pie Firefox extension installed or you will be unable to log into Gerrit.