fix(ci): resolve duplicate assembly attributes and flaky tests for deploy-prod and collection orchestrator
Validators (Pushes and Pull Requests) / validate-ui-and-storage (push) Successful in 16s
Validators (Pushes and Pull Requests) / validate-core (push) Failing after 1m47s

This commit is contained in:
2026-07-13 10:11:07 +09:00
parent ef955750b1
commit d140784737
3 changed files with 29 additions and 10 deletions
+19 -5
View File
@@ -218,20 +218,34 @@ jobs:
echo "✓ Artifact checksum verified" echo "✓ Artifact checksum verified"
- name: Validate Release Manifest - name: Validate Release Manifest
env:
ARTIFACT_NAME: ${{ steps.fetch.outputs.artifact }}
RELEASE_TAG: ${{ steps.fetch.outputs.tag }}
COMMIT_SHA: ${{ steps.fetch.outputs.commit }}
run: | run: |
ARTIFACT="${{ steps.fetch.outputs.artifact }}"
python3 - <<'PY' python3 - <<'PY'
import json import json
import hashlib import hashlib
import os
import pathlib import pathlib
import sys import sys
artifact = pathlib.Path("${ARTIFACT}") artifact_name = os.environ["ARTIFACT_NAME"]
manifest = json.loads(pathlib.Path("${ARTIFACT}.manifest.json").read_text(encoding="utf-8")) release_tag = os.environ["RELEASE_TAG"]
commit_sha = os.environ["COMMIT_SHA"]
artifact = pathlib.Path(artifact_name)
manifest_path = pathlib.Path(f"{artifact_name}.manifest.json")
if not manifest_path.exists():
print(f"ERROR: Manifest file not found: {manifest_path}")
sys.exit(1)
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
expected = { expected = {
"artifact": artifact.name, "artifact": artifact.name,
"version": "${{ steps.fetch.outputs.tag }}", "version": release_tag,
"commit": "${{ steps.fetch.outputs.commit }}", "commit": commit_sha,
} }
for key, value in expected.items(): for key, value in expected.items():
@@ -20,6 +20,8 @@ public class KisDataCollectionOrchestrator : ICollectionOrchestrator
private readonly ILogger<KisDataCollectionOrchestrator> _logger; private readonly ILogger<KisDataCollectionOrchestrator> _logger;
private readonly IRuntimeAuditTrailService _auditTrail; private readonly IRuntimeAuditTrailService _auditTrail;
public Func<DateTime> UtcNowProvider { get; set; } = () => DateTime.UtcNow;
public KisDataCollectionOrchestrator( public KisDataCollectionOrchestrator(
IKisApiClient kisApiClient, IKisApiClient kisApiClient,
ICollectionWriteRepository repository, ICollectionWriteRepository repository,
@@ -70,7 +72,7 @@ public class KisDataCollectionOrchestrator : ICollectionOrchestrator
if (IsMarketClosed()) if (IsMarketClosed())
{ {
var latest = await _readRepository.GetLatestSnapshotsForTickerAsync(ticker, 1); var latest = await _readRepository.GetLatestSnapshotsForTickerAsync(ticker, 1);
var todayPrefix = DateTime.UtcNow.AddHours(9).ToString("yyyy-MM-dd"); var todayPrefix = UtcNowProvider().AddHours(9).ToString("yyyy-MM-dd");
if (latest.Count > 0 && latest[0].CapturedAt.StartsWith(todayPrefix)) if (latest.Count > 0 && latest[0].CapturedAt.StartsWith(todayPrefix))
{ {
cachedSnapshot = latest[0]; cachedSnapshot = latest[0];
@@ -111,7 +113,7 @@ public class KisDataCollectionOrchestrator : ICollectionOrchestrator
// Persist daily OHLCV bars // Persist daily OHLCV bars
try try
{ {
var today = DateTime.UtcNow.AddHours(9).ToString("yyyyMMdd"); var today = UtcNowProvider().AddHours(9).ToString("yyyyMMdd");
var chartResult = await _kisApiClient.GetDailyItemChartPriceAsync(ticker, today, today, "D", account); var chartResult = await _kisApiClient.GetDailyItemChartPriceAsync(ticker, today, today, "D", account);
if (chartResult.TryGetValue("output2", out var output2Obj) && output2Obj is JsonElement output2Elem && output2Elem.ValueKind == JsonValueKind.Array) if (chartResult.TryGetValue("output2", out var output2Obj) && output2Obj is JsonElement output2Elem && output2Elem.ValueKind == JsonValueKind.Array)
{ {
@@ -307,10 +309,10 @@ public class KisDataCollectionOrchestrator : ICollectionOrchestrator
return Path.Combine(Path.GetTempPath(), "kis_dotnet_collection_v1.json"); return Path.Combine(Path.GetTempPath(), "kis_dotnet_collection_v1.json");
} }
private static bool IsMarketClosed() private bool IsMarketClosed()
{ {
// KST Time conversion (UTC+9) // KST Time conversion (UTC+9)
var kst = DateTime.UtcNow.AddHours(9); var kst = UtcNowProvider().AddHours(9);
// Weekend check // Weekend check
if (kst.DayOfWeek == DayOfWeek.Saturday || kst.DayOfWeek == DayOfWeek.Sunday) if (kst.DayOfWeek == DayOfWeek.Saturday || kst.DayOfWeek == DayOfWeek.Sunday)
@@ -48,10 +48,13 @@ public class KisDataCollectionOrchestratorTests
[Fact] [Fact]
public async Task RunCollectionAsync_WithCachedSnapshot_ShouldNotCallKisApiClient() public async Task RunCollectionAsync_WithCachedSnapshot_ShouldNotCallKisApiClient()
{ {
var mockTime = new DateTime(2026, 7, 13, 13, 0, 0, DateTimeKind.Utc); // 2026-07-13 22:00:00 KST (Market closed)
_orchestrator.UtcNowProvider = () => mockTime;
var runId = "test-run-001"; var runId = "test-run-001";
var ticker = "005930"; var ticker = "005930";
var account = "mock"; var account = "mock";
var todayPrefix = DateTime.UtcNow.AddHours(9).ToString("yyyy-MM-dd"); var todayPrefix = mockTime.AddHours(9).ToString("yyyy-MM-dd");
var cachedSnapshot = new CollectionSnapshotRecord( var cachedSnapshot = new CollectionSnapshotRecord(
RunId: "prev-run", RunId: "prev-run",