microsoft / microsoft/microsoft-ui-reactor

Reactor.Cli can't build offline: one command forces a build-time npm download

Open
#1,133 0 comments 0 reactions 0 assignees View on GitHub
tech-debt
Dominant language
C#
Stars
646
Forks
54
Avg merge
1d 3h
Merged PRs (30d)
84

Description

## Summary

`src/Reactor.Cli` cannot be built without network access, because `GitHub.Copilot.SDK` downloads a platform-specific Copilot CLI npm tarball during `BeforeBuild`. The dependency exists to serve exactly one command — `mur loc translate` — but the cost is paid by every build of every other command.

## Repro

```
dotnet build src\Reactor.Cli -c Debug -p:Platform=x64
```

```
GitHub.Copilot.SDK.targets(108,5): error MSB3923: Failed to download file
"https://registry.npmjs.org/@github/copilot-win32-x64/-/copilot-win32-x64-1.0.79.tgz".
The SSL connection could not be established ... TLS alert: 'HandshakeFailure'.
```

Workaround:

```
dotnet build src\Reactor.Cli -c Debug -p:Platform=x64 -p:CopilotSkipCliDownload=true
```

## The coupling

`GitHub.Copilot.SDK` has exactly one consumer in the CLI:

```
src/Reactor.Cli/Loc/AzureOpenAiProvider.cs:2 using GitHub.Copilot;
src/Reactor.Cli/Loc/AzureOpenAiProvider.cs:33 await using var client = new CopilotClient();
```

(The other files matching "Copilot" reference it only in comments or env-var names. The file is renamed to `CopilotTranslationProvider.cs` in #1129.)

So building `mur check`, `mur doctor`, `mur docs`, or `mur --create` from source requires fetching an npm package that only `mur loc translate` will ever use.

## Why it's worth addressing

- **Offline and restricted-network builds fail** with an error that doesn't point at the fix. `MSB3923` naming an npm registry gives no hint that `-p:CopilotSkipCliDownload=true` exists.
- **The opt-out is silently lossy.** Building with the skip flag produces a `mur` whose `loc translate` will fail at runtime, with nothing recording that the binary is degraded.
- **The blast radius is disproportionate.** One command's optional AI backend gates the whole CLI's buildability.

## Options

1. **Move the translation backend into its own assembly** loaded on demand, so `GitHub.Copilot.SDK` isn't in the CLI's build graph. Cleanest, most work.
2. **Make the download lazy/tolerant** — set `CopilotSkipCliDownload=true` by default and have `loc translate` fetch or diagnose at first use, with a clear "run X to enable translation" message.
3. **Minimum, cheap:** keep current behaviour but catch the failure and emit an actionable message naming the opt-out property, and have `loc translate` fail at startup with a clear diagnostic when the binary was built without the asset.

Even option 3 removes most of the pain, since the current failure is a raw `MSB3923` with no breadcrumb.

## Context

Relevant to the broader question of whether `mur loc` is earning its keep: `loc translate` is the least-evidenced command in the CLI (there are zero `.resw` files anywhere in the repo), yet it is the one imposing a build-time network dependency on everything else.

Discovered while building `mur` from source at `88ef6db4`.

Contributor guide

Open the contributing guide

Research direction

Reproduce the offline build with src\Reactor.Cli and inspect the GitHub.Copilot.SDK build target plus src/Reactor.Cli/Loc/AzureOpenAiProvider.cs, the cited SDK consumer. Compare normal and CopilotSkipCliDownload=true builds, then establish a solution that keeps unrelated commands buildable offline and gives loc translate an actionable diagnostic when its asset is unavailable.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
build-system, cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.