135 lines
5.5 KiB
Markdown
135 lines
5.5 KiB
Markdown
# 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:
|
|
|
|
```powershell
|
|
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:
|
|
|
|
```powershell
|
|
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
|
|
<?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:
|
|
|
|
```powershell
|
|
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:
|
|
|
|
```powershell
|
|
(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.
|