Skip to content

Commit 8a3ceed

Browse files
build(cli): skip SignaturesGen regen in CI to break the Reactor.Localization.Generator file-lock race
Root cause of the recurring CI "Unit Tests" failure on PR #437 and sporadically on main: `src/Reactor.Cli/Reactor.Cli.csproj` declares a `BeforeBuild` Exec target that shells out to a nested `dotnet build Reactor.SignaturesGen.csproj`. SignaturesGen ProjectReferences `Reactor.csproj`, which ProjectReferences `Reactor.Localization.Generator`. The OUTER build (`dotnet test tests/Reactor.Tests`) already produces `obj/x64/Debug/netstandard2.0/Reactor.Localization.Generator.dll` because `Reactor.Tests.csproj` directly references that project too. The outer and nested `dotnet build` processes have their own VBCSCompiler instances and don't coordinate — they race on the same output dll. The second writer hits CSC error CS2012 ("Cannot open ... for writing -- file may be locked by 'VBCSCompiler'"). The race window scales with project size, which is why PR #437's increased compile load triggers it consistently. The committed `skills/reactor.api.txt` is what pack (`Reactor.csproj:134`) and embed (`Reactor.Cli.csproj:84`) consume, both gated `Condition="Exists(...)"`. CI never actually needs to regen api.txt — it's a dev-machine convenience step. Fix: add `and '$(CI)' != 'true'` to the RunSignaturesGen Target's Condition. GitHub Actions sets `CI=true` as an env var; MSBuild picks it up as `$(CI)`. Verified locally: - `unset CI; dotnet build src/Reactor.Cli` — RunSignaturesGen fires (nested build runs, fast-up-to-date-checks skip everything since outputs are current). - `CI=true dotnet build src/Reactor.Cli` — RunSignaturesGen fully skipped (zero "RunSignaturesGen" / "SignaturesGen.csproj" mentions in verbose log). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 122e839 commit 8a3ceed

1 file changed

Lines changed: 14 additions & 2 deletions

File tree

src/Reactor.Cli/Reactor.Cli.csproj

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,21 @@
109109
targets net10.0-windows10.0.22621.0. A ProjectReference across that TFM
110110
boundary fails NuGet asset resolution at pack time, so we shell out
111111
instead — SignaturesGen runs its own AfterBuild step that writes
112-
skills/reactor.api.txt, which this csproj then embeds as a resource. -->
112+
skills/reactor.api.txt, which this csproj then embeds as a resource.
113+
114+
Skip in CI ('$(CI)' = 'true' is set by GitHub Actions). The nested
115+
`dotnet build` spawns its own VBCSCompiler instance that doesn't
116+
coordinate with the outer build — when an outer test/build target
117+
(e.g. `dotnet test tests/Reactor.Tests`, which itself ProjectReferences
118+
Reactor.Localization.Generator) is already producing
119+
obj/<plat>/<cfg>/<tfm>/Reactor.Localization.Generator.dll, the nested
120+
SignaturesGen build races on the same output file and the second
121+
writer loses with CSC error CS2012. The committed
122+
skills/reactor.api.txt is what pack + embed consume (both via
123+
Condition="Exists(...)"), so the regen is a dev-machine convenience —
124+
CI never needs to run it. -->
113125
<Target Name="RunSignaturesGen" BeforeTargets="BeforeBuild"
114-
Condition="'$(SkipSignaturesGen)' != 'true'">
126+
Condition="'$(SkipSignaturesGen)' != 'true' and '$(CI)' != 'true'">
115127
<Exec Command="dotnet build &quot;$(MSBuildThisFileDirectory)..\..\tools\Reactor.SignaturesGen\Reactor.SignaturesGen.csproj&quot; -c $(Configuration) -p:Platform=$(_SignaturesGenPlatform) --nologo -v:q"
116128
ConsoleToMSBuild="true"
117129
ContinueOnError="false" />

0 commit comments

Comments
 (0)