Git + TrackStudio - development automation
- Tutorial
This article is about how to use TrackStudio and Git to organize a convenient software development process. The article discusses an option for Windows OS. But if you wish, it’s not difficult to do everything for other OCs.
For this we need:
Installing the rest of the application is very simple, I note only one thing that blat should be put in the folder with git.exe (I have C: / Program files / Git / bin), or add the folder in which blat is located to PATH .
To configure this process, you must specify the mail collection parameters in the TS_HOME \ etc \ trackstudio.mail.properties file (if you do not have one):
We created the script, now in TS select “Task Management -> Categories” in the menu, first click on the category with the name “Change”, open the “Triggers” tab and select the trigger called createRuleImport.bsh in the “AFTER Trigger” list . We are doing the same for the “Error” category.
If everything is done correctly, then when creating a new task, the ancestor will have the import rule newNUMBER_EXT or bugNUMBER_EXT. When sending a letter to the email address from which the mail is imported, with the subject line “new_TRAN_NEW new task”, TS will create a task in the ANCESTOR with a name that is equal to the subject of the letter. And if you send a letter in the subject, which has the key newNUMBER_TRAN # TASK NUMBER (the task exists), TS imports the letter as comments on the task and the comment message will be the body of the letter. Moreover, if you attach a file to the letter, TS will attach it to the task.
Now we need to make TS change the message type to “Complete” or “Fix” for the category “Change” or “Error”, respectively (“Comments”, “Finish”, “Change” and “Error” - names of the message type and categories , they depend on how you configure your workflow in TS; if you use a demo Russian database, then they will be just that). We need to create a script that will look in the message body for some key that will tell TS that it is necessary to change the type of message. I suggest using the [new_state = done] construct, but that's up to you. Create in the folder TS_HOME \ plugins \ scripts \ before_add_message, which hosts the scripts executed before the message is added, the changeType.bsh file with the code:
In theory, after the letter is imported, the task has a state change, it should go to the completed state and the message body will be a message to this state.
In the folder where you installed stunnel find file stunnle.conf (the C: \ Program Files \ stunnel \ stunnel.conf). We change its contents to the following:
In order to configure the behavior of git when committing, we need to change 2 hooks, the first post-commit and prepare-commit-msg , the first is executed at the time of the commit, the second when the commit message is generated. Hook files are in the directory DIR_YOUR_REPO / .git / hooks .
The prepare-commit-msg hook inserts message sending options at the top of the commit message, such as:
command line
Then press Ctrl + Enter and through the interval that you set the mail collector in TS, check the status of the task. Here the comment is framed in html, but this is the topic of a separate post.
And when it appears, it is not clear how the work with distributed repositories will be implemented.
And this solution allows several programmers who have their own zoo repositories to work on the task. And then combine them into one central, in which order and purity.
In addition, it is very convenient to work without having direct access to TS.
The project manager can create tasks and assign specific people to them. Letters will come to their mail that they have created a task or that he has been appointed responsible. He sees in the message message what the task is and the branch name for git, starts work on the task. At the end of the work, he quietly commits in the repository and may no longer worry that the task needs to be completed. Moreover, he can also remotely create subtasks knowing the key of the task of the ancestor by sending letters to the email from which mail is imported to TS with the subject in which the desired key is present. In response, letters will also come that he created the task.
For this we need:
- TrackStudio is a universal task management system.
- Git - VCS.
- Blat - A small (70kB) open source console program for Windows that allows you to send e-mail via SMTP from the command line with the attached files.
- STunnel - A program that allows you to encrypt arbitrary TCP connections inside SSL. The tool is available for Unix and Windows.
Needed if you use gmail.com as a mail service. Since blat cannot work directly with gmail.
Organize the workflow in such a way that when committing in git, comments with various message types were automatically added to TrackStudio task and the text of the comment was the text of the commit message.
Installation
Trackstudio
We do everything as it is written here.Installing the rest of the application is very simple, I note only one thing that blat should be put in the folder with git.exe (I have C: / Program files / Git / bin), or add the folder in which blat is located to PATH .
Customization
Trackstudio
TrackStudio can pick up emails from email and import them as tasks.To configure this process, you must specify the mail collection parameters in the TS_HOME \ etc \ trackstudio.mail.properties file (if you do not have one):
here is an example for 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=интервал проверки почты
Everything is described in more detail in the documentation .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
Script to create an import rule
Now in TS, for the ancestor of each task with the category category “Change” or “Error”, you need to create an import rule and it is desirable that they be created on behalf of the administrator. But every time you do it, it’s unprofitable with pens - we solve this problem by writing a plugin. In the TS_HOME \ plugins \ scripts \ after_create_task folder (it contains the scripts that are executed after the tasks are created), create the createRuleImport.bsh file with the following code:
- / **
- * The script creates an import rule for an ancestor task when creating a child task.
- * /
- 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 {
- // object for working with mail import rules
- SecuredMailImportAdapterManager mam = AdapterManager.getInstance ()
- .getSecuredMailImportAdapterManager ();
- // contains methods for working with message types
- SecuredStepAdapterManager sam = AdapterManager.getInstance ()
- .getSecuredStepAdapterManager ();
- // list of available message types for the task and current user
- ArrayList arrMS = sam.getAvailableMstatusList (task.getSecure (), task.getId ());
- // message type
- SecuredMstatusBean curMS = null;
- String pefixStr = "new";
- / **
- * Check the category type of the task being created.
- * If the task category is “Error” = category name in TS
- * /
- if (task.getCategory (). getName (). equals ("Error"))
- pefixStr = "bug";
- / **
- * We generate a key for importing messages of the current task:
- * prefix + parent task number + # + task number
- * this key should appear in the subject line
- * eg:
- * new759 # 2845 any text, anyway it will be ignored when adding a community.
- * /
- String mailimKey = pefixStr + task.getParent (). GetNumber () + "#" + task.getNumber ();
- / **
- * Do I need to create a rule.
- * Since an ancestor task can have several subtasks,
- * then it is necessary to check the existence of the import rule,
- * that would not produce them.
- * /
- boolean found = false;
- for (int i = 0; i <arrMS.size (); i ++) {
- curMS = (SecuredMstatusBean) arrMS.get (i);
- msn = curMS.getName ();
- // “Comment” or “Comment” is the name of the message type
- if (msn.compareToIgnoreCase ("Comment") == 0 || msn.compareToIgnoreCase ("Comment") == 0) {
- // Get data for root user
- SecuredUserBean adminUser = new SecuredUserBean (CSVImport.findUserIdByLogin ("root"), sc);
- // Current user context
- SessionContext needSc = task.getSecure ();
- // check if root is authorized
- if (SessionManager.getInstance (). existUserSession (adminUser.getUser ())) {
- for (SessionContext curSc: SessionManager.getInstance (). getSessions ()) {
- if (curSc.getUser (). getLogin (). equals ("root")) {
- // if so, get its context
- needSc = curSc;
- break;
- }
- }
- }
- else {
- // if not, then create its context
- needSc = SessionManager.getInstance (). getSessionContext (
- SessionManager.getInstance (). Create (adminUser.getUser ()));
- }
- if (! found)
- for (SecuredMailImportBean curMailS: mam.getAllAvailableMailImportList (needSc, task.getParentId ())) {
- // We are looking for the rule to import new tasks from the ancestor.
- found = curMailS.getKeywords (). equals (pefixStr + task.getParent (). getNumber ());
- if (found)
- break;
- }
- if (! found) {
- / **
- * if not found, then create a new import rule for the ancestor
- * as root, as TS supports the ability to create
- * users of individual mail import rules need
- * That this rule would be visible to all.
- * /
- mam.createMailImport (needSc, pefixStr + task.getParent (). getNumber (),
- task.getParentId (), pefixStr + task.getParent (). getNumber (), 1, i,
- task.getCategoryId (), curMS.getId (), "", true, false);
- found = true;
- }
- }
- }
- // Add a value for the UDF field with the name "Branch name in git".
- AdapterManager.getInstance (). GetSecuredUDFAdapterManager (). SetTaskUDFValueSimple (
- task.getSecure (), task.getId (), "Branch name in git", mailimKey);
- }
- catch (GranException e) {
- throw new com.trackstudio.exception.UserMessageException (e.getMessage ());
- }
- return task;
We created the script, now in TS select “Task Management -> Categories” in the menu, first click on the category with the name “Change”, open the “Triggers” tab and select the trigger called createRuleImport.bsh in the “AFTER Trigger” list . We are doing the same for the “Error” category.
If everything is done correctly, then when creating a new task, the ancestor will have the import rule newNUMBER_EXT or bugNUMBER_EXT. When sending a letter to the email address from which the mail is imported, with the subject line “new_TRAN_NEW new task”, TS will create a task in the ANCESTOR with a name that is equal to the subject of the letter. And if you send a letter in the subject, which has the key newNUMBER_TRAN # TASK NUMBER (the task exists), TS imports the letter as comments on the task and the comment message will be the body of the letter. Moreover, if you attach a file to the letter, TS will attach it to the task.
How to add a UDF field
To do this, in the TS top menu, select "Task Management -> Processes", open the process of interest to you and click on the "String" button in the "Additional Fields" tab. Indicate the name you need in the name, in our case, “Branch name in git”, and click the Save button. But this is just to copy and paste quickly into sh when creating a new branch in git, such as convenient.Script for processing a message received via mail
TS already knows how to create messages with the type "Comments" on tasks from letters.Now we need to make TS change the message type to “Complete” or “Fix” for the category “Change” or “Error”, respectively (“Comments”, “Finish”, “Change” and “Error” - names of the message type and categories , they depend on how you configure your workflow in TS; if you use a demo Russian database, then they will be just that). We need to create a script that will look in the message body for some key that will tell TS that it is necessary to change the type of message. I suggest using the [new_state = done] construct, but that's up to you. Create in the folder TS_HOME \ plugins \ scripts \ before_add_message, which hosts the scripts executed before the message is added, the changeType.bsh file with the code:
We created the script, now in TS select “Task Management -> Processes” in the menu, first click on the process with the name “Change”, then select the operation types tab and click on the operation with the name “Comment”, open the “Triggers” tab and in the list "BEFORE Trigger" marks the trigger called changeType.bsh . We are doing the same for the “Error” process. Like everything, you can try. Create a task -> copy the value from the "Branch name in git" field -> create a message with a subject into which we paste the copied value -> then in the body of the message we write any text and add the directive [new_state = done].
- / **
- * The script changes the type of the imported message if it is found in the message body
- * construction [new_state = type], where type can be done or start
- * /
- import java.util. *;
- import java.util.regex. *;
- import java.io. *;
- try {
- if (message.description! = null)
- {
- String [] tempArr = null;
- // Looking for the construction we need in the message
- 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)};
- // check if the first parameter is a directive to change the type of message
- if (tempArr! = null && tempArr [0] .toLowerCase (). equals ("new_state")) {
- // determine which type to change the current message type
- if (tempArr [1] .toLowerCase (). equals ("done")) {
- // Remove the directive from the message
- message.description = message.description.replaceFirst ("\\ [new_state = done \\]", "");
- // check the task of which category belongs
- if (message.getTask (). getCategory (). getName (). equals ("Change"))
- // set a new message type by its name
- message.setMstatus ("Complete");
- if (message.getTask (). getCategory (). getName (). equals ("Error"))
- message.setMstatus (“Fix”);
- }
- if (tempArr [1] .toLowerCase (). equals ("start")) {
- message.description = message.description.replaceFirst ("\\ [new_state = start \\]", "");
- if (message.getTask (). getCategory (). getName (). equals ("Change") ||
- message.getTask (). getCategory (). getName (). equals ("Error"))
- message.setMstatus ("Get started");
- }
- }
- }
- }
- catch (Exception e) {
- throw new com.trackstudio.exception.UserMessageException (e.printStackTrace ());
- }
- return message;
In theory, after the letter is imported, the task has a state change, it should go to the completed state and the message body will be a message to this state.
Total
We have expanded the capabilities of TS, now she can:- Automatically create import rules to create new messages and tasks.
- Change the message status depending on the directive found in the message body.
- Attach files to the task, if they are attached to the letter.
This ability was given to TS by developers, but we will need it in the future.
Stunnel
If you are not using gmail.com as a mail server, skip this step!In the folder where you installed stunnel find file stunnle.conf (the C: \ Program Files \ stunnel \ stunnel.conf). We change its contents to the following:
And so that stunnel starts as a service, we automatically execute it on the command line: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" –installsource: Sending letters from the Windows command line using a GMail account
Git
Everything related to TS was done on the server side. And now all the settings will be at a specific workplace.In order to configure the behavior of git when committing, we need to change 2 hooks, the first post-commit and prepare-commit-msg , the first is executed at the time of the commit, the second when the commit message is generated. Hook files are in the directory DIR_YOUR_REPO / .git / hooks .
- In the prepare-commit-msg file, generate a message header.
#! / 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
# Put at the beginning of the file with the message the keys to send the letter.
echo "sendmail" > temp_msg
echo "to = srvemail@gmail.com" >> temp_msg
echo "[new_state = done]" >>
temp_msg
cat temp_msg > $ 1
rm temp_msg
fi - In the post-commit file, we’ll configure the collection of information about the change and sending mail.
#! / bin / sh
# we get from the variable GIT_AUTHOR_IDENT the mail of the current committer
sender = `git var GIT_COMMITTER_IDENT | cut -f1 -d '>' | cut -f 2 -d '<' `
# check for sendmail
if [ ` git log -1 | sed "s / [] * // g" | grep -e "^ sendmail $" ` ==" sendmail " ]; then
# we form the subject of the message, which is taken from the name of the branch
# but this is optional, you can make the topic be taken from the first line of the main body of the message
subject = `git branch | grep -e "^ \ *. \ (new \ | bug \) [0-9] \ + # [0-9] \ +" | cut -f2 -d '' `
if [ " `git log -1 | sed"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
# we determine from the third line of the commit message the mail,
# to which you want to send an email,
# by default, the mail of the current committer is set.
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
# form the name of the patch file
patchname = " $ (date +% j% H% M% s) .patch "
# save the diff of the committed commit,
( git diff-index -p -M HEAD ^) > $ patchname
# take the last message from the
git log except for the control text 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
# we send by means of 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
How it works
Most importantly, when starting work on a new task, it is necessary in the operational repository of the current programmer to create a branch with the name that TS created when the task was created.The prepare-commit-msg hook inserts message sending options at the top of the commit message, such as:
- sendmail - whether to send the letter. If the message does not contain a line containing only this word, then the letter will not be sent.
- to - to which email to send. If it is not, the letter will be sent to the sender.
- [new_state = done] - a directive for TS that you need to set the message "Completed" or "Fixed" to the new message.
This parameter can be omitted, then TS will add new messages with the type “Comment”. - newroot - this parameter indicates whether the subject of the message should be redone. In TS, it is possible to move subtasks from one task to another, so just to not create a new branch, you can simply specify the new parent of the current task.
For example, you created a subtask (number 2084, ancestor number 754, key new754 # 2084) and started working on it, and then realized that the subtask should belong to another parent task (with number 458, new key new458 # 2084) and moved it to her. So that git does not start a new branch, you can add the following code in the commit message
Important: each parameter must be on a separate line, the number of spaces or tabs does not affect its detection.newroot=new458
command line
$ git add --all & git gui
Then press Ctrl + Enter and through the interval that you set the mail collector in TS, check the status of the task. Here the comment is framed in html, but this is the topic of a separate post.
Conclusion
A standard workflow consists of 4 main steps:- Setting the task in TS and copying the branch name for git.
- Creating a branch in git and switching to it.
You can execute it with one command:$ git checkout -b имя_ветви
- Task completion.
- Completing a task in TS, committing to git.
Why is this mechanism used?
The reason is that TS does not yet have integration with SCM GIT.And when it appears, it is not clear how the work with distributed repositories will be implemented.
And this solution allows several programmers who have their own zoo repositories to work on the task. And then combine them into one central, in which order and purity.
In addition, it is very convenient to work without having direct access to TS.
The project manager can create tasks and assign specific people to them. Letters will come to their mail that they have created a task or that he has been appointed responsible. He sees in the message message what the task is and the branch name for git, starts work on the task. At the end of the work, he quietly commits in the repository and may no longer worry that the task needs to be completed. Moreover, he can also remotely create subtasks knowing the key of the task of the ancestor by sending letters to the email from which mail is imported to TS with the subject in which the desired key is present. In response, letters will also come that he created the task.
Sources
- ProGit is an online git book .
- TrackStudio documentation .
- TS_HOME \ docs \ javadoc \ index.html - TrackStudio API manual, supplied with TS.
- Sending letters from the Windows command line using a GMail account .