ci(ios): run the iOS build and tests on every pull request - #754
Conversation
GitHub reads workflows only from the repository root, so everything under hosts/ios/.github/workflows/ is inert. These seven are the ones that never trigger themselves: two are workflow_call, five are workflow_dispatch. Moving them changes no scheduled or pull request behaviour, so the mechanical work lands before the secrets and runners that the pull request checks need. Paths now resolve from the repository root. Composite action references become ./hosts/ios/.github/actions/..., which is also how the workflow_call references between these files start resolving at all, since a local uses: path is always read from the root regardless of where the calling file sits. Steps that drive the app rather than the repository run from hosts/ios: the fastlane invocations, the xcconfig edit, and the TestFlight build number lookup. Steps that take a path argument keep a root-relative one instead, so read-build-version reads a prefixed pbxproj default and a prefixed script path. The shared composite actions pick up the same treatment: bundler resolves hosts/ios/Gemfile, the SPM cache points at hosts/ios/source_packages, the generated secrets and GoogleService-Info.plist land under hosts/ios, and the built ipa is uploaded from there. None of this is exercised yet. No current job resolves these workflows, and the build itself needs the credentials tracked in #672, so this is verified by actionlint and by every local reference resolving, not by a run.
The last eight, which is every iOS workflow that triggers itself. Four run on pull_request and four on a schedule, so unlike the first batch they cannot be moved and left alone: at the repository root they would run, and the build credentials tracked in #672 are not all in place. Each live trigger is therefore commented out rather than deleted, with the note that restoring it is what puts the workflow live. The original filters are preserved exactly, including the pull_request types and branch lists and the cron expressions, so going live is a readable diff rather than a rewrite. pr.yml and release_branch_lifecycle.yml carried only pull_request, so they gain a workflow_dispatch trigger to stay valid. Paths get the same treatment as the first batch. Steps that drive the app run from hosts/ios, artifact and upload paths are prefixed, and the simulator release writes a root-relative archive path because the release step resolves it from the workspace. These files are linted for the first time by moving to the root, so the pre-existing findings are fixed here: six unquoted GITHUB_ENV and GITHUB_OUTPUT redirects, and a glob that could be read as options. Two things deliberately left for the follow-up that restores the triggers. The branch filters name develop and main from the source repository's branching model, which does not apply here. And no run has exercised any of this.
Every credential pr.yml reads is now set on this repository, so the trigger it was held back from can be restored. Nothing else changes: the distribution and schedule workflows stay on workflow_dispatch, since they need credentials that are not here yet and branch filters that name a branching model this repository does not use. pr.yml never carried a branch filter, so restoring it is the trigger alone. workflow_dispatch stays so a build can be reproduced without pushing a commit. This also exercises the path rewrites for the first time. A workflow gaining a pull_request trigger runs on the pull request that adds it, so the build and test jobs here are the first real test of the move to the repository root.
The first run failed both jobs at package resolution: invalid custom path 'ios/truapi-provider/Sources/truapi_providerFFI/include' for target 'truapi_providerFFI' Not a path rewrite. Every re-homed step succeeded. The app resolves the core from this tree rather than a published version, and the core's bindings, xcframework and FFI headers are gitignored build outputs, so the package graph cannot resolve until they are generated. In the source repository the core arrived prebuilt, so nothing had to generate it. A composite action does that once and both jobs call it: the Rust codegen output, the host bindings and xcframework, and the provider bindings. It mirrors what release-ios.yml already does, which is the known-good sequence. Simulator slice only, since a pull request never builds for a device, which halves the xcframework build.
|
CI Status: 17 required jobs green, 13 passed and 4 skipped by path filter. All job results
Commit |
The bootstrap built the simulator slice only, on the assumption a pull request never builds for a device. The build job does: While building for iOS, no library for this platform was found in ios/truapi-host/Binaries/truapi_server.xcframework build_app_ci archives through gym, which always targets a device, so it needs the device slice. Only the test job is simulator-only, and both jobs share this action, so both slices it is.
TrUAPIHost's HostRuntimeConfig requires networkSuffix, added with the reserved person and identity key derivation. The app never passed it, so it does not compile against the core in this tree. The value has to name the same network the chains do, since the reserved identities are derived under it and a wrong value derives a different person from the same seed rather than failing. So it lives beside the chain selection, under the same compile-time conditions, where the two cannot drift apart. UNSTABLE selects the previewnet chains, which the host CLI pairs with the testnet suffix. NIGHTLY selects the nightly Paseo chains, which it pairs with paseo. Release is unconfirmed and marked as such: its chains carry the same assets as the nightly ones, pas in the native slot and pusd beside it, which points at Paseo rather than Polkadot. No CI configuration builds that branch.
|
The failing This pull request turns on the The fix is #756, stacked on this branch. It is not in this branch, so this one Merge order is #741, then this, then #756. Everything the re-homing itself owns |
The note pointed at the pull request that added it, which says nothing once the change is merged. It names the issue that carries the open question instead.
# Conflicts: # .github/workflows/ios-pr.yml
A reviewer can run the change rather than read it. The simulator slice is ad-hoc signed, so it needs no provisioning profile and no signing identity, and therefore nothing the build job does not already have. The commit goes into the bundle's Info.plist, not only the artifact name, so a build that has been downloaded and unzipped still says where it came from. The stamp is read back and the job fails if it did not take, because a build that cannot name its commit should not be published. Simulator slice only, unlike the build job, which archives for a device and needs both. DevCI configuration, so the preview exercises the same chains and settings the checks do.
Turns on the iOS build and tests for every pull request, and makes them pass.
Folded together rather than stacked, so this is one CI run and one merge instead
of three, and
mainnever carries a red iOS check.Four files
.github/workflows/ios-pr.ymlgoes back to triggering onpull_request,and gains a preview job.
workflow_dispatchstays so a build can be reproducedwithout pushing a commit. Every other iOS workflow stays on dispatch: they need
credentials that are not here yet and branch filters naming a branching model
this repository does not use.
.github/actions/bootstrap-ios-coregenerates what the app needs before itspackage graph can resolve: the Rust codegen output, the host bindings and
xcframework, and the provider bindings. The app resolves the core from this tree
rather than a published version, and those outputs are gitignored, so without
this the build fails at package resolution. It mirrors the sequence
release-ios.ymlalready uses.KnownChains.swiftandTrUAPIHostRuntimeProvider.swiftpass thenetwork suffix the host's chains belong to.
HostRuntimeConfigrequires it andthe app never passed it, so the app did not compile against the core at HEAD.
Background on #755.
What runs per pull request
buildmacos-26testmacos-26-xlargepreviewmacos-26-xlarge.app, stamped with its commitThe preview needs no provisioning profile or signing identity, since the lane
signs ad-hoc, so it adds no credential requirement. The commit goes into the
bundle's
Info.plist, not only the artifact name, and the job fails if thestamp did not take.
Verified
buildandtestboth passed on this code before it was folded together. Thatrun was the first time the app has been compiled and tested against a core built
from this tree.
Three things were wrong before it went green, recorded because they are the
interesting part: the core bindings were never generated, the xcframework was
built simulator-only while
gymarchives for a device, and the app did not passnetworkSuffix. The last had been onmainsince #627 on 2026-09-07, invisiblebecause iOS built against a pinned published core in another repository.
One value still needs confirming
KnownNetworkSuffix.currentreturnspaseofor the Release configuration andthat is unverified, tracked by #760. No CI configuration builds that branch:
build_app_ciusesDevCI, which setsUNSTABLEand resolves totestnet,the value these runs exercised.
Closes #680. Closes #755.