Skip to main content

Building and testing

Runesmith is one solution, Runesmith.slnx, with the projects in src/, the build tools in tools/, the template in templates/, the test projects in tests/ and the benchmarks in benchmarks/. The official plugins live in their own repositories in the RunesmithHub organization. This page covers the tools you need and the commands CI runs, so a change that passes here passes there.

Tools​

  • The .NET 10 SDK. global.json pins the feature band and rolls forward to newer ones.
  • Node.js 22, only for the documentation site in website/.

On NixOS​

Avalonia and SkiaSharp load the system's font and X11 libraries by name when the app starts. NixOS keeps those out of the default library path, so running the app fails with Unable to load shared library 'libSkiaSharp' and libfontconfig.so.1: cannot open shared object file. The repository's flake.nix has a development shell with the .NET SDK, Node.js, xvfb-run and those libraries on LD_LIBRARY_PATH:

nix develop
dotnet run --project src/Runesmith.App

An IDE has to start in that environment too, or the app it runs fails the same way:

  • Start it from the shell, such as nix develop -c <ide> Runesmith.slnx.
  • Or use direnv: .envrc loads the shell when you enter the folder (direnv allow once), and an IDE plugin for direnv passes it on to the IDE.

HammerUI​

Runesmith's user interface comes from HammerUI. The projects that use it set UsesHammerUI, and Directory.Build.targets decides where it comes from:

WhenHammerUI comes from
A HammerUI checkout next to the Runesmith checkout, at ../HammerUIThat checkout, as a project reference, so both can change together.
There is noneThe HammerUI package from the Runesmith Hub feed, https://nuget.runesmith.dev/index.json, with no sign-in.

For the checkout, clone both repositories into the same folder:

git clone https://github.com/RunesmithHub/HammerUI.git
git clone https://github.com/RunesmithHub/Runesmith.git

nuget.config maps HammerUI and RunesmithHub.* to the hub feed only. The hub library, RunesmithHub.Protocol, works the same way, from a checkout of RunesmithHub/hub at ../hub.

Build​

dotnet build Runesmith.slnx -warnaserror

The build has no warnings, and CI treats any warning as an error. Analyzers run at the latest-recommended level, and BannedSymbols.txt rejects calls that are easy to get wrong; each entry says why and what to use instead.

Building src/Runesmith.App also brings in the bundled plugins; see Bundled plugins.

Bundled plugins​

Runesmith ships the official Git and GitHub plugins as published on the plugin hub; the other official plugins, such as C# and Java, are installed from the hub by the users who want them. bundled-plugins.json at the repository root pins each shipped plugin by id, version and the SHA-256 of its package:

bundled-plugins.json
{
"index": "https://runesmithhub.github.io/registry/",
"plugins": [
{ "id": "runesmith.git", "version": "0.1.0", "sha256": "aa827f72..." }
]
}

After src/Runesmith.App builds, tools/Runesmith.BundledPlugins runs. It updates its copy of the hub's signed index, starting from the root in src/Runesmith.App/Hub/root.json, and checks that each pinned version is published, not blocked or frozen, and published with the pinned SHA-256. It downloads each package, checks its length and hash, and unpacks it into plugins/<id> next to the executable, in the same layout as a plugin the hub installs. Publishing copies the same folders.

The index and the packages are kept under src/Runesmith.App/obj/bundled-plugins, packages by their hash, so later builds work without a network connection. Without a connection and without that cache, Debug builds warn and leave the plugins out; Release builds and publishing fail. The tool never uses a package the signed index does not pin.

To update a bundled plugin, set its version and sha256 to those of a published version in the hub's index. The build checks both and fails when they do not match.

Work on an official plugin​

Each official plugin has its own repository, such as RunesmithHub/plugin-csharp, built against the SDK and language packages from the hub feed. To run your changes in Runesmith, build the plugin and install it as a local plugin from the plugin's repository:

dotnet build src/Runesmith.CSharp -t:InstallPlugin

InstallPlugin writes the plugin into the user's plugins folder, under RUNESMITH_HOME when it is set. Bundled plugins live next to the executable and updates from the hub in hub/plugins in Runesmith's data folder, so the local copy sits beside them and never changes their files (see Where plugins live). A local copy of a plugin that comes with Runesmith or from the hub does not load until you allow it; until then the plugin manager marks it Not loaded and says why. To run the local copy:

  1. Turn on Local copies replace plugins in Settings, under Plugins, or add "plugins.allowLocalOverrides": true to your own settings.json. A folder's .runesmith/settings.json cannot turn it on.
  2. Restart Runesmith. The local copy runs in place of the bundled or hub copy, whatever its version.
  3. Sign in again where the plugin asks. The local copy has its own secrets and storage, so it never sees the bundled copy's sign-ins or files, and they stay as they were.

While a local copy runs, Runesmith shows a notice at each start, and the plugin manager's Installed tab marks it Replaces the installed plugin. Remove the local copy, or turn the setting off, to go back to the bundled or hub copy, which stayed as it was.

Test​

dotnet test --solution Runesmith.slnx -- --ignore-exit-code 8

Tests run on Microsoft.Testing.Platform with xUnit v3, as global.json sets. A test project that has no tests yet ends with exit code 8, which --ignore-exit-code 8 accepts.

Benchmarks​

benchmarks/Runesmith.Benchmarks is a BenchmarkDotNet project, with benchmarks such as completion ranking and the C# analyzer's answer times. Run it in Release:

dotnet run --project benchmarks/Runesmith.Benchmarks --configuration Release

benchmarks/Runesmith.TypingBenchmark types into the running editor and measures how fast it responds; see Language services.

Formatting​

dotnet format whitespace Runesmith.slnx
dotnet format style Runesmith.slnx

The Checks workflow runs both with --verify-no-changes on every pull request.

The documentation site​

The site is a Docusaurus project in website/:

cd website
npm ci
npm start

npm run build checks the prose against website/STYLE.md first, then fails on broken links and anchors. npm run typecheck checks the site's TypeScript. The site's README.md has the details.