Reusable React Native Builds and Uploads with GitHub Actions and Fastlane
A request for an installable app soon raises further questions: which environment does it use, how does another app join the pipeline, can an upload failure reuse the existing build, and can another engineer repeat the process?
I helped implement and maintain a shared GitHub Actions and Fastlane pipeline covering builds, artifact transfer, and uploads. Here, submission means uploading to TestFlight or a configured Google Play track. Formal review submission, review monitoring, and rollout control are a separate release orchestration design, not a completed end-to-end implementation.
Separate three configuration dimensions
| Dimension | Question | Examples |
|---|---|---|
| Application environment | Which business services does the app use? | Test, production |
| Build and export type | Which native artifact is produced? | iOS device or simulator app; Android APK or AAB |
| Upload destination | Where does the artifact go? | Internal distribution, TestFlight, Google Play, build only |
A production-connected iOS build can be distributed through TestFlight before public release. A simulator app is not a device artifact for store upload.
The shared entry point validates the platform and profile combination before choosing the execution lane. Callers provide an explicit delivery target while platform implementations remain independently maintainable.
Keep application policy separate from shared execution

Technical flow; implementation and validation boundaries are explained below.
My work included organizing application onboarding around stable metadata, signing configuration, and limited application hooks. Shared execution handles preparation, native builds, and artifact transfer; hooks own application-specific version and runtime rules.
Frequently changing build numbers do not belong in stable application metadata. Resolved iOS build numbers, Android version codes, and runtime identifiers travel through build metadata to the upload stage.
The upload identity must describe the artifact actually being uploaded. Recomputing a next build number during recovery can make the reported version differ from the binary.
Make the build-to-upload handoff explicit
Express the handoff through a fixed artifact identity
This iOS fragment omits dependency setup, signing, compilation and the upload lane. It keeps the existing build/post split and additionally illustrates artifact-ID binding and checksums; those additions are examples, not a claim about deployed behavior. Android can apply the same contract in its own build job.
# Handoff fragment for an iOS build. Project setup/build steps are omitted.
jobs:
build:
runs-on: macos-latest
outputs:
artifact_id: ${{ steps.archive.outputs.artifact-id }}
steps:
# Existing build steps must produce both files below.
- name: Verify and fingerprint delivery
run: |
test -s delivery/app.ipa
test -s delivery/build-info.json
cd delivery
shasum -a 256 app.ipa build-info.json > SHA256SUMS
- uses: actions/upload-artifact@v7
id: archive
with:
name: ios-${{ github.run_id }}-${{ github.run_attempt }}
path: delivery/
if-no-files-found: error
retention-days: 14
post:
needs: build
runs-on: macos-latest
steps:
- uses: actions/download-artifact@v8
with:
artifact-ids: ${{ needs.build.outputs.artifact_id }}
path: delivery/
- name: Verify before upload
run: |
cd delivery
shasum -a 256 -c SHA256SUMS
# Restore pinned tooling/configuration, then run the existing upload lane.
# Read version/build identity from build-info.json; do not allocate it again.
The build producing the binary must also produce build-info.json, recording the actual source SHA, Bundle ID, build number, runtime and configuration revision. The artifact ID fixes the handoff object for this run. Checksums check file consistency, not signing identity, review status or trusted provenance. Cross-run recovery also requires the run ID, artifact ID, authorization context and a check for prior store receipt.
The example's 14-day retention illustrates a configurable recovery window; the inspected implementation uses one day. Longer review cycles still need separate archival. Inputs and outputs are defined by upload-artifact and download-artifact.
The existing pipeline separates build and post jobs. The first preserves native output and diagnostic material; the second restores its environment, downloads artifacts from that run, and executes upload and distribution steps.
This supports recovering the upload stage, provided artifacts remain available, metadata matches, and the destination has not already accepted the build. Two jobs alone do not establish unconditional retry safety.
A useful handoff records the application, source commit, configuration revision, platform, build identifiers, artifact location, destination track, and failure stage. It does not include secret values.
After an upload timeout, I would inspect the destination before retrying. A compiler failure requires correcting the source or toolchain and rebuilding. Those failures need different recovery actions.
Preserve platform-specific behavior
On iOS, the Team, Bundle ID, signing material, and entitlements must agree. The implemented upload lane loads build metadata, checks the IPA, and uploads to TestFlight.
An accepted upload, completed build processing, tester availability, and App Review approval are distinct. A lane configured not to wait for processing can finish before testers can install. Formal review requires selecting a build and completing the submission information. Apple submission documentation.
On Android, the lane resolves the package and track and checks for an AAB or APK. It distinguishes a draft-app path from ordinary uploads. A completed internal-track release is not a public production launch. First-time application setup also extends beyond what an upload tool does. Fastlane Google Play upload documentation.
Deliver diagnostic material with the binary
The pipeline includes artifact paths and upload logic for debugging material. Whether sourcemaps, symbols, or obfuscation mappings are enabled and successfully delivered must be checked for each application and run.
These files must match the build they describe. A green workflow does not prove every optional upload executed, and a mapping from another build cannot establish reliable source attribution.
The inspected build artifacts have a one-day retention period. That supports short-term transfer but does not cover a multi-day review lifecycle. Durable release storage belongs to the next phase of the design.
Scope a remote delivery engagement
I start by identifying the repository, platform, environment, signing setup, destination, and failing stage. The deliverables are a repeatable entry point, configuration instructions, the identified artifact and actual upload status, any device verification performed, and stage-specific recovery notes.
This article was checked against the application caller, shared workflows, actions, and upload lanes. No new hosted build or store upload was triggered for the article. Source inspection does not prove every application or branch has passed, and no unmeasured speed or labor savings are claimed.
ivan provides part-time remote support for React Native / iOS / Android builds, signing, and upload workflows through written, asynchronous collaboration.
