Gerrit/ru

From JazzTeamWiki
Jump to: navigation, search

Краткое описание

Gerrit - это opensource приложение, которое предоставляет возможности для ревью кода приложения. С помощью gerrit вы можете оставлять комментарии для разработчиков со своими замечаниями по коду, можете отвергать чей-либо код с целью его дальнейшего улучшения или изменения в корне.

Gerrit является промежуточной системой между локальным репозиторием и удаленным репозиторием с кодом, который идет на production. Т.е. если вы делаете коммит в удаленный production-репозиторий, то он попадает туда не сразу. Сперва ваш код попадает на gerrit, где с помощью веб-интерфейса можно просмотреть ваши изменения. Затем ревьювер также просматривает ваши изменения и решает одобрить их или отвергнуть. Если изменения одобряются, то только тогда с gerrit'a они попадают в production-репозиторий. Если же ваши изменения отвергаются, то они и остаются на gerrit. Вы можете отменить их или же исправить локально и затем обратно поместить на gerrit для повторного ревью. Как видно, gerrit предоставляет очень удобный инструмент для контроля качества вашего кода и просмотра изменений в нем.

Gerrit работает, используя систему контроля версий git.

Полезные ссылки

Установка

Статья: http://scmforge.com/?p=1

Чтобы установить gerrit нужно сделать следующее:

   sudo adduser gerrit            ; создаем пользователя для gerrit
   su gerrit                      ; переключаем пользователя

Далее с репозитория нужно загрузить проект:

   git clone https://gerrit.googlesource.com/gerrit

Собрать проект с помощью Maven:

   mvn package

Для хранения данных о пользователях и других необходимых данных gerrit использует базу данных. Пример создания базы данных в MySQL:

   mysql -u [user] -p            ; запускаем консоль MySQL
   далее выполняем команды
      CREATE USER 'gerrit'@'localhost' IDENTIFIED BY 'secret';
      CREATE DATABASE reviewdb;
      ALTER DATABASE reviewdb charset=latin1;
      GRANT ALL ON reviewdb.* TO 'gerrit'@'localhost';
      FLUSH PRIVILEGES;

Теперь нужно развернуть и сконфигурировать gerrit для работы:

   java -jar gerrit-2.5-SNAPSHOT.war init -d /path/to/your/gerrit_application_directory        ; gerrit будет развернут в /path/to/your/gerrit_application_directory

Возможные проблемы и пути их решения

Ошибка "** ERROR: GERRIT_SITE not set"

Если gerrit выдает ошибку "** ERROR: GERRIT_SITE not set", то нужно сделать:

   создать файл /etc/default/gerritcodereview
   добавить в этот файл строку: GERRIT_SITE=/path/to/your/gerrit_application_directory

Ошибки при изменении/добавлении email

Для решения этой проблемы нужно вручную отредактировать email в базе данных:

   ./bin/gerrit.sh stop                 ; останавливаем gerrit
   java -jar bin/gerrit.war gsql        ; открываем консоль sql консоль gerrit'a
   SELECT * FROM account_external_ids;  ; делаем выборку из таблицы account_external_ids. Должны увидеть пользователей и их данные. Если выдается ошибка, что таблица не найдена, напишите название таблицы в верхнем регистре.
   UPDATE account_external_ids set email_address='[correct email]' where account_id=[account_id];          ; обновляем email выбранного пользователя по его account_id
   SELECT * FROM account_external_ids;  ; делаем выборку из таблицы account_external_ids и убеждаемся, что email обновлен
   \q                                   ; выходим из консоли sql
   ./bin/gerrit.sh start                ; запускаем gerrit

При обращении к gerrit возникает ошибка "500 internal server error"

Скорее всего при инициализации вы указали каталог git репозитория к которому у gerrit нет доступа. Реинициализируйте gerrit, в графе <git> введите каталог в котором будут храниться ваши gerrit проекты. Перед реинициализацией убедитесь, что у gerrit есть доступ к каталогу.

При попытке запуска gerrit выводит в консоль FAIL

Убедитесь, что каталог gerrit принадлежит тому пользователю от имени которого вы пытаетесь его запустить.

Ваших коммитов не видно на gerrit

См. Push в репозиторий gerrit'a

Полезные команды

Запуск / остановка

Для запуска/остановки используется скрипт gerrit.sh, который находится в директории: /path/to/your/gerrit_application_directory/bin.

Вид комманды:

   ./gerrit.sh [start|stop]

Проверка работы

Проверка, что gerrit работает и у вас есть доступ:

   ssh -p [port] [user]@[host]         ; пример: ssh -p 29418 skars@localhost

Клонирование репозитория

Клонирования репозитория с gerrit:

   git clone ssh://[user]@[host]:[port]/[repository_name]        ; пример: git clone ssh://skars@skars-netbook:29418/sandbox

Push в репозиторий gerrit'a

Для того, чтобы залить изменения на gerrit используется команда `git push`. По умолчанию push происходит в ветку master (это можно посмотреть с помощью `git remote origin show`). Если мы будем напрямую делать push в master, то все наши изменения будут лететь мимо gerrit'a. Для того, чтобы ваши коммиты попадали на gerrit нужно использовать команду:

   git push ssh://[host]:[port]/[project] HEAD:refs/for/master   ; пример: git push ssh://192.168.1.10:29418/sandbox HEAD:refs/for/master

Чтобы при каждом push'e не вводить адрес репозитория и название ветки нужно нужно отредактировать файл /path/to/project/.git/config:

   [core]
       repositoryformatversion = 0
       filemode = false
       bare = false
       logallrefupdates = true
       symlinks = false
       ignorecase = true
       hideDotFiles = dotGitOnly
    [remote "origin"]
       url = ssh://[user]@[host]:[port]/[project]
       fetch = +refs/heads/*:refs/remotes/origin/*
       fetch = refs/notes/review:refs/notes/review
       pushurl = ssh://[user]@[host]:[port]/[project]
       push = HEAD:refs/for/master
    [branch "master"]
       remote = origin
       merge = refs/heads/master
    [gerrit]
       createchangeid = true

Теперь вы можете использовать `git push` для отправки изменений на gerrit.

Настройка Basic Authentication

Для настройки basic авторизации нужно установить Apache2 сервер:

   sudo apt-get install -y apache2

Затем нужно изменить настройки gerrit: открываем конфигурационный gerrit

 nano /path/to/your/gerrit_application_directory/etc/gerrit.config

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


[gerrit]
       basePath = git
       canonicalWebUrl = https://host:1443 ; url, по которому мы будем заходить на gerrit. Например: http://172.31.11.34:9835/gerrit
[database]
       type = mysql
       hostname = localhost
       database = reviewdb
       username = gerrit
[auth]
       type = http
[sendemail]
       smtpServer = localhost
[container]
       user = sudoUser
       javaHome = /usr/lib/jvm/java-7-oracle/jre
[sshd]
       listenAddress = *:29418
[httpd]
       listenUrl = proxy-https://*:8082/   ; url, на который будет перенаправлять нас Apache2 после авторизации. Это тот же url, по которому доступен gerrit, если бы не было авторизации, например: proxy-http://*:9835/gerrit
[cache]
       directory = cache
                              

Cоздаем логин и пароль для пользователя, которому нужно получить доступ на gerrit через basic auth:

   sudo mkdir /etc/apache2/passwd                                        ; создаем папку для хранения файлов с логинами и паролями, которые будут использоваться при авторизации в разных приложениях
   sudo touch /etc/apache2/passwd/gerrit                                 ; создаем файл /etc/apache2/passwd/gerrit, в котором будут храниться логины и пароли для gerrit 
   sudo htpasswd /etc/apache2/passwd/gerrit [user]                       ; создаем логин и пароль для пользователя [user] и сохраняем в файле /etc/apache2/passwd/gerrit

Настраиваем Apache2: Cоздаем и открываем конфигурационный файл для Apache2. В этом файле будут настройки basic auth и доступа на gerrit

   sudo nano /etc/apache2/sites-available/gerrit

пишем следующие настройки:

<VirtualHost *:1443>
      ProxyRequests Off
      ProxyVia Off
      ProxyPreserveHost On
   <Proxy *>
         Order deny,allow
         Allow from all
   </Proxy>
   <Location /login/>
     AuthType Basic
     AuthName "Gerrit Code Review"
       AuthUserFile /etc/apache2/passwd/gerrit
     Require valid-user
   </Location>
   ProxyPass / http://localhost:8082/
</VirtualHost>

Запускаем необходимые модули Apache2:

   sudo a2enmod proxy
   sudo a2enmod proxy_http
   sudo a2enmod vhost_alias 

"Включаем" наши настройки для gerrit:

   sudo a2ensite gerrit                                  ; в папке /etc/apache2/sites-enabled появится файл gerrit с настройками, которые мы сохрании ранее

Перезапускаем Apache2:

   sudo service apache2 restart

Запускаем gerrit:

   ./path/to/your/gerrit_application_directory/bin/gerrit.sh

Если gerrit уже был запущен, то его следует перезапустить.

Теперь мы можем получить доступ к gerrit по адресу. При этом будет работать basic auth:

   http://[host]                                         ; [host] это адрес или ip, идентифицирующие сервер, на котором запущен gerrit. Например: http://172.31.11.34. После авторизации произойдет перенаправление на адрес http://localhost:[port]/gerrit

Введение в работу

Прежде всего для работы с gerrit нам понадобится git. С помощью git мы будем коммитать наш код, а также сливать его с gerrit.

Типичные действия с gerrit для разработчика:

  • 1. Разработка кода и локальный коммит в git-репозиторий
  • 2. Отправка кода в удаленный репозиторий (на gerrit)
  • 3. Ревью кода другим разработчиком (ревьювером)
  • 4. Если ревьювер подтверждает ваш код, то код отправляется в production-репозиторий. Если ревьювер отвергает ваш коммит, то вы фиксаете свои ошибки и перезаливаете этот коммит снова на gerrit.

Также вам предоставляется возможность загрузить в свой локальный репозиторий чужой коммит, пофиксать его и отправить обратно на gerrit.

Flows по работе с gerrit

Т.к. gerrit использует git для управления коммитами, то вы можете сначала ознакомиться с типичными ситуациями в работе с git: Flows по работе с git

Нужно обновить коммит, который уже есть на gerrit

Для идентификации одного и того же коммита с разными хешами gerrit использует Change-Id. Этот идентфикатор он создает при самом первом коммите, используя его хеш. Затем, если хеш коммита меняется (к примеру, после операции rebase) и коммит перезаливается на gerrit, то gerrit не будет видеть один и тот же коммит, как два разных коммита, т.к. мы будет использовать Change-Id.

И так вы отправили коммит на gerrit, локально хеш коммита был изменен, нужно перезалить этот коммит на gerrit, причем коммит является последним в истории:

   git add .                     ; добавить изменные файлы в индекс
   git commit --amend            ; перезаписать последний коммит

с gerrit'a копируем Change-Id нашего коммита. Допустим он выглядит так: Change-Id: I6a4074228e1c08b8788165cf4fd6e20825824c27 этот Change-Id вставляем через одну строчку после сообщения к коммиту.

В итоге сообщение к коммиту должно выглядель так:

  Короткое описание коммита в одну строку
  <пустая строка>
  Подробное описание коммита в несколько
  строк.
  <пустая строка>
  Change-Id: I6a4074228e1c08b8788165cf4fd6e20825824c27

Затем сохраняем это сообщение и отправляем изменения на gerrit:

   git push                      ; отправить изменения в удаленный репозиторий

Нужно слить коммит, который не апрувнули, пофиксать его и залить изменения обратно на gerrit

Если это ваш коммит, то вы обновляете его локально у себя, а затем делаете как в Нужно обновить коммит, который уже есть на gerrit.

Если вам нужно пофиксать не свой коммит, т.е. локально у вас его нету, но он есть на gerrit, то в таком случае лучше всего создать отдельную локальную ветку для этого коммита:

   git checkout -b bugfix        ; создание ветки bugfix и переключение в нее

Затем на gerrit нужно открыть этот коммит и скопировать команду, которая позволит слить этот коммит. Gerrit предоставляет команды и адреса, с помощью которых можно получить любой коммит (к примеру, предлагаются pull, cherry-pick, fetch). Требуемая команда будет выглядеть:

   git pull <адрес коммита на геррите>

Копируем эту команду и вставляем в консоль. Затем, если нужна прямолинейная история, то добавляем опцию --rebase:

   git pull --rebase <адрес коммита на геррите>

Выполняем команду и получаем коммит в локальном репозитории. Далее фиксаем его, переносим в master branch и отправляем обратно на gerrit, как написано в Нужно обновить коммит, который уже есть на gerrit.

Нужно перезалить коммит после того, как локально поверх него создано несколько коммитов

Предположим, что вы сделали изменения, закоммитали их и отправили на gerrit. Затем сделали локально несколько коммитов поверх того, что отправили на gerrit. Коммит на gerrit'e не апрувнули и нужно его фиксать. Все это происходит в ветке master.

Чтобы пофиксать коммит, который находится где-то внутри истории (например, 5-ый с конца истории), то нужно сделать следующее:

   git branch master-copy         ; создаем копию текущей ветки master
   git reset --hard HEAD~4        ; удаляем с вершины 4 последних коммита, чтобы наверху остался 5-ый коммит, который нужно фиксать

Фиксаем коммит и добавляем в сообщение к коммиту Change-Id с геррита, если он уже не был добавлен ранее как написано в Нужно обновить коммит, который уже есть на gerrit и заливаем его обратно на gerrit:

   git push                       ; отправить изменения в удаленный репозиторий

Затем нужно возвратить удаленные 4 коммита обратно в ветку master. Для этого переходим в созданную ранее ветку master-copy:

   git checkout master-copy

Сейчас 4 верхних коммита нужно перенести в ветку master:

   git log                        ; показать историю коммитов
   копируем в буфер обмена хеш 4-го коммита, считая от вершины.

Допустим хеш коммита был I6a4074228e1c08b8788165cf4fd6e20825824c27

   git checkout master            ; переходим обратно в ветку master
   git cherry-pick I6a4074228e1c08b8788165cf4fd6e20825824c27 ; переносим в текущую ветку коммит с заданным хешем

Далее нужно снова переключится в ветку master-copy, скопировать хеш 3-го коммита, переключится в ветку master и в нее перенести коммит по хешу. Так делатся для всех остальных коммитов (коммиты 2 и 1).

Сейчас мы имеем начальное состояние ветки master, только с обновленным 5-ым коммитом.

Перенос проекта с github на gerrit

Допустим на github есть проект MyProject. Помимо ветки master есть и другие ветки br1 и br2. Нужно перенести этот проект на gerrit с сохранением всей истории коммитов и всех веток. Чтобы это сделать нужно:

  • 1. Создать проект MyProject через веб-интерфейс gerrit'а

GerritCreateProject.png


  • 2. Создать все существующие ветки через веб-интерфейс gerrit'a (на картинке пример создания ветки br1)

GerritCreateBranch.png


  • 3. Тому, кто делает перенос, нужно добавить права Create Reference, Forge Author Identity, Forge Committer Identity, Push Merge Commit для refs/heads/*, refs/for/*, refs/remotes/*

GerritProjectRights.png


  • 4. Получить все последние изменения из github и выполнить команду
  * git push --mirror ssh://[gerrit_user]@[gerrit_host]:[gerrit_port]/[project].git
  • 5. УДАЛИТЬ все предоставленные права в пункте 3!

Как запретить коммитать в какую-либо ветку мимо Gerrit Code Review System

Если Вы не измените файл /<project>/.git/config как описано в Push в репозиторий gerrit'a, то при коммите в любую ветку Ваш коммит пройдет мимо Gerrit Code Review System. Чтобы запретить это делать нужно настроить права на операцию Push (на картинке приведен пример для настройки Push-прав для ветки master):

Example.png