Installing¶
Every tagged release publishes prebuilt packages for Windows, macOS, and Linux (see Building & packaging) plus Android and, for pre-approved devices only, iOS. Each Release page also gets an Install section with working links, generated automatically — this page explains what those links do and the steps around them.
Android¶
- Open the release's Install section (or its Assets list) and
download
CountdownSolver-<version>-android-arm64-v8a.apk. - Android blocks installs from outside Google Play by default. When you open the downloaded file you'll be prompted to allow it — either via a one-time "Install unknown apps" prompt, or in advance under Settings → Apps → Special app access → Install unknown apps, choose the app you downloaded with (browser or Files), and enable it.
- Open the
.apkagain and confirm the install prompt.
The signed APK comes from release.yml's android-release job — see
CI & dependencies for how it's
built and signed.
iOS (ad-hoc, pre-registered devices only)¶
A standard Apple Developer account can only produce an ad-hoc signed
build — installable solely on iPhones/iPads whose UDID is already listed
in the provisioning profile used to sign that release
(IOS_PROVISIONING_PROFILE_BASE64, see
CI & dependencies). There's no
link that installs the app on an arbitrary device: if yours isn't
registered yet, its UDID has to be added in the Apple Developer portal, a
new ad-hoc provisioning profile regenerated to include it, and that
profile's base64 re-uploaded to the IOS_PROVISIONING_PROFILE_BASE64
secret — before the next tagged release will install on it. TestFlight
or the App Store are separate, wider-distribution options not set up for
this project yet.
Once your device is registered:
- On the device itself, open the GitHub Release page in Safari
(
itms-services://links are a Safari-only install trigger — they won't work from Chrome or any other browser, or from a share sheet) and tap the Install on iOS link in the release's Install section. This lands on a small install page — tap its Install on iOS button there to actually trigger the install. - iOS shows an install confirmation naming the app; confirm it. The icon appears on the home screen once the download finishes.
- First launch is blocked by "Untrusted Developer" — this is standard for any ad-hoc/enterprise-signed app, not specific to this one. Go to Settings → General → VPN & Device Management, select the developer profile under Developer App, and tap Trust. The app opens normally from then on.
How the install link works¶
The install ultimately runs through an itms-services:// URL:
itms-services://?action=download-manifest&url=<manifest.plist URL>
but the release notes' Install on iOS link doesn't point there
directly — GitHub's release-notes markdown renderer sanitizes link
hrefs to a fixed scheme allowlist (http/https/mailto/etc.) and
silently drops any <a> tag using an unrecognized scheme like
itms-services://, leaving unclickable plain text. Instead, the release
notes link to install-ios.html?tag=<release tag> — a small page hosted
alongside these docs on GitHub Pages (not subject to that sanitizer) —
which builds the real itms-services:// link client-side from the tag in
its query string and shows it as a normal tappable button.
manifest.plist itself is a small property list — generated by
release.yml's ios-release job alongside the IPA — declaring the app's
bundle identifier, version, and the IPA's own release-asset URL. Safari
reads that manifest and downloads/installs the IPA it points to; there's
no way to trigger an OTA install from a bare .ipa link the way Android
accepts a bare .apk link.
Verifying a download¶
Every release publishes SHA256SUMS/SHA512SUMS covering every asset
(including manifest.plist), each Sigstore-attested at build time and the
combined manifests cosign-signed at publish time:
sha256sum -c SHA256SUMS
gh attestation verify CountdownSolver-android-arm64-v8a.apk -R iainchesworth/CountdownSolver
See Building & packaging → Packaging for details.