«Gerrit Code Review»: краткое руководство с картинками

в 8:59, , рубрики: badoo, code review, gerrit, Git, баду, Блог компании Badoo, разработка, метки: , , , ,

«Gerrit Code Review»: краткое руководство с картинками
Red and Blue Chair by Gerrit Rietveld (1918)

В компании «Badoo» есть отдел C/C++-программистов. Отдел довольно небольшой, и потому его сотрудники обычно работают над разными проектами, которые между собой пересекаются только в исключительных случаях.

Одним из негативных последствий такой ситуации является bus factor, который стремится к единице. Для решения этой и других проблем было решено в порядке эксперимента внедрить систему ревизии кода (англ. code review): назначить одного разработчика ревизором у другого и таким образом познакомить его с кодом, а заодно и повысить качество последнего.

Были сформированы основные требования к системе ревизии кода:

  • локальная установка;
  • минимум усилий на установку и администрирование;
  • максимальное удобство пользования;
  • разграничение доступа к проектам;
  • поддержка Git;
  • бесплатность (ввиду экспериментального статуса этого проекта).

После рассмотрения нескольких вариантов (Rietveld, ReviewBoard, Gerrit) нам показалось, что Gerrit проще всего поставить и подготовить к работе. Поэтому мы решили составить небольшое руководство по использованию этой системы.

Экскурс в историю

Как это часто бывает в мире открытых исходников, Gerrit появился в виде набора патчей к другому проекту. Изначальной целью было добавить поддержку ACL в Rietveld — систему ревизии кода, которую написал на Python автор самого Python Гвидо ван Россум (нидерл. Guido van Rossum). Из-за того, что Гвидо не захотел усложнять код Rietveld, появился «форк» последнего под названием Gerrit.

В дальнейшем Gerrit был переписан с Python на Java и таким образом стал совершенно самостоятельным проектом. На данный момент Gerrit используют такие компании и проекты как «eBay», «Sony», «Couchbase», «MediaWiki», «Rockbox» и «Qt», но самым известным пользователем Gerrit, вероятно, является проект по разработке Android, для которого Gerrit и был написан.

Кстати, здесь можно найти объяснение имени проекта: http://en.wikipedia.org/wiki/Gerrit_Rietveld.

Принцип работы

Разработка с использованием Gerrit выглядит следующим образом:

  • создаётся репозиторий в Gerrit;
  • разработчик клонирует репозиторий из Gerrit (или добавляет git remote в уже существующий проект);
  • с помощью git push разработчик отправляет изменения для ревизии кода в специальную ветвь репозитория;
  • для каждой записи изменения Gerrit создаёт отдельный «тикет», который ревизор может откомментировать, применить или отвергнуть.

С помощью настройки системы доступа в Gerrit можно запретить разработчику отправлять изменения в обход ревизии кода и оставить это право только ревизору, что нам очень подходит: это значит, что ревизор будет видеть все изменения и (теоретически, конечно) будет знаком со всем кодом проекта.

Установка и настройка

Дистрибутив Gerrit распространяется в виде WAR-архива, поэтому его установка выглядит довольно просто: создать базу (поддерживаются MySQL, PostgreSQL и встроенная H2), добавить пользователя в систему, проинициализировать сайт и настроить веб-сервер. В «Badoo» традиционно используется nginx, поэтому мы настроили именно его. В nginx.conf это выглядит примерно так:

  server {
       	listen 80;
       	server_name gerrit;
       	rewrite  ^(.*)  https://$server_name$1 permanent;
	}

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

       	ssl on;
       	ssl_certificate  /local/nginx/conf/cert/gerrit.crt;
       	ssl_certificate_key  /local/nginx/conf/cert/gerrit.key;

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

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

       	location / {
               	proxy_pass   http://127.0.0.1:8080;
               	proxy_set_header X-Forwarded-For $remote_addr;
               	proxy_set_header Host $host;
               	auth_basic        	"Restricted";
               	auth_basic_user_file  htpasswd;
       	}


	}

Установка подробно описана в документации, поэтому вдаваться в детали не будем, вместо этого перейдём сразу к описанию веб-интерфейса Gerrit.

Вот так выглядит первая страница Gerrit сразу после начальной установки:

«Gerrit Code Review»: краткое руководство с картинками

Тут самое время сказать, что какую-либо локальную авторизацию Gerrit на данный момент не поддерживает. Есть поддержка OpenID, HTTP Basic/Digest Authentication и Computer Associates Siteminder (коммерческое «single sign-on» решение), и это всё. Решение использовать внешнюю авторизацию довольно логично для проектов с открытым участием, но в нашем случае HTTP Auth — единственно возможный вариант, несмотря на его сомнительное удобство.

Начало работы с Gerrit

После регистрации в системе путём добавления e-mail и публичного ключа для SSH, можно приступать к работе.

Для начала нужно создать новый проект в Gerrit. К сожалению, возможности сделать это через веб-интерфейс нет. В процессе написания статьи вышла версия Gerrit 2.3, в которой это упущение исправлено и, наконец, можно создать новый репозиторий прямо из веб-интерфейса: AdminProjectsCreate new project:

«Gerrit Code Review»: краткое руководство с картинками

В форме создания проекта можно сразу выбрать, какие права наследовать — это пригодится при создании проектов с типовыми правами. По умолчанию наследуются общие права (All-Projects).

Так же можно указать дополнительные настройки проекта:

«Gerrit Code Review»: краткое руководство с картинками

Переходим в консоль и непосредственно к работе с Git:

$ git clone ssh://gerrit:29418/test_project.git
Cloning into test_project...
warning: remote HEAD refers to nonexistent ref, unable to checkout.

Предупреждение можно игнорировать, оно вполне обосновано (репозиторий не содержит ни одной ревизии), но для нас совершенно бесполезно. Не удивляйтесь странному порту 29418 — у Gerrit свой собственный SSH-сервер и своя реализация Git (JGit на Java).

Создадим первый файл и первую ревизию кода:

$ cd test_project
$ echo “test” > README
$ git add README
$ git commit README -m “first commit”
[master (root-commit) b1f69cf] first commit
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 README

Права по умолчанию для всех проектов не позволяют отправлять изменения на сервер в обход системы ревизии кода, поэтому команда `git push origin master` на данном этапе завершится с такой ошибкой:

$ git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 224 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To ssh://gerrit:29418/test_project.git
! [remote rejected] master -> master (can not create new references)
error: failed to push some refs to 'ssh://gerrit:29418/test_project.git'

И это правильно, ведь наша цель как раз сделать так, чтобы ревизор всегда просматривал и одобрял код. Поэтому отправлять изменения на сервер надо следующим образом:

$ git push origin HEAD:refs/for/master
Counting objects: 3, done.
Writing objects: 100% (3/3), 224 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
remote:
remote: New Changes:
remote:   https://gerrit/337
remote:
To ssh://gerrit:29418/test_project.git
* [new branch]  	HEAD -> refs/for/master

Тут следует заметить, что синтаксис команды, мягко говоря, не самый удобный. Однако это легко исправляется с помощью такой настройки:

$ git config branch.master.merge refs/for/master

Теперь изменение успешно ушло на сервер, но сразу в репозиторий не попало. Вместо этого создалось изменение с идентификатором 337 на сервере, которое можно просмотреть и одобрить через веб-интерфейс Gerrit (обратите внимание на ссылку в выводе Gerrit):

«Gerrit Code Review»: краткое руководство с картинками

На данном снимке экрана можно увидеть все параметры и действия конкретного изменения. При желании можно добавить дополнительного ревизора (в этом случае он получит извещение), рассмотреть (Review) или отвергнуть изменение (Abandon Change). Тут же присутствуют готовые тексты команд для быстрого «copy/paste»: checkout проекта, pull, cherry-pick или получение патча данного изменения.

Естественно, к каждому изменению можно добавлять комментарии, делается это на странице Review — перейдём к ней.

«Gerrit Code Review»: краткое руководство с картинками

Здесь можно увидеть непосредственно форму оценки изменения. Обратите внимание, что на данном снимке присутствуют только 3 (-1/0/+1) возможных оценки из 5 (-2/-1/0/+1/+2). Так произошло, потому что наш тестовый пользователь Philip J. Fry не обладает правом решающего голоса на этот проект.

Оценки -1/+1 имеют рекомендательный статус, на принятие или непринятие изменения они не влияют, поэтому по умолчанию все зарегистрированные пользователи имеют право их ставить. Решающими являются оценки -2 и +2 (нет, -1/+1 не суммируются, но это можно сделать с помощью автоматического скрипта) — любая оценка +2 позволяет применить изменение, любая оценка -2 блокирует изменение и оно не может быть применено до её снятия (несмотря на присутствие любого количества +2). Подробное описание системы голосов есть в документации.

Дадим право решающего нашему пользователю и заодно проиллюстрируем систему прав в Gerrit. Для начала надо создать группу, которой мы разрешим оценивать изменения нашего проекта. Для этого заходим в закладку Groups, там в самом низу находим форму создания новой группы. Наш тестовый пользователь будет автоматически добавлен в участники этой группы, но если нужно добавить кого-либо еще, то просто начинайте печатать его имя, и Gerrit покажет вам подсказку:

«Gerrit Code Review»: краткое руководство с картинками

После этого новой группе Test Reviewers нужно выдать право принимать или отвергать изменения в этот проект. Во вкладке Projects выбираем наш проект, вкладку Access, далее нажимаем кнопку Edit:

«Gerrit Code Review»: краткое руководство с картинками

На этой странице можно изменить права и их параметры. В нашем случае мы выдаем право ставить оценку (Label Code-Review) от -2 до +2 группе Test Reviewers, и это право распространяется на все ветви проекта. Заодно этой же группе дадим и право применять изменения (Submit). После добавления новых привилегий возвращаемся на страницу изменения. Теперь на ней отображается больше опций:

«Gerrit Code Review»: краткое руководство с картинками

Как вы можете заметить, во-первых, у нашего пользователя теперь есть возможность поставить любые оценки изменению, включая решающие +2 и -2. И во-вторых, появилась кнопка Publish and Submit, которая позволяет нашему пользователю применить изменение.

Система привилегий

В Gerrit присутствует сложная система привилегий. Каждую привилегию можно выдать группе (или группам) пользователей, и вместе с тем ограничить радиус её действия рамками конкретной ветви репозитория. При этом администраторы могут создавать новые привилегии (в документации приводится пример с проверкой копирайта).

Список привилегий, которые доступны по-умолчанию:
* Label Verified — возможность помечать изменения как проверенные.
Эта категория была добавлена специально для проекта Android и означает, что изменение не ломает сборку проекта и проходит тесты. Нам эта категория не пригодилась, как убрать её описано в документации.
* Label Code Review — непосредственно ревизия кода с возможностью указать диапазон доступных оценок (от -2 до +2).
* Create reference — возможность создавать ссылки, ветви и тэги в репозитории.
* Forge author/Forge committer/Forge server — возможность «подделывать» изменения от других людей. Обычно Gerrit требует, чтобы e-mail автора изменения совпадал с одним из зарегистрированных адресов, но это можно обойти при наличии данной привилегии. Обычно она нужна только на время импорта уже существующего репозитория в Gerrit.
*Owner — даёт право выдавать/менять привилегии на данный проект, менять описание проекта, удалять и создавать ветви в репозитории (только через веб-интерфейс).
*Push — право на запись изменения (англ. commit) в репозиторий. Привилегия на commit в refs/* даёт право добавлять изменения напрямую в репозиторий, в обход системы ревизии кода.
*Push Merge Commit — дополнение к Push, разрешающее пользователю проводить слияния ветвей.
*Push Annotated Tag — еще одно дополнение к Push, на этот раз разрешающее добавлять в репозиторий тэги.
*Read — право на чтение кода в репозитории, изменений в системе и комментариев к ним; по умолчанию разрешено всем пользователям, которые зарегистрированы в системе.
*Submit — право на применение изменений в репозитории.

Исходя из наших целей, мы подобрали вот такую оптимальную конфигурацию для наших проектов:

«Gerrit Code Review»: краткое руководство с картинками

Таким образом «коммиттеры» могут добавлять слияния веток в ту часть репозитория, которая предназначена для ревизии кода (но не напрямую в репозиторий), создавать тэги и сами изменения для их дальнейшего рассмотрения. А ревизоры могут рассматривать изменения и применять их.

Вместо заключения

Gerrit оставил довольно неоднозначные впечатления у автора данной статьи.

С одной стороны, его некоторые возможности неочевидны, неудобны или же вообще не существуют, что в целом сильно напоминает тот странный стул, который изображен в заглавии статьи. Например, удалить группу из интерфейса нельзя, код проекта посмотреть возможности нет, до недавнего времени нельзя было даже создать новый проект из браузера, только через SSH. И многие административные функции приходится делать напрямую в базе данных, что чревато проблемами. Отсутствие какого-либо управления пользователями в самом Gerrit тоже не радует. В общем, недостатков много, что подтверждает этот список.

С другой стороны, свою непосредственную функцию Gerrit успешно выполняет, и после некоторого времени, затраченного на первичное знакомство и настройку, не требует никакого внимания со стороны разработчиков.

В заключение надо также признать, что изначальная цель, с которой мы внедряли Gerrit, так и не была выполнена — бесполезно пытаться «познакомить» с кодом разработчика, который только просматривает его, но не участвует в обсуждении проекта и не понимает, почему код такой, какой он есть. Но система ревизии кода прекрасно работает в случае уже существующего проекта, где разработчиков можно разделить на «владельцев», которые отвечают за проект в целом и рассматривают изменения других, и «участников», которые могут присылать свои изменения к проекту без возможности применять их напрямую. Поэтому, несмотря на все свои недостатки, наш отдел принял Gerrit на вооружение и успешно использует его для всех текущих проектов.

Антон Довгаль, разработчик
компания «Badoo»

Автор: Badoo

* - обязательные к заполнению поля