Это статья о том, как с помощью TrackStudio и Git можно организовать удобный процесс разработки ПО. В стать рассмотрен вариант для ОC Windows. Но при желании не сложно все сделать и для других OC.
Для этого нам понадобиться:
Установка всех остальных приложении очень проста, замечу только одно, что blat надо положить в папку с git.exe (у меня С:/Program files/Git/bin), или папку, в которой находится blat добавить в PATH.
Для настройки этого процесса необходимо в файле TS_HOME\etc\trackstudio.mail.properties (если у вас его нет создайте) прописать параметры сбора почты:
Скрипт создали, теперь в TS выбираем в меню «Управление задачами -> Категории»,
щелкаем сначала по категории с наименование «Изменение»,
открываем вкладку «Триггеры» и в списке «AFTER Триггер» отмечаем триггер, который называется createRuleImport.bsh.
Проделываем тоже самое и для категории «Ошибка».
Если все сделано правильно, то при создании новой задачи у ПРЕДКА появится правило импорта newНОМЕР_ПРЕДКА или bugНОМЕР_ПРЕДКА. При отправки письма на email, с которого импортируется почта, с темой «newНОМЕР_ПЕРЕДКА новая задача», TS создаст задачу в ПРЕДКЕ с наименование, которое равно теме письма. А если отправить письмо в теме, которого есть ключ newНОМЕР_ПЕРЕДКА#НОМЕР_ЗАДАЧИ (при этом задача существует), то TS импортирует письмо, как комментарии к задаче и сообщение комментария будет тело письма. При чем если к письму прикрепить файл, то TS прикрепит его к задаче.
В названии указать нужное вам имя, в нашем случае «Имя ветви в git», и нажать кнопку Сохранить. Но это все лишь для того, что бы скопировать и быстро вставить в sh при создании новой ветки в git, типа удобно.
Теперь нам необходимо сделать, чтобы TS изменил типа сообщения на «Завершить» или «Исправить» для категории «Изменение» или «Ошибка» соответственно («Комментарии», «Завершить», «Изменение» и «Ошибка» — наименования типа сообщения и категорий, они зависят от того как вы настроите свой workflow в TS; если вы используете демонстрационную русскую бд, то они будут именно такими). Нам нужно создать скрипт, который будет искать в теле сообщения, какой нибудь ключ, который будет сообщать TS, что необходимо поменять тип сообщения. Я предлагаю использовать конструкцию [new_state=done], но это уже на ваше усмотрение. Создадим в папке TS_HOME\plugins\scripts\before_add_message, в которой размещаются скрипты, выполняемые до добавления сообщения, файл changeType.bsh с кодом:
открываем вкладку «Триггеры» и в списке «BEFORE Триггер» отмечаем триггер, который называется changeType.bsh.
Проделываем тоже самое и для процесса «Ошибка».
Вроде все, можно пробовать.
Создаем задачу -> копируем из поля «Имя ветви в git» значение ->
создаем письмо с темой, в которую вставляем скопированное значение -> затем в теле письма пишем любой текст и добавляем директиву [new_state=done].
По идее после импорта письма у задачи измениться состояние она должна перейти в состояние завершена и сообщением к этому состоянию будет тело письма.
В папке куда вы установил stunnel находим файл stunnle.conf (C:\Program Files\stunnel\stunnel.conf). Меняем его содержимое на следующее:
Для того чтобы настроить поведение git при совершении коммита, нам надо изменить 2 хука первый post-commit и prepare-commit-msg, первый выполняется в момент коммита, второй когда формируется сообщение коммита. Файлы хуков лежат в директории DIR_YOUR_REPO/.git/hooks.
Хук prepare-commit-msg вставляет в начало сообщения коммита параметры отправки письма, такие как:
Вводим в командную строку
Затем нажимаем Ctrl + Enter и через интервал, который вы установли сборщику почты в TS, провермяем состояние задачи.
Здесь комментарий оформлен html, но это тема отдельного поста.
Да и когда появиться, не понятно каким образом будет реализована работа с распределенными репозиториями.
А данное решение позволяет работать над задачей нескольким программистам, у которых свой зоопарк репозиториях. А потом объединять их в один центральный, в котором порядок и чистота.
К тому же, очень удобно работать не имея прямого доступа до TS.
Создавать задачи может руководитель проекта и назначать на них ответственными конкретных людей. К ним на почту будут приходить письма о том, что создана задача или, что его назначили ответственным. Он в сообщении письма видит какая поставлена задача и имя ветви для git, начинает работу над задачей. По окончанию работы, спокойно делает коммит в репозитории и может уже не волноваться о том, что задачу надо завершить. Причем он также может удаленно создавать подзадачи зная ключ задачи предка, отправляя письма на email, с которого импортируется почта в TS с темой, в которой присутствует нужный ключ. В ответ также будут приходить письма о том, что он создал задачу.
Для этого нам понадобиться:
- TrackStudio — универсальная система управления задачами.
- Git — VCS.
- Blat — Маленькая (70kB) open source консольная программа под Windows, которая позволяет отправлять e-Mail по SMTP протоколу из командной строки, с приложенными файлами.
- STunnel — Программа, которая позволяет вам зашифровать произвольные TCP подключения внутри SSL. Инструмент доступен для Unix и Windows.
Нужен если вы используете gmail.com, как почтовый сервис. Так как blat напрямую работать с gmail не может.
Организовать рабочий процесс таким образом, что бы при коммите в git, автоматически в TrackStudio задаче добавлялся комментарии с различными типами сообщения и текстом этого комментария был текст сообщения коммита.
Установка
TrackStudio
Делаем все как написано здесьУстановка всех остальных приложении очень проста, замечу только одно, что blat надо положить в папку с git.exe (у меня С:/Program files/Git/bin), или папку, в которой находится blat добавить в PATH.
Настройка
TrackStudio
TrackStudio умеет забирать письма из email и импортировать их как задачи.Для настройки этого процесса необходимо в файле TS_HOME\etc\trackstudio.mail.properties (если у вас его нет создайте) прописать параметры сбора почты:
вот пример для gmail.com:mail.pop3.apop.enable=\ mail.store.forward=отправлять не распознанные письма на email mail.store.fwdaddress=email куда отправлять не распознанные письма mail.store.host=pop сервер mail.store.password=ваш пароль mail.store.port=порт mail.store.protocol=протокол mail.store.user=учетная запись, email, с которого импортировать trackstudio.emailSubmission=yes trackstudio.mailimport.interval=интервал проверки почты
Более подробно все описано в документации.mail.pop3.apop.enable=\ mail.store.forward=yes mail.store.fwdaddress=mymail@gmail.com mail.store.host=pop.gmail.com mail.store.password=password mail.store.port=995 mail.store.protocol=pop3s mail.store.user=srvmail@gmail.com
Скрипт для создания правила импорта
Теперь в TS для предка каждой задачи с типом категории «Изменение» или «Ошибка» надо создать правило импорта и желательно, чтобы они создавались от имени администратора. Но каждый раз делать, это ручками накладно — решаем эту проблему написание плагина. В папке TS_HOME\plugins\scripts\after_create_task (в ней размещаются скрипты, которые выполняются после создания задач) создаем файл createRuleImport.bsh со следующим кодом:
- /**
- * Скрипт создает правило импорта для задачи предка, при создании дочерней задачи.
- */
- import com.trackstudio.app.adapter.AdapterManager;
- import com.trackstudio.exception.GranException;
- import com.trackstudio.secured.*;
- import com.trackstudio.securedkernel.SecuredMailImportAdapterManager;
- import com.trackstudio.securedkernel.SecuredStepAdapterManager;
- import java.util.*;
- import com.trackstudio.secured.SecuredUserBean;
- import com.trackstudio.app.session.*;
- import com.trackstudio.app.csv.CSVImport;
- try {
- //объек для работы с правилами импорта почтовых сообщений
- SecuredMailImportAdapterManager mam = AdapterManager.getInstance()
- .getSecuredMailImportAdapterManager();
- //содержит методы для работы с типами сообщений
- SecuredStepAdapterManager sam = AdapterManager.getInstance()
- .getSecuredStepAdapterManager();
- //список доступных типов сообщений для задачи и текущего пользователя
- ArrayList arrMS = sam.getAvailableMstatusList(task.getSecure(), task.getId());
- //тип сообщения
- SecuredMstatusBean curMS = null;
- String pefixStr = «new»;
- /**
- * Проверяем тип категории создаваемой задачи.
- * Если категория задачи равна «Ошибка» = наименование категории в TS
- */
- if(task.getCategory().getName().equals(«Ошибка»))
- pefixStr = «bug»;
- /**
- * Формируем ключ для импорта сообщений текущей задачи:
- * префик + номер родительской задачи + # + номер задачи
- * этот ключ должен встречаться в теме письма
- * например:
- * new759#2845 любой текст, все равно он будет проигнорирован при добавлении сообщеиня.
- */
- String mailimKey = pefixStr + task.getParent().getNumber() + "#" + task.getNumber();
- /**
- * Надо ли создавать правило.
- * Так как задача предок может иметь несколько подзадач,
- * то необходимо проверять существование правила импорта,
- * что бы не плодить их.
- */
- boolean found = false;
- for (int i = 0; i < arrMS.size(); i++) {
- curMS = (SecuredMstatusBean) arrMS.get(i);
- msn = curMS.getName();
- //«Комментрарий» или «Комментировать» это наименования типа сообщения
- if(msn.compareToIgnoreCase(«Комментарий») == 0 || msn.compareToIgnoreCase(«Комментировать») == 0) {
- //Получаем данные по пользователю root
- SecuredUserBean adminUser = new SecuredUserBean(CSVImport.findUserIdByLogin(«root»), sc);
- //Текущий контекст пользователя
- SessionContext needSc = task.getSecure();
- //проверяем авторизировался ли root
- if(SessionManager.getInstance().existUserSession(adminUser.getUser())) {
- for(SessionContext curSc: SessionManager.getInstance().getSessions()) {
- if(curSc.getUser().getLogin().equals(«root»)) {
- //если да то получаем его контекст
- needSc = curSc;
- break;
- }
- }
- }
- else {
- //если нет, то создаем его контекст
- needSc = SessionManager.getInstance().getSessionContext(
- SessionManager.getInstance().create(adminUser.getUser()));
- }
- if(!found)
- for (SecuredMailImportBean curMailS: mam.getAllAvailableMailImportList(needSc, task.getParentId())) {
- // Ищем правило импорта новых задачь у предка.
- found = curMailS.getKeywords().equals(pefixStr + task.getParent().getNumber());
- if(found)
- break;
- }
- if(!found) {
- /**
- * если не нашли, то создаем новое правило импорта для предка
- * от имени root, так как TS поддерживает возможность создания
- * пользователями индивидуальных правил импорта почты, необходимо
- * что бы это правило было видно всем.
- */
- mam.createMailImport(needSc, pefixStr + task.getParent().getNumber(),
- task.getParentId(), pefixStr + task.getParent().getNumber(), 1, i,
- task.getCategoryId(), curMS.getId(), "", true, false);
- found = true;
- }
- }
- }
- //Добавляем значение для UDF поля с наименование «Имя ветви в git».
- AdapterManager.getInstance().getSecuredUDFAdapterManager().setTaskUDFValueSimple(
- task.getSecure(),task.getId(),«Имя ветви в git», mailimKey);
- }
- catch(GranException e) {
- throw new com.trackstudio.exception.UserMessageException(e.getMessage());
- }
- return task;
Скрипт создали, теперь в TS выбираем в меню «Управление задачами -> Категории»,
щелкаем сначала по категории с наименование «Изменение»,
открываем вкладку «Триггеры» и в списке «AFTER Триггер» отмечаем триггер, который называется createRuleImport.bsh.
Проделываем тоже самое и для категории «Ошибка».
Если все сделано правильно, то при создании новой задачи у ПРЕДКА появится правило импорта newНОМЕР_ПРЕДКА или bugНОМЕР_ПРЕДКА. При отправки письма на email, с которого импортируется почта, с темой «newНОМЕР_ПЕРЕДКА новая задача», TS создаст задачу в ПРЕДКЕ с наименование, которое равно теме письма. А если отправить письмо в теме, которого есть ключ newНОМЕР_ПЕРЕДКА#НОМЕР_ЗАДАЧИ (при этом задача существует), то TS импортирует письмо, как комментарии к задаче и сообщение комментария будет тело письма. При чем если к письму прикрепить файл, то TS прикрепит его к задаче.
Каким образом добавить UDF поле
Для этого в TS верхнем меню выбрать «Управление задачами -> Процессы», открыть интересующий вас процесс и во вкладке «Дополнительные поля» кликнуть по кнопке «Строка».В названии указать нужное вам имя, в нашем случае «Имя ветви в git», и нажать кнопку Сохранить. Но это все лишь для того, что бы скопировать и быстро вставить в sh при создании новой ветки в git, типа удобно.
Скрипт для обработки сообщении полученных через почту
TS уже умеет из писем создавать сообщения с типом «Комментарии» к задачам.Теперь нам необходимо сделать, чтобы TS изменил типа сообщения на «Завершить» или «Исправить» для категории «Изменение» или «Ошибка» соответственно («Комментарии», «Завершить», «Изменение» и «Ошибка» — наименования типа сообщения и категорий, они зависят от того как вы настроите свой workflow в TS; если вы используете демонстрационную русскую бд, то они будут именно такими). Нам нужно создать скрипт, который будет искать в теле сообщения, какой нибудь ключ, который будет сообщать TS, что необходимо поменять тип сообщения. Я предлагаю использовать конструкцию [new_state=done], но это уже на ваше усмотрение. Создадим в папке TS_HOME\plugins\scripts\before_add_message, в которой размещаются скрипты, выполняемые до добавления сообщения, файл changeType.bsh с кодом:
Скрипт создали, теперь в TS выбираем в меню «Управление задачами -> Процессы», щелкаем сначала по процессу с наименование «Изменение», затем выбираем вкладку типы операции и кликнем по операции с наименованием «Комментарий»,
- /**
- * Скритп изменяет тип импортируемого сообщения если находит в теле сообщения
- * конструкуцию [new_state=type], где type может быть done или start
- */
- import java.util.*;
- import java.util.regex.*;
- import java.io.*;
- try {
- if(message.description != null)
- {
- String[] tempArr = null;
- //Ищем нужную нам конструкцию в сообщение
- String pattern = ".*\\[(\\w*)=(\\w*)\\].*";
- Pattern p = Pattern.compile(pattern, Pattern.MULTILINE);
- Matcher m = p.matcher(message.description);
- if (m.find())
- tempArr = new String[]{m.group(1), m.group(2)};
- //проеряем ялсяется ли первый параметер директивой к смене типа сообщения
- if(tempArr != null && tempArr[0].toLowerCase().equals(«new_state»)) {
- //определяем на какой тип изменить текущий тип сообщения
- if(tempArr[1].toLowerCase().equals(«done»)) {
- //Удаляем из сообщения директиву
- message.description = message.description.replaceFirst("\\[new_state=done\\]", "");
- //проверяем задаче какой категории принадлежит
- if(message.getTask().getCategory().getName().equals(«Изменение»))
- //устанавливаем новый тип сообщения по его наименованию
- message.setMstatus(«Завершить»);
- if(message.getTask().getCategory().getName().equals(«Ошибка»))
- message.setMstatus(«Исправить»);
- }
- if(tempArr[1].toLowerCase().equals(«start»)) {
- message.description = message.description.replaceFirst("\\[new_state=start\\]", "");
- if(message.getTask().getCategory().getName().equals(«Изменение») ||
- message.getTask().getCategory().getName().equals(«Ошибка»))
- message.setMstatus(«Начать работу»);
- }
- }
- }
- }
- catch(Exception e) {
- throw new com.trackstudio.exception.UserMessageException(e.printStackTrace());
- }
- return message;
открываем вкладку «Триггеры» и в списке «BEFORE Триггер» отмечаем триггер, который называется changeType.bsh.
Проделываем тоже самое и для процесса «Ошибка».
Вроде все, можно пробовать.
Создаем задачу -> копируем из поля «Имя ветви в git» значение ->
создаем письмо с темой, в которую вставляем скопированное значение -> затем в теле письма пишем любой текст и добавляем директиву [new_state=done].
По идее после импорта письма у задачи измениться состояние она должна перейти в состояние завершена и сообщением к этому состоянию будет тело письма.
Итог
Мы расширили способности TS, теперь она умеет:- Автоматически создавать правила импорта для создания новых сообщении и задач.
- Менять статус сообщения в зависимости от найденной в теле письма директивы.
- Прикреплять файлы к задаче, если они прикреплены к письму.
Этой способностью TS наделили разработчики, но она нам понадобиться в дальнейшем.
STunnel
Если вы не используете gmail.com как почтовый сервер, то пропустите этот пункт!В папке куда вы установил stunnel находим файл stunnle.conf (C:\Program Files\stunnel\stunnel.conf). Меняем его содержимое на следующее:
И для того, чтобы stunnel запускался как служба автоматически выполняем в командной строке:socket = l:TCP_NODELAY=1 socket = r:TCP_NODELAY=1 debug = 7 output = stunnel.log client = yes [ssmtp] accept = 127.0.0.1:465 connect = smtp.gmail.com:465
«C:\Program Files\stunnel\stunnel.exe» –installисточник: Отправка писем из командной строки Windows используя аккаунт GMail
Git
Все что связано с TS производилось на стороне сервера. А теперь все настройки будут на конкретном рабочем месте.Для того чтобы настроить поведение git при совершении коммита, нам надо изменить 2 хука первый post-commit и prepare-commit-msg, первый выполняется в момент коммита, второй когда формируется сообщение коммита. Файлы хуков лежат в директории DIR_YOUR_REPO/.git/hooks.
- В файле prepare-commit-msg генерацию шапки сообщения.
#!/bin/sh
case "$2,$3" in
merge,)
perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/… /#/; print' "$1" ;;
*) ;;
esac
if [ "`git branch | grep -e "^\*.\(new\|bug\)[0-9]\+#[0-9]\+" | cut -f2 -d ' '`" != "" ]; then
#Помещаем в начало файла с сообщением ключи для отправки письма.
echo «sendmail» > temp_msg
echo «to= srvemail@gmail.com» >> temp_msg
echo "[new_state=done]" >> temp_msg
cat $1 >> temp_msg
cat temp_msg > $1
rm temp_msg
fi - В файле post-commit настроим сбор информации о изменения и отправку почты.
#!/bin/sh
# получаем из переменной GIT_AUTHOR_IDENT майл текущего коммитера
sender=`git var GIT_COMMITTER_IDENT | cut -f1 -d '>' | cut -f 2 -d '<'`
#проверяем наличие в первой строке сообщения коммита текста sendmail
if [ `git log -1 | sed «s/[ ]*//g» | grep -e "^sendmail$"` == «sendmail» ]; then
#формируем тему сообщения, которая берется из названия ветви
#но это пожеланию, можно сделать чтоб тема была взята из первой строчки основного текста сообщения
subject=`git branch | grep -e "^\*.\(new\|bug\)[0-9]\+#[0-9]\+" | cut -f2 -d ' '`
if [ "`git log -1 | sed "s/[]*//g" | gre grep -e "^newroot\=" | cut -f2 -d '='`" != "" ]; then
subject=`git log -1 | sed «s/[ ]*//g» | grep -e "^newroot\=" | cut -f2 -d '=' | cut -f1 -d '#'`
subject="$subject#`git branch | grep -e "^\*.\(new\|bug\)[0-9]\+#[0-9]\+" | cut -f2 -d '#'`"
fi
#определяем из третей строчки сообщения коммита майл,
#на который необходимо отправить письмо,
#по-умолчанию ставиться майл текущего коммитера.
to=$sender
if [ "`git log -1 | sed «s/[ ]*//g» | grep -e "^[Tt][Oo]\=" | cut -f2 -d '='`" != "" ]; then
to=`git log -1 | sed «s/[ ]*//g» | grep -e "^[Tt][Oo]\=" | cut -f2 -d '='"`
fi
#формируем имя патчфайла
patchname="$(date +%j%H%M%s).patch"
# сохраняем diff соверщеного комита,
(git diff-index -p -M HEAD^) > $patchname
#берем из лога git последние сообщение за исключениием управляющего текста
git log -1 | grep -v "^Date:" | grep -v "^commit " | grep -v "^Author:" | grep -v " *Signed-off-by: " | grep -v "^[ ]*sendmail[ ]*$" | grep -v "^[ ]*newroot\=" | grep -v "^[ ]*[Tt][Oo]\=" | grep -v ".*$subject.*" | sed -e "/^[ ]*$/d" -e "/^$/d" >> temp.tmp
echo «shortstat» >> temp.tmp
git diff-index --stat HEAD^ >> temp.tmp
#отправляем по средствам blat
blat -charset «utf-8» -f $sender -server localhost -port 465 -u useremail@gmail.com -pw password -to $to -bodyF temp.tmp -subject $subject -base64 -attach $patchname > logSendMail.log
rm $patchname
rm temp.tmp
edit logSendMail.log
sleep 2s
rm logSendMail.log
fi
Как это работает
Самое важно, при начале работы над новой задаче, необходимо в оперативном репозитории текущего программиста, создать ветвь с именем, которое создала TS при формировании задачи.Хук prepare-commit-msg вставляет в начало сообщения коммита параметры отправки письма, такие как:
- sendmail — отправлять ли письмо. Если в сообщении нет строчки содержащей только это слово, то письмо отправлено не будет.
- to — на какой email отправить. Если его нет то письмо будет отправлено отправителю.
- [new_state=done] — директива для TS, что необходимо присвоить новому сообщению тип «Завершен» или «Исправлено».
Этот параметр можно не указывать, тогда TS будет добавлять новые сообщения с типом «Комментарий». - newroot — этот параметр обозначает, надо переделать тему письма. В TS есть возможность перемещать подзадачи из одной задачи в другую, так вот чтоб не создавать новой ветки можно просто указать нового родителя текущей задачи.
Например, вы создали подзадачу (номер 2084, номер предка 754, ключ new754#2084) и начали над ней работу, а потом поняли, что подзадача должна принадлежать другой родительской задаче (с номером 458, новый ключ new458#2084) и переместили ее к ней. Для того, чтобы в git не заводит новую ветку, можно в сообщении коммита добавляем следующий код
Важно: каждый параметр должен находиться в отдельной строке, количество пробелов или знаков табуляции не влияют на его обнаружение.newroot=new458
Вводим в командную строку
$ git add --all & git gui
Затем нажимаем Ctrl + Enter и через интервал, который вы установли сборщику почты в TS, провермяем состояние задачи.
Здесь комментарий оформлен html, но это тема отдельного поста.
Заключение
Стандартный рабочий процесс состоит из 4 основных этапов:- Постановка задачи в TS и копировании имени ветви для git.
- Создание ветви в git и переход на нее.
Можно выполнить одной командой:$ git checkout -b имя_ветви
- Выполнение задачи.
- Завершение работы над задачей в TS, совершением коммита в git.
Почему используется именно такой механизм
Причина в том, что у TS пока нет интеграции с SCM GIT.Да и когда появиться, не понятно каким образом будет реализована работа с распределенными репозиториями.
А данное решение позволяет работать над задачей нескольким программистам, у которых свой зоопарк репозиториях. А потом объединять их в один центральный, в котором порядок и чистота.
К тому же, очень удобно работать не имея прямого доступа до TS.
Создавать задачи может руководитель проекта и назначать на них ответственными конкретных людей. К ним на почту будут приходить письма о том, что создана задача или, что его назначили ответственным. Он в сообщении письма видит какая поставлена задача и имя ветви для git, начинает работу над задачей. По окончанию работы, спокойно делает коммит в репозитории и может уже не волноваться о том, что задачу надо завершить. Причем он также может удаленно создавать подзадачи зная ключ задачи предка, отправляя письма на email, с которого импортируется почта в TS с темой, в которой присутствует нужный ключ. В ответ также будут приходить письма о том, что он создал задачу.
Источники
- ProGit — онлайн книга по git.
- Документация по TrackStudio.
- TS_HOME\docs\javadoc\index.html — мануал по API TrackStudio, поставляется вместе с TS.
- Отправка писем из командной строки Windows используя аккаунт GMail.