Files
moonwell-launcher/docs/launcher_self_update.md
T
2026-07-28 20:56:19 +04:00

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

MoonWell.exe uses the Windows requireAdministrator execution level. Users therefore receive a UAC prompt whenever the launcher starts. This is required to synchronize game files installed in protected directories. The per-user Inno Setup installer remains configured with PrivilegesRequired=lowest.

Build Configuration

Pass the public feed URL at build time:

flutter build windows `
  --dart-define=MOONWELL_API_BASE_URL=https://moon-well.online `
  --dart-define=MOONWELL_APPCAST_URL=https://moon-well.online/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 for a public release. Flutter writes the complete X.Y.Z+N value into the Windows ProductVersion; sparkle:version must match that complete value exactly. Use sparkle:shortVersionString for the human-readable X.Y.Z value. Pass X.Y.Z without the build suffix 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>
      <pubDate>Sun, 21 Jun 2026 12:00:00 +0400</pubDate>
      <enclosure
          url="https://storage.yandexcloud.net/warcraft-client/moonwell_launcher_setup.exe"
          sparkle:version="1.1.0+3"
          sparkle:shortVersionString="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.

The recommended production workflow is the automated tool/deploy_launcher.ps1 script. See production_deploy.md for prerequisites, environment variables, dry-run usage, deployment, and failure recovery. The steps below are the manual fallback and describe the same release order.

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

  2. Run 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:

    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 installer to the root of the warcraft-client bucket as moonwell_launcher_setup.exe. The object must be publicly readable.

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

  9. Set LAUNCHER_AUTH_KEY in the release environment and publish appcast.xml last:

    curl.exe `
      -X POST "https://moon-well.online/api/service/update-appcast" `
      -H "Auth: $env:LAUNCHER_AUTH_KEY" `
      -H "Content-Type: application/xml" `
      --data-binary "@appcast.xml"
    
  10. Fetch https://moon-well.online/appcast.xml and verify the published version, installer URL, byte length, and DSA signature.

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.