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:
- Call
curl -sf --max-time 3 against the GitHub releases API before launching the binary.
- Parse the
tag_name field from the JSON response.
- Compare with the bundled
VERSION file (written at bundle time from git describe / GitTag).
- 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.
- 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)
- Add
libcurl to vcpkg.json (platform !windows, or behind a SAGE_UPDATE_CHECK cmake flag).
- 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.
- Guard the whole feature behind
SAGE_USE_SDL3 (only meaningful for cross-platform builds).
- 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
- 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).
- 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.
- 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
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.
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 providesGitTag,GitSHA1,GitRevision, and more as runtime-available C++ globals (seegitinfo.h).Versionclass in both games exposesgetAsciiGitTagOrHash(), which returns the current build's git tag or short hash.bundle-macos-zh.shscript writesInfo.plistwithCFBundleVersion/CFBundleShortVersionString, but no standaloneversion.txtfile 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_OpenURLis available in SDL3 to open a browser to the releases page.MessageBox()inGeneralsMD/Code/CompatLib/is currently a no-op stub.vcpkg.json. The systemcurlbinary exists on macOS/Linux but is not invokable safely from production C++ code.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.shwrapper generated by deploy/bundle scripts is already the entry point on macOS and Linux. We can extend it to:curl -sf --max-time 3against the GitHub releases API before launching the binary.tag_namefield from the JSON response.VERSIONfile (written at bundle time fromgit describe/GitTag).osascript -e 'display dialog ...'orSDL_ShowSimpleMessageBoxvia a tiny helper binary.zenity --info,kdialog --msgbox, orxmessageas fallbacks.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)
libcurltovcpkg.json(platform!windows, or behind aSAGE_UPDATE_CHECKcmake flag).Core/Libraries/Source/Platform/UpdateChecker.cpp(or underCore/GameEngineDevice/):SDL_Threadat engine startup (before main loop, or at shell-map init).GitTag(available viagitinfo.h).GitTagis empty or a dirty hash (dev build).https://api.github.com/repos/fbraz3/GeneralsX/releases/latestwith a hard timeout of 5 s.tag_namefrom the JSON response via simplestrstr(no full JSON parser needed).SDL_ShowSimpleMessageBoxwith a "New version available" message, thenSDL_OpenURLwith the releases URL.SAGE_USE_SDL3(only meaningful for cross-platform builds).SAGE_UPDATE_CHECK_DISABLEcmake 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(fromgit describe --tags). Launcherrun.shchecks 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 aSDL_ShowSimpleMessageBoxwithout 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
v1.0.0-alpha.1).bundle-macos-zh.sh(and future Linux bundle script) must write aVERSIONfile derived fromgit describe --tags --exact-match HEADorGitTag.Options.ini: CheckForUpdates = yes/no) or env var (GENERALSX_NO_UPDATE_CHECK=1) to respect user privacy and offline/LAN setups.Acceptance Criteria
VERSIONfile with the current release tag.Out of Scope
Notes
https://api.github.com/repos/fbraz3/GeneralsX/releases/latestreturns HTTP 404 if no releases exist, which the checker must handle gracefully.