Mobile store release
Store binaries for AgentUp.Mobile ship from
Mobile CI,
not from ci.yml.
A path-filtered push smoke-builds and signs Android and iOS. It does not upload
to Play or App Store Connect and does not create android-v* / ios-v* GitHub
releases. Dispatch the same workflow on the branch that already has a product
vX.Y.Z tag to publish.
After validation, each platform job uploads the signed AAB or IPA plus checksum
to GitHub Actions artifacts (mobile-android, mobile-ios) with 1-day
retention, including on smoke, before any Play or App Store Connect submit.
The workflow runs Mobile typechecking, provider and script tests, and a web
export in a dedicated Ubuntu job before either native build. Dependency
installation runs the design-system generator with --check so stale committed
outputs fail instead of being rewritten. It does not call
semantic-release or use .releaserc.json. Android compiles on Ubuntu. iOS
compiles on macos-26 with Xcode 26.4 because CocoaPods and xcodebuild cannot
run on Linux, and Expo SDK 57 rejects Xcode 16.
Inputs
| Input | Values | Effect |
|---|---|---|
channel | beta or prod | Play internal vs production; TestFlight vs App Store Connect upload |
platforms | both, android, or ios | Which store jobs run |
These inputs apply only to workflow_dispatch. A path-filtered push always
builds both platforms and never publishes.
prod iOS uploads the IPA to App Store Connect with metadata and screenshots
skipped and does not submit for App Review. A human submits review from App
Store Connect until listing metadata exists.
Versioning
The version job is the gate for every later job.
- On
workflow_dispatch, marketing version is the newest git tag reachable fromHEADthat matchesvX.Y.Z. Tags namedandroid-v*andios-v*are ignored so this pipeline cannot version from its own GitHub releases. The job fails if this branch has no product tag; ship a normalci.ymlrelease first. - On
push, marketing version is0.0.0so the smoke does not need a product tag. - Play
versionCodeand iOSCFBundleVersionareGITHUB_RUN_NUMBER.
Each successful dispatched platform job creates or updates a GitHub release
whose tag is android-v<version> or ios-v<version>, with the AAB or IPA
attached. Re-running the same marketing version replaces those assets; the stores
still accept the binary because the build number changed.
ci.yml listens to every branch push and ignores android-v* and ios-v* tag
pushes. A tags-ignore filter without a branches filter would skip branch
pushes entirely, so desktop CI would never start on this branch.
Job graph
push (path-filtered) or workflow_dispatch
version (ubuntu)
tests (ubuntu)
android (ubuntu)
ios (macos-26)
Push runs when AgentUp.Mobile, AgentUp.Chat, AgentUp.AgentAuth,
AgentUp.ServerClient, AgentUp.DesignSystem, AgentUp.WebAudit, this
workflow, the iOS certs workflow, the mobile helper scripts, Fastlane,
Gemfile, Gemfile.lock, or .ruby-version change. Changing only ci.yml
does not start Mobile CI.
The Android and iOS jobs both require the shared Mobile test job to pass. Android failure does not cancel iOS, and the reverse. A second dispatch on the same ref waits; it does not cancel an in-flight store upload. A newer push on the same ref cancels an in-flight smoke, not a dispatch.
Signing
iOS uses Fastlane Match against the shared private
certificates repository
(master). Deploy lanes set readonly: true and
force_for_new_certificates: false so a release cannot mint a new Apple
certificate. New Agent-Up work creates profiles only for
net.themassiveone.agent-up.ios.
One-time bootstrap is Mobile iOS certificates:
init_ciwrites a writable deploy key from this repository onto the Match store.synccreates development and App Store profiles while reusing the existing Apple certificates.
Android signing uses a Play upload keystore stored in GitHub secrets. That keystore does not belong in the certificates git repo. Google Play App Signing holds the app signing key.
Expo identity
iOS is net.themassiveone.agent-up.ios. Android is
net.themassiveone.agentup.android.
AgentUp.Mobile/app.config.js overlays
those identifiers plus AGENTUP_MOBILE_VERSION and
AGENTUP_MOBILE_VERSION_CODE onto app.json. Play package_name must match the
Android package baked at prebuild; a different id is a hard Play API failure.
CI runs expo prebuild and does not commit android/ or ios/. Store
icon.png and adaptive-icon.png under AgentUp.Mobile/assets/ are 1024px
scales of AgentUp.Mobile/public/agent-up-icon-512.png.
GitHub-hosted store jobs invoke Expo and Fastlane directly. Fastlane, Gemfile,
Gemfile.lock, and .ruby-version live at the repository root; expo prebuild
still runs in AgentUp.Mobile. Do not add public Mobile npm scripts for those
commands; local scripts still enter shell.nix.
First-run console steps
These cannot be automated in the workflow:
- Copy Match, App Store Connect, Play, and Android keystore secrets onto the Agent-Up GitHub repository. Names are listed in CI Configuration.
- Run Mobile iOS certificates
init_ci, thensync, and confirmAppStore_net.themassiveone.agent-up.ios.mobileprovisionlanded in certificates without a new Apple certificate. - Create the App Store Connect app with bundle ID
net.themassiveone.agent-up.ios. - Create the Play Console app with package
net.themassiveone.agentup.android, enable Play App Signing, register the upload keystore, and grant the Play Developer API to the service account. - Dispatch Mobile CI with
channel: betaafter a productvX.Y.Ztag exists on the branch.