Skip to content

Version check and update notification at startup #51

@fbraz3

Description

@fbraz3

Summary

Add a version check mechanism that detects when a newer GitHub release is available and notifies the user at startup (before or during the main menu).

Motivation

As we ship macOS and Linux builds as app bundles/packages, users need a way to know when a new release is available without manually watching the repository.

Current State (code analysis)

  • resources/gitinfo/ already provides GitTag, GitSHA1, GitRevision, and more as runtime-available C++ globals (see gitinfo.h).
  • The Version class in both games exposes getAsciiGitTagOrHash(), which returns the current build's git tag or short hash.
  • The bundle-macos-zh.sh script writes Info.plist with CFBundleVersion/CFBundleShortVersionString, but no standalone version.txt file is written to the bundle or runtime dir.
  • SDL_ShowSimpleMessageBox (from SDL3, already linked) works natively on all three platforms and can show a user-facing dialog without touching the game's internal window system.
  • SDL_OpenURL is available in SDL3 to open a browser to the releases page.
  • MessageBox() in GeneralsMD/Code/CompatLib/ is currently a no-op stub.
  • No HTTP client library is currently in vcpkg.json. The system curl binary exists on macOS/Linux but is not invokable safely from production C++ code.
  • The CI workflows (build-macos.yml, build-linux.yml) upload build artifacts but do not publish GitHub Releases. A tagging and release strategy is therefore a prerequisite.

Approaches

Option A — Launcher script (zero C++ changes, recommended for a first iteration)

The run.sh wrapper generated by deploy/bundle scripts is already the entry point on macOS and Linux. We can extend it to:

  1. Call curl -sf --max-time 3 against the GitHub releases API before launching the binary.
  2. Parse the tag_name field from the JSON response.
  3. Compare with the bundled VERSION file (written at bundle time from git describe / GitTag).
  4. If a newer tag is found, show a native dialog:
    • macOS: osascript -e 'display dialog ...' or SDL_ShowSimpleMessageBox via a tiny helper binary.
    • Linux: zenity --info, kdialog --msgbox, or xmessage as fallbacks.
  5. Offer to open the releases page via open (macOS) / xdg-open (Linux).

Pros: No C++ changes, no new dependencies, no determinism risk, easy to disable.
Cons: Requires system curl/zenity (usually present), dialog style is platform-specific, no in-game UI.

Option B — In-game C++ check (richer UX, slightly higher complexity)

  1. Add libcurl to vcpkg.json (platform !windows, or behind a SAGE_UPDATE_CHECK cmake flag).
  2. Implement Core/Libraries/Source/Platform/UpdateChecker.cpp (or under Core/GameEngineDevice/):
    • Spawns a detached SDL_Thread at engine startup (before main loop, or at shell-map init).
    • Reads current version from GitTag (available via gitinfo.h).
    • Skips check if GitTag is empty or a dirty hash (dev build).
    • GETs https://api.github.com/repos/fbraz3/GeneralsX/releases/latest with a hard timeout of 5 s.
    • Parses tag_name from the JSON response via simple strstr (no full JSON parser needed).
    • Compares tags using semver rules or lexicographic fallback.
    • If newer: calls SDL_ShowSimpleMessageBox with a "New version available" message, then SDL_OpenURL with the releases URL.
  3. Guard the whole feature behind SAGE_USE_SDL3 (only meaningful for cross-platform builds).
  4. Provide SAGE_UPDATE_CHECK_DISABLE cmake option and an ini/options file toggle for users who want to opt out.

Pros: Integrated UX, works in-game at startup, single codebase.
Cons: Adds libcurl (~500 KB static), requires careful offline/error handling, versioning format must be consistent.

Option C — Hybrid (recommended long-term)

Bundle script writes version.txt (from git describe --tags). Launcher run.sh checks GitHub at startup and, if a newer version is found, writes a flag file (e.g., update_available.flag) to the user data dir. The C++ startup code reads this flag and shows a SDL_ShowSimpleMessageBox without ever making a network call itself.

This keeps network I/O out of C++, avoids libcurl, and still shows an in-game-style dialog.

Prerequisites

  1. GitHub Releases strategy: The CI pipeline must publish versioned GitHub Releases (not just artifacts). A consistent tag format must be agreed on (e.g., v1.0.0-alpha.1).
  2. Version file in bundle: bundle-macos-zh.sh (and future Linux bundle script) must write a VERSION file derived from git describe --tags --exact-match HEAD or GitTag.
  3. Opt-out mechanism: An ini option (e.g., Options.ini: CheckForUpdates = yes/no) or env var (GENERALSX_NO_UPDATE_CHECK=1) to respect user privacy and offline/LAN setups.

Acceptance Criteria

  • GitHub Release + tagging strategy documented and CI publishes releases with consistent tag names.
  • Bundle/deploy scripts write a VERSION file with the current release tag.
  • At startup, if a newer GitHub release exists, a non-blocking notification is shown to the user (dialog style TBD based on chosen approach).
  • Notification includes the releases page URL and a "dismiss" option.
  • Check is skipped for dev/dirty builds (no stable tag).
  • Check is skipped if user has opted out (ini setting or env var).
  • Fails silently when offline (no crash, no error dialog).
  • Zero effect on game logic or replay determinism.
  • Legacy VC6/win32 builds are unaffected.

Out of Scope

  • Auto-download or auto-install of updates.
  • Patch/delta download mechanism.
  • Windows modern stack (can be added later once the release pipeline is established for Linux/macOS).

Notes

  • GitHub API rate limit for unauthenticated requests is 60/hour per IP — well within acceptable range for a one-per-launch check.
  • The releases endpoint https://api.github.com/repos/fbraz3/GeneralsX/releases/latest returns HTTP 404 if no releases exist, which the checker must handle gracefully.
  • Consider a cool-down: write the last-checked timestamp to user data dir and re-check at most once per day.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions