Build and Test
Grex’s GUI, CLI, and .NET tests build only on Windows. WinUI XAML compilation, Windows App SDK, MSIX, and PRI tooling prevent a complete build on Linux or macOS, even with -p:EnableWindowsTargeting=true.
Only the Python tools under Scripts/ are cross-platform.
Prerequisites
Required:
- Windows 10 version 1809, build 17763, or later
- Git
- .NET 8 SDK
- a concrete target platform: x86, x64, or ARM64
Recommended:
- Windows 11
- Visual Studio 2022 with .NET desktop development tools, or VS Code with C# tooling
- Windows App Runtime 1.8 for running and notification tests
- PowerShell 5.1 or later
Optional:
- Docker Desktop for Docker integration
- WSL plus
grep,find,sed, andstatfor WSL integration - Inno Setup 6 or 7 to build
setup.exe - ImageMagick when replacing icon assets
Install common prerequisites:
winget install --id Microsoft.DotNet.SDK.8 -e --source winget
winget install --id Microsoft.WindowsAppRuntime.1.8 -e --source winget
The Windows App SDK NuGet packages are restored by the solution. The Windows App Runtime is needed to run the unpackaged GUI.
Clone and inspect
The repository intentionally tracks C#, XAML, project, and resource files as CRLF. Python, JSON, and generated notices use LF.
git clone https://github.com/visorcraft/Grex.git
cd Grex
git config core.autocrlf false
dotnet --info
Verify a critical resource file:
git ls-files --eol Strings/en-US/Resources.resw
Expected index form is i/crlf.
Restore
dotnet restore grex.sln
Do not omit the concrete platform from build, run, or test commands.
Build
Debug x64
dotnet build grex.sln -p:Platform=x64
Release x64
dotnet build grex.sln -c Release -p:Platform=x64
Other declared platforms
dotnet build grex.sln -p:Platform=x86
dotnet build grex.sln -p:Platform=ARM64
The project declares x86, x64, and ARM64. The maintained release workflow publishes win-x64 only.
Build individual projects
dotnet build Grex.csproj -p:Platform=x64
dotnet build Grex.Cli/Grex.Cli.csproj -p:Platform=x64
Run
GUI
dotnet run --project Grex.csproj -p:Platform=x64
After a Debug build:
.\bin\x64\Debug\net8.0-windows10.0.19041.0\Grex.exe
Avoid running elevated if testing notifications. Windows toasts can fail in an administrator session.
CLI
After a Debug build:
.\Grex.Cli\bin\x64\Debug\net8.0-windows10.0.19041.0\grex-cli.exe --help
.\Grex.Cli\bin\x64\Debug\net8.0-windows10.0.19041.0\grex-cli.exe "C:\repo" "TODO"
Through dotnet run, put CLI arguments after --:
dotnet run --project Grex.Cli/Grex.Cli.csproj -p:Platform=x64 -- "C:\repo" "TODO"
Test
Keep WindowsAppSdkBootstrapInitialize=false on test commands. The application project is an unpackaged WinUI executable, so its normal build injects the Windows App SDK bootstrap module initializer. Loading that initializer inside testhost keeps the Dynamic Dependency Lifetime Manager active after the tests finish. Test builds disable only that initializer; normal app builds and publishes keep it enabled.
Entire solution
dotnet test grex.sln -p:Platform=x64 -p:WindowsAppSdkBootstrapInitialize=false
Release configuration
dotnet test grex.sln -c Release -p:Platform=x64 -p:WindowsAppSdkBootstrapInitialize=false
Individual projects
dotnet test Tests/Grex.Tests.csproj -p:Platform=x64 -p:WindowsAppSdkBootstrapInitialize=false
dotnet test Tests/Grex.Cli.Tests/Grex.Cli.Tests.csproj -p:Platform=x64 -p:WindowsAppSdkBootstrapInitialize=false
dotnet test IntegrationTests/Grex.IntegrationTests.csproj -p:Platform=x64 -p:WindowsAppSdkBootstrapInitialize=false
dotnet test UITests/Grex.UITests.csproj -p:Platform=x64 -p:WindowsAppSdkBootstrapInitialize=false
One class or method
dotnet test Tests/Grex.Tests.csproj -p:Platform=x64 -p:WindowsAppSdkBootstrapInitialize=false --filter "FullyQualifiedName~SearchServiceTests"
dotnet test Tests/Grex.Tests.csproj -p:Platform=x64 -p:WindowsAppSdkBootstrapInitialize=false --filter "FullyQualifiedName~TestMethodName"
xUnit 2.9.3 does not provide Assert.Skip or Assert.SkipUnless. For a runtime condition, return early or use Xunit.SkippableFact. Static [Fact(Skip = "...")] is used for tests that require unavailable WinUI initialization.
Test scope
| Project | Scope |
|---|---|
| Grex.Tests | Services, models, ViewModels, control helpers, credits/license coverage |
| Grex.Cli.Tests | CLI runner and output formatters |
| Grex.IntegrationTests | Real filesystem and app integration |
| Grex.UITests | ViewModel-driven UI behavior |
UI tests do not use WinAppDriver. Some integration facts that instantiate full WinUI context are skipped.
Python script checks
These use the Python standard library and can run on Windows, Linux, or macOS:
python Scripts/test_add_localization_entry.py
python Scripts/test_remove_localization_entry.py
python Scripts/test_generate_third_party_notices.py
Pytest can also discover them when installed:
python -m pytest Scripts/test_add_localization_entry.py Scripts/test_remove_localization_entry.py Scripts/test_generate_third_party_notices.py
Publish
GUI
dotnet publish Grex.csproj -c Release -p:Platform=x64 --self-contained -r win-x64
Default output:
bin\Release\net8.0-windows10.0.19041.0\win-x64\publish\
CLI
dotnet publish Grex.Cli/Grex.Cli.csproj -c Release -p:Platform=x64 --self-contained -r win-x64
Default output:
Grex.Cli\bin\Release\net8.0-windows10.0.19041.0\win-x64\publish\
These publishes include the .NET runtime. The GUI still depends on Windows App Runtime 1.8 unless its deployment model changes.
One-command package build
Run from a non-elevated Windows PowerShell:
.\build.ps1
The script has no parameters and uses Release, x64, and win-x64. It:
- reads the version from
Directory.Build.props; - restores
grex.sln; - builds the solution;
- runs all solution tests;
- publishes self-contained GUI and CLI folders;
- creates versioned ZIP files in
dist\; - creates an Inno Setup installer when
ISCC.exeis available.
Artifacts:
dist\grex-<version>-win-x64.zip
dist\grex-cli-<version>-win-x64.zip
dist\grex-<version>-setup.exe
If tests fail, build.ps1 still produces artifacts for inspection, then exits with code 1. Do not release those artifacts.
If Inno Setup is unavailable, ZIP creation succeeds and setup creation is skipped with a warning.
Installer behavior
Grex.iss creates a per-user x64-compatible installer:
- install root:
%LocalAppData%\Programs\Grex; - GUI in the root;
- CLI in
cli\; - Start menu shortcut;
- optional desktop shortcut;
- optional current-user
PATHentry for the CLI; - built-in uninstaller that removes that PATH entry.
The script does not code-sign the installer or install Windows App Runtime.
Versioning
Never edit version strings by hand:
python Scripts/update_version.py 1.5.0
The script synchronizes:
Directory.Build.props;Properties/AssemblyInfo.cs;Package.appxmanifest;app.manifest;Controls/AboutView.xaml.cs.
Versions are three-part SemVer. Manifests and assembly versions receive the required fourth .0 component.
Third-party notices
When adding, removing, or updating a GUI NuGet dependency:
- Update
Assets/third-party-licenses.json. -
Regenerate notices:
python Scripts/generate_third_party_notices.py -
Run:
python Scripts/test_generate_third_party_notices.py dotnet test Tests/Grex.Tests.csproj -p:Platform=x64 -p:WindowsAppSdkBootstrapInitialize=false --filter "FullyQualifiedName~CreditsLicenseCoverageTests"
Never hand-edit THIRD-PARTY-NOTICES.txt.
Build/test-only packages belong in KnownBuildOnlyExclusions inside Tests/Controls/CreditsLicenseCoverageTests.cs, with a reason, rather than in the redistributed-component manifest.
Localization maintenance
Add one key to every catalog:
python Scripts/add_localization_entry.py "KeyName" "English text"
Remove one key from every catalog:
python Scripts/remove_localization_entry.py "KeyName"
Report status:
python Scripts/generate_translation_status.py
Review Translations before running bulk translation. .resw files must remain CRLF.
Assets
Assets/Grex.png is the source artwork. Grex.csproj, Package.appxmanifest, and Grex.iss reference the generated PNG and ICO variants.
There is no maintained icon-generation project in this repository. When replacing artwork:
- regenerate every referenced size with a deterministic image tool;
- preserve transparency and exact dimensions;
- verify manifest and project paths;
- inspect the installer icon and running app;
- avoid touching unrelated binary assets.
Continuous integration
.github/workflows/ci.yml runs on pull requests, pushes to master, and manual dispatches. Its Windows x64 job restores and builds the Release solution, then runs unit, CLI, integration, and UI projects as separate named steps. Each step reuses restored packages and incremental build output. A three-minute per-test hang detector stops deadlocked test hosts, and the job has a 30-minute ceiling.
Release workflow
.github/workflows/release.yml runs when a v* tag is pushed. On windows-latest, it:
- checks out the tag;
- installs .NET 8;
- restores and builds Release x64;
- tests the full solution;
- publishes self-contained win-x64 GUI and CLI;
- creates both ZIP files;
- compiles the Inno Setup installer;
- uploads artifacts;
- creates a GitHub Release.
The release workflow fails before packaging if any solution test fails. Maintainers should still run the same test gate before tagging.
Release tags are signed and annotated:
git tag -m "Grex 1.5.0" v1.5.0
git push origin master
git push origin v1.5.0
See Contributing for the full maintainer checklist.
Troubleshooting
| Error or symptom | Cause and fix |
|---|---|
| XAML compiler failure on Linux/macOS | Unsupported host. Build on Windows. |
| Any CPU failure | Add -p:Platform=x64, x86, or ARM64. |
| App starts but notifications fail | Install Windows App Runtime 1.8 and launch non-elevated. |
Grex.exe missing resources |
Run from the complete build/publish directory; verify PRI and Assets\ copies. |
| Docker tests/features unavailable | Start Docker and confirm docker version. |
| WSL search unavailable | Confirm wsl --status and target command availability. |
Massive .resw diff |
Restore CRLF handling and rerun only the intended script. |
| Credits coverage test fails | Update the license manifest or justified build-only exclusions, then regenerate notices. |
| Release setup missing | Install Inno Setup or use the release workflow runner. |
Application runtime logs are written to %Temp%\Grex.log.