-
Notifications
You must be signed in to change notification settings - Fork 4
15 development
Build, test, publish, versioning, localization, code style. Related: 02 — Projects & Solution · 14 — Testing
- .NET SDK 10.0.x (
global.jsonpins10.0.0, roll-forward latestMajor, no prereleases). - Windows (the projects target
net10.0-windowsand use WPF/DPAPI).
# build everything (Windows, both TFMs)
dotnet build SimpleLauncher.sln -c Debug
dotnet build SimpleLauncher.sln -c Release
# build one project
dotnet build SimpleLauncher/SimpleLauncher.csproj -c Debug
dotnet build SimpleLauncher.Avalonia/SimpleLauncher.Avalonia.csproj -c Debug
# run unit tests — WPF (net10.0-windows) and Avalonia (net10.0, headless)
dotnet test SimpleLauncher.Tests/SimpleLauncher.Tests.csproj -c Debug
dotnet test SimpleLauncher.Avalonia.Tests/SimpleLauncher.Avalonia.Tests.csproj -c Debug
# fast local WPF run (skip live mount + network tests that need G:\/X:\/J:\ or internet)
dotnet test SimpleLauncher.Tests/SimpleLauncher.Tests.csproj -c Debug \
--filter "FullyQualifiedName!~IntegrationTests&FullyQualifiedName!~ApiConnectivity&FullyQualifiedName!~UrlValidation&FullyQualifiedName!~MountChd&FullyQualifiedName!~MountZip"
# WSL2 / Linux — Avalonia only (net10.0 TFM, no Windows desktop pack)
dotnet build SimpleLauncher.Avalonia/SimpleLauncher.Avalonia.csproj -c Debug -f net10.0
dotnet test SimpleLauncher.Avalonia.Tests/SimpleLauncher.Avalonia.Tests.csproj -c Debug
wsl dotnet test SimpleLauncher.Avalonia.Tests/SimpleLauncher.Avalonia.Tests.csproj -c DebugSee 14 — Testing for test filters and the known slow network test. Tests are not run by CI (the suites include live endpoints and real app launches); verification stays local + WSL2. The GitHub Actions workflows only package releases and deploy the docs — see Continuous integration.
dotnet publish SimpleLauncher/SimpleLauncher.csproj -c Release -r win-x64
dotnet publish SimpleLauncher/SimpleLauncher.csproj -c Release -r win-arm64-
RuntimeIdentifiersarewin-x64;win-arm64; every bundled tool ships both variants (X.exe+X_arm64.exe) and is resolved per architecture at runtime (see 11 — Bundled Tools). - Release zip naming for updates:
release_{version}_{rid}.zip(the unified WPF + Avalonia payload) +updater_{rid}.zip(the singleUpdater.exeshared by both apps) (see 16 — Updater). - A
publish-check\folder with per-RID outputs is used locally to validate published payloads.
scripts/package-release.ps1 reproduces the unified release artifacts (also used by CI):
pwsh scripts/package-release.ps1 -Version 5.7.0
# -> artifacts\release\release_5.7.0_win-x64.zip, release_5.7.0_win-arm64.zip
# -> artifacts\release\updater_win-x64.zip, updater_win-arm64.zip- The bundle places
SimpleLauncher.exe(WPF) andSimpleLauncher.Avalonia.exe(Avalonia) next to each other and ships one shared set of content files (images/,tools/,samples/,appsettings.json, …). Users choose which app to run. - Both apps are published framework-dependent (the .NET 10 Desktop Runtime is required on the target machine), so the payload carries no runtime: WPF as a single file, Avalonia as a normal multi-file publish. The updater is published framework-dependent single-file with its Avalonia native libraries bundled (
IncludeNativeLibrariesForSelfExtract), soupdater_{rid}.zipis one self-sufficientUpdater.exethat also works on legacy WPF-only installs. - Validates the version against
SimpleLauncher.csproj(canonical),SimpleLauncher.Core.csproj, both app csproj files/manifests andSimpleLauncher.Avalonia.Updater.csprojbefore publishing. - Merges the two publish outputs and fails loudly when a shared file has different content (for example
appsettings.jsondrift);AppSettingsFilesAreIdenticalguards the two appsettings sources in the test suite. - Prunes the other architecture's bundled tools from the payload (plus the Linux-only extension-less
RetroAchievementsSharpbinaries) and packagesUpdater.exealone intoupdater_{rid}.zip(the updater's staging tree is cleaned before each publish so stale sidecars cannot accumulate). - Prunes debug symbol files (
*.pdb) — never needed at runtime; the native SkiaSharp/HarfBuzzSharp symbols alone account for roughly 105 MB.
The Avalonia app targets both net10.0 (Linux) and net10.0-windows (Windows), so the
target framework must be specified when publishing:
dotnet publish SimpleLauncher.Avalonia/SimpleLauncher.Avalonia.csproj -c Release -f net10.0-windows -r win-x64
dotnet publish SimpleLauncher.Avalonia/SimpleLauncher.Avalonia.csproj -c Release -f net10.0-windows -r win-arm64
dotnet publish SimpleLauncher.Avalonia/SimpleLauncher.Avalonia.csproj -c Release -f net10.0 -r linux-x64
dotnet publish SimpleLauncher.Avalonia/SimpleLauncher.Avalonia.csproj -c Release -f net10.0 -r linux-arm64
# Verify the output includes the bundled tools + updater
ls SimpleLauncher.Avalonia/bin/Release/net10.0/linux-x64/publish/ | head -20
ls SimpleLauncher.Avalonia/bin/Release/net10.0-windows/win-x64/publish/Updater* 2>/dev/null | head- The
net10.0TFM is Linux-only (audio uses libsndfile/SoundFileReader). Publishing it with a Windows RID (-f net10.0 -r win-x64) is rejected by a build guard: theWINDOWSsymbol would not be defined, soPlaySoundEffectswould take the Linux path and crash on Windows (DllNotFoundException: libsndfile, no Windows native binary is shipped). - The Windows publish uses Media Foundation + WaveOut, so
libsndfileis not needed there. - Windows-only features (F8 global hotkey, active-window screenshot) are compiled with
#if WINDOWS(defined only on thenet10.0-windowsTFM) and pullSystem.Drawing.Commonas a package reference conditional on that TFM; the tray icon is cross-platform. -
WSL2 smoke test (Linux): after
publish -f net10.0 -r linux-x64, run the binary under WSLg:wsl ./SimpleLauncher.Avalonia/bin/Release/net10.0/linux-x64/publish/SimpleLauncher.Avalonia— window 1280×800 should map, single-instance mutex enforces one instance, tray icon is NoOp on WSL2. The full headless test suite also runs on WSL2 without a display:wsl dotnet test SimpleLauncher.Avalonia.Tests/... -c Debug(518 tests viaAvalonia.Headless).
Version 5.7.0 must stay in sync across:
-
SimpleLauncher\SimpleLauncher.csproj(AssemblyVersion,FileVersion,Version) -
SimpleLauncher.Core\SimpleLauncher.Core.csproj(same three) SimpleLauncher.Tests\SimpleLauncher.Tests.csproj-
SimpleLauncher\app.manifest(assemblyIdentity version) -
SimpleLauncher.Avalonia\SimpleLauncher.Avalonia.csproj(same three, matching the WPF app) -
SimpleLauncher.Avalonia\app.manifest(assemblyIdentity version) -
SimpleLauncher.Avalonia.Updater\SimpleLauncher.Avalonia.Updater.csproj(Version, matching the WPF app)
VersionConsistencyTests enforces the manifests, the Avalonia csproj/manifest and the shared
appsettings.json in local runs; scripts/package-release.ps1 validates all of the above when
packaging. Bump all of them together.
- 18 languages as WPF resource dictionaries:
SimpleLauncher\resources\strings.{code}.xaml(ar, bn, de, en, es, fr, hi, id, it, ja, ko, nl, pt-br, ru, tr, ur, vi, zh-hans). - 18 languages as Avalonia JSON resources:
SimpleLauncher.Avalonia\Resources\strings.{code}.json— UTF-8 without BOM, 2-space indent,StringComparer.OrdinalIgnoreCasekey order.strings.en.jsonis the canonical Avalonia key set (2669 keys). -
SimpleLauncher.ResourceTranslator(OpenRouter API, defaultz-ai/glm-5.3-flash) translates missing keys for both projects; see its README. - Unit tests guard against common translation issues: missing keys in other languages, duplicate/mismatched resource keys, empty values, key-count mismatches (
DetectMissingResourceStringsTestsfamily — WPF XAML and Avalonia JSON/AXAML source scan). -
DetectMissingResourceStringsTestsscans the Avalonia source (.csGetString(...)calls and.axaml{ext:Translate Key}usages) and auto-adds missing keys with fallback values tostrings.en.json;LocalizationTests.EveryLanguageFileSharesTheEnglishKeySetfails with a per-language missing-key list when files are out of sync. - Add a new language: create
strings.{code}.xaml(WPF) andstrings.{code}.json(Avalonia, UTF-8 without BOM + sorted), register it inApp.ChangeLanguage/LanguageMenuService(WPF) andAvaloniaLanguageMenuService(Avalonia), run the translator, and update the resource-key tests if needed.
-
Meziantou.Analyzer 3.0.139 and Microsoft.CodeAnalysis.NetAnalyzers 10.0.302 (both
PrivateAssets). -
Nullableenabled everywhere;LangVersion 14; implicit usings + globalusing System.IO; using System.Net.Http; using Serilog;. -
NoWarnin app:NU1903;CS0436. - Tests must satisfy the analyzers (e.g.
StringComparisonoverloads on string assertions). - Conventions observed in the codebase: services take Serilog
ILogger; UI services use the host-interface pattern (Initialize(host)) instead of receiving windows; ViewModels use CommunityToolkit.Mvvm.
GitHub Actions only builds release packages and deploys documentation — it never runs the test suites (they include live endpoints and real app launches; run them locally).
| Workflow | Trigger | What it does |
|---|---|---|
.github/workflows/release.yml |
manual (workflow_dispatch) with a version |
Packages the unified WPF + Avalonia bundle for win-x64 + win-arm64 via scripts/package-release.ps1, uploads the zips as workflow artifacts, and creates/updates the release{version} GitHub release with release_{version}_{rid}.zip + updater_{rid}.zip. Options: skip release creation, provide custom release notes. |
.github/workflows/docs.yml |
push to master touching docs/** (or manual) |
Deploys GitHub Pages from docs/ and syncs the wiki via scripts/sync-wiki.py. |
To publish a release: bump the version everywhere (see Versioning), commit and push, then run Actions → Publish release → Run workflow with the new version.
The docs\ folder is published in two places:
The site is served from docs/ via docsify (client-side rendering, no build step):
- Enable once in repo settings: Settings → Pages → Build and deployment → Source: GitHub Actions.
- The
docs.ymlworkflow deploysdocs/on every push tomasterthat touches docs (or manually). - URL:
https://purelogiccode.github.io/SimpleLauncher/.
docs/index.html (docsify loader), docs/_sidebar.md (TOC) and docs/.nojekyll are the site assets. docs/parameters.md and docs/manual-tests.md are copies kept for the site and wiki:
-
docs/parameters.md←SimpleLauncher/parameters.md— refresh it whenever the canonical file changes. -
docs/manual-tests.md←ManualTests.md(repo root) — refresh likewise.
The wiki is a separate git repo (SimpleLauncher.wiki.git); the default GITHUB_TOKEN cannot push to it, so the docs.yml workflow syncs it with a WIKI_PAT secret (classic PAT, repo scope). Without that secret the wiki job warns and skips.
python scripts/sync-wiki.py --dry-run # preview
python scripts/sync-wiki.py # clone/pull, rewrite, commit, pushThe script maps docs/README.md → Home, copies all docs/NN-*.md as pages, and protects the parameters page (https://github.com/purelogiccode/SimpleLauncher/wiki/parameters) — the app opens this URL (EditSystemWindow.xaml.cs, config key WikiParametersUrl), so it is never deleted and is refreshed from docs/parameters.md. Stale pages are deleted, _Sidebar.md is regenerated, and markdown links are rewritten to the flat wiki namespace.
- Implement features/fixes; keep
WhatsNew.mdupdated with a release section. - Bump version in the places listed under Versioning.
- Run the full test suite (minus the slow URL test).
- Run Actions → Publish release with the new version — it packages both RIDs (
release_{version}_{rid}.zip+updater_{rid}.zip) and creates the GitHub release. Locally,pwsh scripts/package-release.ps1 -Version <version>produces the same packages. - The in-app updater and silent update check use the GitHub
releases/latestAPI.
- Home
- 01 Overview
- 02 Projects And Solution
- 03 Quickstart
- 04 Architecture
- 05 Configuration
- 06 Systems And Launch
- 07 Core Services
- 08 Ui Layer
- 09 Retroachievements
- 10 Game Scanning
- 11 Bundled Tools
- 12 Data Formats
- 13 Logging And Debug
- 14 Testing
- 15 Development
- 16 Updater
- 17 Release Notes
- 18 Emulator Parameters
- Manual Tests
- Parameters