feat: compile-check can build and run its changed-files check worker
Merged
HA
2d ago+1586+1586+0123456789012345678901234567890123456789-0-0-0123456789
Summary
uloop compile-checkcan now build the changed-files check worker on the user's machine with the Editor's own dotnet and Roslyn, cache it, and call it. Nothing calls this from a compile-check run yet; the next pull request wires it in.
User Impact
- No change in behavior yet. When the worker is wired in, its first build costs one csc run per Editor toolchain and is reused afterwards. An environment where the worker cannot build pays for that build once and then falls back to a full compile, instead of trying again on every run.
Changes
- New package
cli/dispatcher/internal/compilecheck/fastcheck:- The worker's C# sources are embedded with
go:embed. Bootstrap.Ensurebuilds the worker withdotnet exec csc.dll, references only the managed assemblies of the Editor's shared framework plus the Editor's Roslyn, and copies csc's runtime config and the Roslyn directory next toworker.dll.- A managed assembly is a PE file with a CLR runtime header; native images would fail with CS0009. The PE headers are read directly rather than with
debug/pe, becausedebug/perefuses the machine values of the ReadyToRun images in the macOS shared framework (ARM64 reads 0xEC20), and leaving those out dropsSystem.Private.CoreLib. - The cache key covers a build recipe version, the embedded sources, and the four toolchain paths. Each run builds in its own temporary directory and renames it into place, so runs that start together never read a half-built worker. A leftover directory under the key that is neither a worker nor a failure record is set aside and replaced.
- A build where csc ran to completion and failed is recorded in
build-failed.txtand not retried for the same key. A build stopped by its context, killed by a signal, or that could not start records nothing. Client.Fingerprint/Client.Checkwrite a JSON request, rundotnet exec worker.dll <command> <in> <out>, and read the JSON response. A non-zero exit, a timeout (one minute by default), a missing or malformed response, or an unknown outcome is an error. The request and response files are removed after each call.
- The worker's C# sources are embedded with
Verification
cli/dispatcher:golangci-lint fmt --diff,go vet ./...,golangci-lint run ./...(0 issues),go test ./...all pass.cli/commonis unchanged, so the other modules were not rerun.- Dispatcher module coverage measured locally with the CI exclusions is 94.19%, against a baseline of 94.2.
- On macOS arm64,
Bootstrap.Ensurebuilt the worker andClient.Fingerprintreturned fingerprints and content hashes from the real worker with the dotnet and Roslyn of Unity 2022.3, 6000.3, and 6000.7. With the old machine check put back, the same build fails with CS0518. - Mutation checks, each restored afterwards and each failing the test that pins it: the machine check, the recipe version in the key, recording a signaled build, and setting aside the incomplete directory.
- Repository CI that triggers only for
mainmay not run on this pull request into the integration branch; the commands above are the local equivalent.