Files
moonwell-launcher/docs/launcher_self_update.md
T

5.5 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:

fvm 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.

  1. Update pubspec.yaml to the new X.Y.Z+N version.

  2. Run fvm flutter pub get, formatting, analysis, and all tests.

  3. Build Windows with both production --dart-define values.

  4. Compile the installer with ISCC.exe /DMyAppVersion=X.Y.Z.

  5. Make the private key available outside the repository and sign the artifact:

    fvm dart run auto_updater:sign_update `
      build\installer\moonwell_launcher_X.Y.Z_windows_setup.exe `
      C:\secure-path\dsa_priv.pem
    
  6. Copy the emitted sparkle:dsaSignature into the enclosure. The package's Windows helper reports length="0"; replace it with the actual value from:

    (Get-Item build\installer\moonwell_launcher_X.Y.Z_windows_setup.exe).Length
    
  7. Upload the versioned installer and release notes first.

  8. Download the hosted installer, verify its byte length, and test its DSA signature before changing the feed.

  9. Publish appcast.xml last 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.