5.4 KiB
Launcher Self-Update
MoonWell Launcher uses auto_updater 1.0.0, backed by WinSparkle 0.8.1, to
update installed Windows launchers from an AppCast feed. This is independent of
the manifest-based World of Warcraft client synchronization.
The launcher performs one background update check after its window is visible. WinSparkle shows its native prompt only when a newer version is available. Missing configuration, network failures, and malformed feeds do not block the launcher. Periodic WinSparkle checks are disabled.
Build Configuration
Pass the public feed URL at build time:
flutter build windows `
--dart-define=MOONWELL_API_BASE_URL=https://host `
--dart-define=MOONWELL_APPCAST_URL=https://host/launcher/updates/appcast.xml
The feed URL must be an absolute HTTPS URL. Omit
MOONWELL_APPCAST_URL to disable self-update, including for ordinary local
development.
Signing Keys
WinSparkle verifies installer artifacts with a DSA signature. The public key is
committed at windows/runner/resources/dsa_pub.pem and embedded as the
DSAPub resource. The corresponding private key is local signing material at
.moonwell_signing/dsa_priv.pem; it is ignored by Git and must be backed up to
the project secret store before publishing the first update.
Never commit or upload the private key. Losing it prevents existing installations from accepting future updates. Rotating it requires shipping an ordinary installer containing the replacement public key before publishing artifacts signed by the replacement private key.
The AppCast signature is not Authenticode. Publicly trusted Authenticode certificates and managed signing services are paid products, so MoonWell does not currently Authenticode-sign the installer. Windows can therefore display an unknown-publisher or SmartScreen warning. A free self-signed Authenticode certificate would not establish trust on player machines.
Version and AppCast Contract
Increase the X.Y.Z version in pubspec.yaml for every launcher release. A
build-number-only change such as 1.0.0+2 is not sufficient because WinSparkle
compares the Windows product version. Pass the same X.Y.Z value to Inno Setup:
ISCC.exe /DMyAppVersion=1.1.0 installer\moonwell_launcher.iss
The resulting artifact is
build/installer/moonwell_launcher_1.1.0_windows_setup.exe.
Use a public AppCast with absolute URLs:
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle">
<channel>
<title>MoonWell Launcher</title>
<description>MoonWell Launcher updates</description>
<language>ru</language>
<item>
<title>MoonWell Launcher 1.1.0</title>
<sparkle:releaseNotesLink>https://host/launcher/updates/1.1.0/release-notes.html</sparkle:releaseNotesLink>
<pubDate>Sun, 21 Jun 2026 12:00:00 +0400</pubDate>
<enclosure
url="https://host/launcher/updates/1.1.0/moonwell_launcher_1.1.0_windows_setup.exe"
sparkle:version="1.1.0"
sparkle:os="windows"
sparkle:dsaSignature="SIGNATURE_FROM_SIGN_UPDATE"
length="ACTUAL_INSTALLER_SIZE_IN_BYTES"
type="application/octet-stream" />
</item>
</channel>
</rss>
The installer URL and release-notes URL must be absolute. The publication host must serve the feed, notes, and installer without authentication or redirects to an authenticated endpoint.
Manual Release
Perform Windows signing on the Windows release machine because the package invokes WinSparkle's Windows signing utility.
-
Update
pubspec.yamlto the newX.Y.Z+Nversion. -
Run
flutter pub get, formatting, analysis, and all tests. -
Build Windows with both production
--dart-definevalues. -
Compile the installer with
ISCC.exe /DMyAppVersion=X.Y.Z. -
Make the private key available outside the repository and sign the artifact:
dart run auto_updater:sign_update ` build\installer\moonwell_launcher_X.Y.Z_windows_setup.exe ` C:\secure-path\dsa_priv.pem -
Copy the emitted
sparkle:dsaSignatureinto the enclosure. The package's Windows helper reportslength="0"; replace it with the actual value from:(Get-Item build\installer\moonwell_launcher_X.Y.Z_windows_setup.exe).Length -
Upload the versioned installer and release notes first.
-
Download the hosted installer, verify its byte length, and test its DSA signature before changing the feed.
-
Publish
appcast.xmllast so clients never observe an incomplete release.
Keep the preceding installer available for rollback and support. Rollback is a new release with a product version higher than the faulty release; WinSparkle does not install a lower version as an update.
Release Verification
Test from an installed older version on a clean Windows x64 machine:
- offline or invalid feed: launcher remains usable and writes a log entry
- same or older feed version: no update prompt
- valid newer release: prompt, download, launcher exit, install, and relaunch
- modified installer or invalid DSA signature: WinSparkle rejects the update
- launcher session and selected game directory remain after installation
Watch the debug output for Flutter platform-channel thread warnings during the
test. auto_updater has an open Windows callback-thread issue; do not release
if it reproduces. Patch and pin auto_updater_windows so native callbacks are
marshalled onto Flutter's platform thread, then repeat the complete update test.