Преглед изворни кода

Fix flaky API tests: config.yaml creation race

CI failed with 'config/config.yaml already exists' when two API test
classes started WebApplicationFactory hosts in parallel: both pointed
at the default ./config dir (the factory's in-memory config overrides
apply too late for values read during BuildApp), passed the
File.Exists check together, and the loser's FileMode.CreateNew threw.

- ApiTestBase now pins RPK_YAML_DIR to each test class's temp dir via
  UseSetting, which does reach BuildApp — API test classes no longer
  share ./config/config.yaml at all.
- Program.BuildApp tolerates losing the create race (two instances
  sharing a config volume), keeping the concurrently created file.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Tim Jones пре 1 дан
родитељ
комит
f648190fe5
2 измењених фајлова са 16 додато и 8 уклоњено
  1. 14 8
      RackPeek.Web/Program.cs
  2. 2 0
      Tests/Api/ApiTestBase.cs

+ 14 - 8
RackPeek.Web/Program.cs

@@ -31,14 +31,20 @@ public class Program {
         var yamlFilePath = Path.Combine(yamlPath, yamlFileName);
 
         if (!File.Exists(yamlFilePath)) {
-            await using var fs = new FileStream(
-                yamlFilePath,
-                FileMode.CreateNew,
-                FileAccess.Write,
-                FileShare.None);
-
-            await using var writer = new StreamWriter(fs);
-            await writer.WriteLineAsync("# default config");
+            try {
+                await using var fs = new FileStream(
+                    yamlFilePath,
+                    FileMode.CreateNew,
+                    FileAccess.Write,
+                    FileShare.None);
+
+                await using var writer = new StreamWriter(fs);
+                await writer.WriteLineAsync("# default config");
+            }
+            catch (IOException) when (File.Exists(yamlFilePath)) {
+                // Another instance created the file between the existence
+                // check and CreateNew — the config is there, carry on.
+            }
         }
 
         builder.Services.ConfigureHttpJsonOptions(options => {

+ 2 - 0
Tests/Api/ApiTestBase.cs

@@ -25,6 +25,8 @@ public abstract class ApiTestBase : IDisposable {
 
         Factory = new WebApplicationFactory<Program>()
             .WithWebHostBuilder(builder => {
+                builder.UseSetting("RPK_YAML_DIR", _tempDir);
+
                 builder.ConfigureAppConfiguration((context, configBuilder) => {
                     var baseConfig = new Dictionary<string, string?> {
                         ["RPK_API_KEY"] = "test-key-123"