AUpdater does not impose where the update comes from. What it needs is a ZIP archive with a complete copy of your
application, found by checkForUpdatesImpl and downloaded by downloadUpdateImpl. This page shows the setup that
App Template ⚡ uses: GitHub releases.
The archive name contains the platform and the architecture, followed by -portable, i.e.
myapp-1.2.3-linux-x86_64-portable.zip. Upload the archive for every platform and architecture you support to the same
release. tar.gz archives are not supported by the updater.
If you distribute a Windows installer as well, it has to install into the user's directory so the updater can replace
files without elevation; see Inno Setup.
aui::updater::AppropriatePortablePackagePredicate tells whether a file name is a portable for the current platform
and architecture. It is meant to be used with ranges::find_if. If you name archives differently, pass your own
qualifier:
aui::updater::github::latestRelease (see aui::updater::github::LatestReleaseResponse) returns the latest non-draft, non-prerelease release of a repository together
with its assets. The example below compares the tag with the current version, finds the matching asset, asks the user
and starts the download.
staticconstexprautoLOG_TAG="MyUpdater";classMyUpdater:publicAUpdater{public:~MyUpdater()override=default;protected:AFuture<void>checkForUpdatesImpl()override{returnAUI_THREADPOOL{try{autogithubLatestRelease=aui::updater::github::latestRelease("aui-framework","example_app");ALogger::info(LOG_TAG)<<"Found latest release: "<<githubLatestRelease.tag_name;autoourVersion=aui::updater::Semver::fromString(AUI_PP_STRINGIZE(AUI_CMAKE_PROJECT_VERSION));autotheirVersion=aui::updater::Semver::fromString(githubLatestRelease.tag_name);if(theirVersion<=ourVersion){getThread()->enqueue([]{AMessageBox::show(nullptr,"No updates found","You are running the latest version.",AMessageBox::Icon::INFO);});return;}aui::updater::AppropriatePortablePackagePredicatepredicate{};autoit=ranges::find_if(githubLatestRelease.assets,predicate,&aui::updater::github::LatestReleaseResponse::Asset::name);if(it==ranges::end(githubLatestRelease.assets)){ALogger::warn(LOG_TAG)<<"Newer version was found but a package appropriate for your platform is not available. ""Expected: "<<predicate.getQualifierDebug()<<", got: "<<(githubLatestRelease.assets|ranges::view::transform(&aui::updater::github::LatestReleaseResponse::Asset::name));return;}ALogger::info(LOG_TAG)<<"To download: "<<(mDownloadUrl=it->browser_download_url);getThread()->enqueue([this,self=shared_from_this(),version=githubLatestRelease.tag_name]{if(AMessageBox::show(nullptr,"New version found!","Found version: {}\n\nWould you like to update?"_format(version),AMessageBox::Icon::INFO,AMessageBox::Button::YES_NO)!=AMessageBox::ResultButton::YES){return;}downloadUpdate();});}catch(constAException&e){ALogger::err(LOG_TAG)<<"Can't check for updates: "<<e;getThread()->enqueue([]{AMessageBox::show(nullptr,"Oops!","There is an error occurred while checking for updates. Please try again later.",AMessageBox::Icon::CRITICAL);});}};}AFuture<void>downloadUpdateImpl(constAPath&unpackedUpdateDir)override{returnAUI_THREADPOOL{try{AUI_ASSERTX(!mDownloadUrl.empty(),"make a successful call to checkForUpdates first");downloadAndUnpack(mDownloadUrl,unpackedUpdateDir);reportReadyToApplyAndRestart(makeDefaultInstallationCmdline());}catch(constAException&e){ALogger::err(LOG_TAG)<<"Can't check for updates: "<<e;getThread()->enqueue([]{AMessageBox::show(nullptr,"Oops!","There is an error occurred while downloading update. Please try again later.",AMessageBox::Icon::CRITICAL);});}};}private:AStringmDownloadUrl;};
downloadAndUnpack downloads the archive, reports progress to AUpdater::status and unpacks into
unpackedUpdateDir. reportReadyToApplyAndRestart then switches the status to
AUpdater::StatusWaitingForApplyAndRestart and remembers the command line to launch, so even if the user quits the app
now, the update is applied on the next start.
Warning
Anonymous GitHub API requests are rate-limited per IP address. Do not check for updates more often than once per
several hours, and never in a loop.
Nothing in AUpdater is tied to GitHub. Fetch a JSON manifest from your server in checkForUpdatesImpl, remember the
download URL in a member, and pass it to downloadAndUnpack in downloadUpdateImpl. Only a ZIP archive is understood
by downloadAndUnpack; for other formats, unpack into unpackedUpdateDir yourself.