From d1407847370be40d58dcffd28a584b07f169ee16 Mon Sep 17 00:00:00 2001 From: kjh2064 Date: Mon, 13 Jul 2026 10:11:07 +0900 Subject: [PATCH] fix(ci): resolve duplicate assembly attributes and flaky tests for deploy-prod and collection orchestrator --- .gitea/workflows/deploy-prod.yml | 24 +++++++++++++++---- .../Services/KisDataCollectionOrchestrator.cs | 10 ++++---- .../KisDataCollectionOrchestratorTests.cs | 5 +++- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/.gitea/workflows/deploy-prod.yml b/.gitea/workflows/deploy-prod.yml index d7228c37..d84f5e9c 100644 --- a/.gitea/workflows/deploy-prod.yml +++ b/.gitea/workflows/deploy-prod.yml @@ -218,20 +218,34 @@ jobs: echo "✓ Artifact checksum verified" - name: Validate Release Manifest + env: + ARTIFACT_NAME: ${{ steps.fetch.outputs.artifact }} + RELEASE_TAG: ${{ steps.fetch.outputs.tag }} + COMMIT_SHA: ${{ steps.fetch.outputs.commit }} run: | - ARTIFACT="${{ steps.fetch.outputs.artifact }}" python3 - <<'PY' import json import hashlib + import os import pathlib import sys - artifact = pathlib.Path("${ARTIFACT}") - manifest = json.loads(pathlib.Path("${ARTIFACT}.manifest.json").read_text(encoding="utf-8")) + artifact_name = os.environ["ARTIFACT_NAME"] + 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 = { "artifact": artifact.name, - "version": "${{ steps.fetch.outputs.tag }}", - "commit": "${{ steps.fetch.outputs.commit }}", + "version": release_tag, + "commit": commit_sha, } for key, value in expected.items(): diff --git a/src/dotnet/QuantEngine.Application/Services/KisDataCollectionOrchestrator.cs b/src/dotnet/QuantEngine.Application/Services/KisDataCollectionOrchestrator.cs index cde1a169..6ce57e6f 100644 --- a/src/dotnet/QuantEngine.Application/Services/KisDataCollectionOrchestrator.cs +++ b/src/dotnet/QuantEngine.Application/Services/KisDataCollectionOrchestrator.cs @@ -20,6 +20,8 @@ public class KisDataCollectionOrchestrator : ICollectionOrchestrator private readonly ILogger _logger; private readonly IRuntimeAuditTrailService _auditTrail; + public Func UtcNowProvider { get; set; } = () => DateTime.UtcNow; + public KisDataCollectionOrchestrator( IKisApiClient kisApiClient, ICollectionWriteRepository repository, @@ -70,7 +72,7 @@ public class KisDataCollectionOrchestrator : ICollectionOrchestrator if (IsMarketClosed()) { 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)) { cachedSnapshot = latest[0]; @@ -111,7 +113,7 @@ public class KisDataCollectionOrchestrator : ICollectionOrchestrator // Persist daily OHLCV bars 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); 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"); } - private static bool IsMarketClosed() + private bool IsMarketClosed() { // KST Time conversion (UTC+9) - var kst = DateTime.UtcNow.AddHours(9); + var kst = UtcNowProvider().AddHours(9); // Weekend check if (kst.DayOfWeek == DayOfWeek.Saturday || kst.DayOfWeek == DayOfWeek.Sunday) diff --git a/src/dotnet/QuantEngine.Core.Tests/KisDataCollectionOrchestratorTests.cs b/src/dotnet/QuantEngine.Core.Tests/KisDataCollectionOrchestratorTests.cs index de6de8cb..6ae1906f 100644 --- a/src/dotnet/QuantEngine.Core.Tests/KisDataCollectionOrchestratorTests.cs +++ b/src/dotnet/QuantEngine.Core.Tests/KisDataCollectionOrchestratorTests.cs @@ -48,10 +48,13 @@ public class KisDataCollectionOrchestratorTests [Fact] 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 ticker = "005930"; 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( RunId: "prev-run",