Sprint 정보를 DB에 저장하는 기능 추가.
This commit is contained in:
53
VTSFetcher/Helpers/SprintHelper.cs
Normal file
53
VTSFetcher/Helpers/SprintHelper.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace VTSFetcher.Helpers;
|
||||||
|
|
||||||
|
public static class SprintHelper
|
||||||
|
{
|
||||||
|
public static string ExtractActiveSprintName(string[] sprintData)
|
||||||
|
{
|
||||||
|
if (sprintData == null || sprintData.Length == 0)
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
// 먼저 ACTIVE 스프린트 찾기
|
||||||
|
foreach (var sprint in sprintData)
|
||||||
|
{
|
||||||
|
if (sprint.Contains("state=ACTIVE"))
|
||||||
|
{
|
||||||
|
var match = Regex.Match(sprint, @"name=([^,]+)");
|
||||||
|
if (match.Success)
|
||||||
|
{
|
||||||
|
return match.Groups[1].Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback - ACTIVE 스프린트가 없으면 가장 최근 CLOSED 스프린트 찾기
|
||||||
|
DateTime latestEndDate = DateTime.MinValue;
|
||||||
|
string latestSprintName = string.Empty;
|
||||||
|
|
||||||
|
foreach (var sprint in sprintData)
|
||||||
|
{
|
||||||
|
if (sprint.Contains("state=CLOSED"))
|
||||||
|
{
|
||||||
|
var endDateMatch = Regex.Match(sprint, @"endDate=([^,\]]+)");
|
||||||
|
var nameMatch = Regex.Match(sprint, @"name=([^,]+)");
|
||||||
|
|
||||||
|
if (endDateMatch.Success && nameMatch.Success)
|
||||||
|
{
|
||||||
|
// endDate 파싱 (예: 2025-12-19T09:18:00.000+09:00)
|
||||||
|
if (DateTime.TryParse(endDateMatch.Groups[1].Value, out DateTime endDate))
|
||||||
|
{
|
||||||
|
if (endDate > latestEndDate)
|
||||||
|
{
|
||||||
|
latestEndDate = endDate;
|
||||||
|
latestSprintName = nameMatch.Groups[1].Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return latestSprintName;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,6 +16,7 @@ public class Issue
|
|||||||
public string self { get; set; }
|
public string self { get; set; }
|
||||||
public string key { get; set; } // RYXMARUV1-NNNN
|
public string key { get; set; } // RYXMARUV1-NNNN
|
||||||
public Fields fields { get; set; }
|
public Fields fields { get; set; }
|
||||||
|
public string Sprint { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Fields
|
public class Fields
|
||||||
@@ -38,6 +39,7 @@ public class Fields
|
|||||||
public DateTime? duedate { get; set; }
|
public DateTime? duedate { get; set; }
|
||||||
public Issue parent { get; set; }
|
public Issue parent { get; set; }
|
||||||
public string customfield_10808 { get; set; } // Epic key
|
public string customfield_10808 { get; set; } // Epic key
|
||||||
|
public string[] customfield_10806 { get; set; } // Splint
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Assignee
|
public class Assignee
|
||||||
@@ -101,4 +103,3 @@ public class Issuetype
|
|||||||
public bool subtask { get; set; }
|
public bool subtask { get; set; }
|
||||||
public int avatarId { get; set; }
|
public int avatarId { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,4 +17,5 @@ public class VtsIssue
|
|||||||
public DateTimeOffset Published { get; set; }
|
public DateTimeOffset Published { get; set; }
|
||||||
public string? ObjectId { get; set; }
|
public string? ObjectId { get; set; }
|
||||||
public int NeedNotify { get; set; }
|
public int NeedNotify { get; set; }
|
||||||
|
public string? Sprint { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
@@ -27,8 +27,8 @@ public class VtsService
|
|||||||
var request = new HttpRequestMessage(HttpMethod.Get, uri);
|
var request = new HttpRequestMessage(HttpMethod.Get, uri);
|
||||||
request.Headers.Add("Accept", "application/json");
|
request.Headers.Add("Accept", "application/json");
|
||||||
request.Headers.Add("Authorization", $"Bearer {_appSettings.VTS.AccessToken}");
|
request.Headers.Add("Authorization", $"Bearer {_appSettings.VTS.AccessToken}");
|
||||||
Log.Debug("Fetch VTS issues ready. Fetch the issues updated after {last_fetch_time} in Project {target_project}.",
|
Log.Debug("Fetch VTS issues ready. Fetch the issues updated after {last_fetch_time} in Project {target_project}. ({fetch_url})",
|
||||||
lastFetchTime.ToString("yyyy-MM-dd HH:mm"), targetProject);
|
lastFetchTime.ToString("yyyy-MM-dd HH:mm"), targetProject, uri);
|
||||||
|
|
||||||
using var client = new HttpClient();
|
using var client = new HttpClient();
|
||||||
var response = await client.SendAsync(request, ct).ConfigureAwait(false);
|
var response = await client.SendAsync(request, ct).ConfigureAwait(false);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using System.Runtime.Intrinsics.X86;
|
|||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using System.Windows.Threading;
|
using System.Windows.Threading;
|
||||||
using VTSFetcher.Commands;
|
using VTSFetcher.Commands;
|
||||||
|
using VTSFetcher.Helpers;
|
||||||
using VTSFetcher.Models;
|
using VTSFetcher.Models;
|
||||||
using VTSFetcher.Repositories;
|
using VTSFetcher.Repositories;
|
||||||
using VTSFetcher.Repositories.Entities;
|
using VTSFetcher.Repositories.Entities;
|
||||||
@@ -119,10 +120,10 @@ public class MainViewModel : INotifyPropertyChanged
|
|||||||
_slackTimer.Tick += SlackTick;
|
_slackTimer.Tick += SlackTick;
|
||||||
_slackTimer.Start();
|
_slackTimer.Start();
|
||||||
|
|
||||||
//_statusTimer = new DispatcherTimer();
|
_statusTimer = new DispatcherTimer();
|
||||||
//_statusTimer.Interval = TimeSpan.FromSeconds(30);
|
_statusTimer.Interval = TimeSpan.FromSeconds(30);
|
||||||
//_statusTimer.Tick += StatusTick;
|
_statusTimer.Tick += StatusTick;
|
||||||
//_statusTimer.Start();
|
_statusTimer.Start();
|
||||||
|
|
||||||
FetchNowCommand = new RelayCommand(_ => FetchNow());
|
FetchNowCommand = new RelayCommand(_ => FetchNow());
|
||||||
SaveStatusCommand = new RelayCommand(_ => {
|
SaveStatusCommand = new RelayCommand(_ => {
|
||||||
@@ -215,6 +216,7 @@ public class MainViewModel : INotifyPropertyChanged
|
|||||||
Due = i.fields.duedate ?? new DateTime(1999, 12, 23, 23, 59, 59),
|
Due = i.fields.duedate ?? new DateTime(1999, 12, 23, 23, 59, 59),
|
||||||
Updated = i.fields.UpdatedAt,
|
Updated = i.fields.UpdatedAt,
|
||||||
Parent = i.fields.parent?.key,
|
Parent = i.fields.parent?.key,
|
||||||
|
Sprint = SprintHelper.ExtractActiveSprintName(i.fields.customfield_10806)
|
||||||
})).ToList();
|
})).ToList();
|
||||||
_sw.Stop();
|
_sw.Stop();
|
||||||
Log.Information("Fetched {issue_count} issues from VTS in {operation_time}ms"
|
Log.Information("Fetched {issue_count} issues from VTS in {operation_time}ms"
|
||||||
|
|||||||
Reference in New Issue
Block a user