Compare commits

..
6 Commits
6 changed files with 110 additions and 53 deletions
+1 -1
View File
@@ -1 +1 @@
1.0.21
1.0.23
+13
View File
@@ -5,5 +5,18 @@
- Предполагается что все Ваши репозитории находятся в одной папке (к которой вы указываете путь в настройках).
- Предполагается что ветки в JIRA имеют название эквивалентное имени бранча в Mercurial.
# Настройки
- Режим работы:
- Mercurial - по коммитам в Mercurial, можем определять множественные коммиты в одну задачу (ветку) и пропорционально списывать время.
- Jira - выполняем JQL и равномерно распределяем время.
- Путь до репо (Режим Mercurial) - путь до папки, в которую клонируются исходники.
- Логин Jira - Логин в Jira (от этого пользователя будем выполнять запросы и вносить время).
- Пароль Jira - шифруется через DPAPI.
- Mercurial Name (Режим Mercurial) - обязателен к указанию для режима Mercurial - имя пользователя Mercurial, от которого проходят коммиты.
- Округление времени - Для красоты распределения времени тут устанавливается округление. По умолчанию - 15 минут, получим время 1:15, 0:30 итд. Остаток нераспределенного времени будет внесен в самую долгую задачу или же если это невозможно - количество рабочего времени будет увеличено или уменьшено.
- JQL (Режим Jira) - можно задать свой JQL для поиска задачь. Возможные замены: %USER% - Логин Jira, %DATE% дата на которую формируем список. Значнеие по умолчанию: status changed by '%USER%' during ("%DATE%","%DATE%")
- Время запуска - время автоматического запуска бота. Если была установлена галочка "тестовый прогон" - она будет снята.
- Добавлять описание (Режим Mercurial) - добавлять ли в описание CommitMessage, если не установлено - добавляются стандартные фразы программистов (типа "написание кода").
# Скачать
Скачать актуальную версию можно тут: https://github.com/monster1025/JiraTimeBot/releases/latest
+14 -7
View File
@@ -34,14 +34,13 @@ namespace JiraTimeBot.JiraIntegration
}
}
public List<Issue> GetTodayIssues(Settings settings, DateTime? date = null, CancellationToken cancellationToken = default(CancellationToken))
public List<Issue> GetIssuesByJQL(string jql, Settings settings, DateTime? date = null, CancellationToken cancellationToken = default(CancellationToken))
{
var jira = Jira.CreateRestClient(settings.JiraUrl, settings.JiraUserName, settings.JiraPassword);
date = date.GetValueOrDefault(DateTime.Now.Date);
var userName = settings.JiraUserName;
var jql = settings.JiraQuery;
if (string.IsNullOrEmpty(jql))
{
jql = $"status changed by '%USER%' during (\"%DATE%\",\"%DATE%\")";
@@ -53,7 +52,7 @@ namespace JiraTimeBot.JiraIntegration
try
{
List<Issue> affectedIssues =
jira.Issues.GetIssuesFromJqlAsync(jql, 50, 0, cancellationToken).Result.ToList();
jira.Issues.GetIssuesFromJqlAsync(jql, 100, 0, cancellationToken).Result.ToList();
return affectedIssues;
}
catch (Exception ex)
@@ -92,15 +91,24 @@ namespace JiraTimeBot.JiraIntegration
var hasTodayWorklog = false;
var workLogs = issue.GetWorklogsAsync().Result;
foreach (var workLog in workLogs)
var userWorklogs = workLogs.Where(w =>
w.CreateDate.GetValueOrDefault().Date == date && w.Author.Equals(settings.JiraUserName,
StringComparison.InvariantCultureIgnoreCase)).ToList();
foreach (var workLog in userWorklogs)
{
var timeSpent = TimeSpan.FromSeconds(workLog.TimeSpentInSeconds);
if (workLog.CreateDate.GetValueOrDefault().Date == date && workLog.Author == settings.JiraUserName)
{
var timeDiff = Math.Abs((timeSpent - taskTimeItem.Time).TotalMinutes);
if (timeDiff > 1 || userWorklogs.Count > 1)
{
if (timeDiff > 1)
{
_log.Trace($"Время отличается на {timeDiff} минут, удаляю worklog: {taskTimeItem.Branch} {workLog.Author} {workLog.CreateDate}: {workLog.TimeSpent}");
}
else
{
_log.Trace($"Найдено более одного ворклога на задачу, удаляю worklog: {taskTimeItem.Branch} {workLog.Author} {workLog.CreateDate}: {workLog.TimeSpent}");
}
if (!dummy)
{
issue.DeleteWorklogAsync(workLog);
@@ -113,7 +121,6 @@ namespace JiraTimeBot.JiraIntegration
hasTodayWorklog = true;
}
}
}
if (!hasTodayWorklog)
{
@@ -1,6 +1,8 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Atlassian.Jira;
using JiraTimeBot.Configuration;
using JiraTimeBot.Mercurial;
using JiraTimeBot.Mercurial.Objects;
@@ -24,9 +26,32 @@ namespace JiraTimeBot.JiraIntegration
{
date = date.GetValueOrDefault(DateTime.Now.Date);
var workTasks = new List<MercurialCommitItem>();
var issues = _jiraApi.GetTodayIssues(settings, date, cancellationToken);
var issues = _jiraApi.GetIssuesByJQL(settings.JiraQuery, settings, date, cancellationToken);
foreach (var issue in issues)
{
if (cancellationToken.IsCancellationRequested)
{
return new List<MercurialCommitItem>();
}
List<Comment> comments = new List<Comment>();
if (issue.Type?.Name != "Дубликат")
{
_log.Trace($"Получаю комментарии по задаче {issue.Key} ({issue.Type?.Name}).");
comments = issue.GetCommentsAsync(cancellationToken).Result?.ToList() ?? new List<Comment>();
}
else
{
_log.Trace($"Пропускаю комментарии по задаче {issue.Key} ({issue.Type?.Name}).");
}
var user = settings.JiraUserName;
var userComments = comments.Where(f => f.Author.Equals(user, StringComparison.InvariantCultureIgnoreCase)).ToList();
if (userComments.Any())
{
foreach (var comment in userComments)
{
workTasks.Add(new MercurialCommitItem
{
@@ -36,6 +61,18 @@ namespace JiraTimeBot.JiraIntegration
FilesAffected = 1
});
}
}
else
{
workTasks.Add(new MercurialCommitItem
{
Description = issue.Summary,
Time = issue.Updated.GetValueOrDefault(date.Value),
Branch = issue.Key.Value,
FilesAffected = 1
});
}
}
return workTasks;
}
+3 -3
View File
@@ -26,6 +26,6 @@ using System.Runtime.InteropServices;
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.21")]
[assembly: AssemblyFileVersion("1.0.21")]
[assembly: AssemblyInformationalVersion("1.0.21")]
[assembly: AssemblyVersion("1.0.23")]
[assembly: AssemblyFileVersion("1.0.23")]
[assembly: AssemblyInformationalVersion("1.0.23")]
@@ -78,7 +78,7 @@ namespace JiraTimeBot.TaskTime
_log.Trace($"Погрешность распределения времени: {remainMinutes}. Добавляю к первой задаче.");
}
if (workTimeItems.First().Time.TotalMinutes > Math.Abs(remainMinutes))
if (workTimeItems.First().Time.TotalMinutes > Math.Abs(remainMinutes) && remainMinutes < 0)
{
//если переборщили или не достаточно добавили до 8 часов - скореектируем остаток в первой задаче (она самая трудозатратная).
workTimeItems.First().Time += TimeSpan.FromMinutes(remainMinutes);