Skip to content

Add Fastlane setup for TestFlight distribution#16

Merged
heybeaux merged 5 commits into
mainfrom
feature/fastlane-testflight
Jul 4, 2026
Merged

Add Fastlane setup for TestFlight distribution#16
heybeaux merged 5 commits into
mainfrom
feature/fastlane-testflight

Conversation

@beaux-riel

@beaux-riel beaux-riel commented Jul 3, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds Gemfile + fastlane/ (Appfile, Fastfile, .env.example, README) for repeatable TestFlight builds of the committed ios/ project — no expo prebuild involved.
  • ios beta lane: ensures pods installed, bumps build number (latest TestFlight build + 1 when an ASC API key is configured), archives UltraEdge.xcworkspace (scheme UltraEdge, Release, automatic signing), uploads via pilot with skip_waiting_for_build_processing.
  • ios build lane: same archive without the upload, for local verification.
  • Auth via App Store Connect API key from env vars (ASC_KEY_ID, ASC_ISSUER_ID, ASC_KEY_P8/ASC_KEY_PATH, ASC_TEAM_ID) — documented in fastlane/.env.example; no secrets committed. .gitignore updated for fastlane/.env, build/, vendor/bundle/.
  • Second commit (3c338b7): the committed ios/Podfile.lock predated the current react-native version, so pod install failed outright (fast_float snapshot conflict, then missing Sentry/HybridSDK 8.56.1 spec). Ran pod update fast_float (with repo update) + pod install and committed the regenerated files: Podfile.lock, codegen/autolinking build phases in project.pbxproj, RCTNewArchEnabled in Info.plist (verified: only semantic change), privacy manifest sync. No hand-written app code touched.

Verification

  • bundle install ✅ (Ruby 3.4, gems in vendor/bundle)
  • bundle exec fastlane lanes lists ios build / ios beta
  • ruby -c on Fastfile/Appfile ✅
  • pod install succeeds after lockfile sync ✅
  • xcodebuild -list confirms scheme UltraEdge
  • No TestFlight upload or archive attempted — no ASC API key / signing credentials exist yet.

Before first run (Beaux)

  1. Create an ASC API key (App Store Connect → Users and Access → Integrations), role App Manager; download the .p8.
  2. cp fastlane/.env.example fastlane/.env and fill in the values (incl. ASC_TEAM_ID from developer.apple.com → Membership).
  3. Make sure the com.beaux.ultraedge app record exists in App Store Connect and you're signed into Xcode with your Apple ID.
  4. bundle install && bundle exec fastlane ios beta

Test plan

  • bundle exec fastlane ios build produces an .ipa locally
  • bundle exec fastlane ios beta uploads to TestFlight

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added streamlined iOS release workflows, including a build option and a beta upload path for TestFlight.
    • Enabled the app’s new architecture configuration for improved platform support.
  • Bug Fixes

    • Improved iOS build reliability by updating resource and privacy bundle handling.
    • Added a targeted workaround to help newer Xcode builds complete successfully.

Adds a beta lane (pods install, build number bump via latest TestFlight
build when an ASC API key is present, gym Release archive, pilot upload)
and a build lane for local verification. Builds the committed ios/
project directly with automatic signing; team ID and ASC API key are
read from env vars documented in fastlane/.env.example.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@beaux-riel, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 10 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d08228bb-b03e-461d-a3b7-85d8e1122a26

📥 Commits

Reviewing files that changed from the base of the PR and between 4bcf5ca and 824853d.

📒 Files selected for processing (8)
  • App.tsx
  • ios/UltraEdge.xcodeproj/project.pbxproj
  • ios/UltraEdge/AppDelegate.h
  • ios/UltraEdge/AppDelegate.mm
  • ios/UltraEdge/AppDelegate.swift
  • ios/UltraEdge/Info.plist
  • ios/UltraEdge/main.m
  • src/components/ErrorBoundary.tsx
📝 Walkthrough

Walkthrough

This PR adds Fastlane-based iOS build and TestFlight automation for UltraEdge, plus supporting Ruby, Xcode, Podfile, plist, and privacy manifest updates.

Changes

Fastlane and iOS build setup

Layer / File(s) Summary
Dependencies and ignore rules
Gemfile, .gitignore
Adds fastlane and cocoapods dependencies and ignores Fastlane environment/report files plus generated build and bundle paths.
Appfile and env template
fastlane/Appfile, fastlane/.env.example
Sets the app identifier and team settings, and adds a Fastlane env template for App Store Connect credentials and signing values.
Fastfile lanes and helpers
fastlane/Fastfile, fastlane/README.md
Defines the build and beta lanes with supporting helpers for pods setup, API key loading, signing, build numbering, archiving, and generated lane documentation.
iOS project adjustments
ios/Podfile, ios/UltraEdge.xcodeproj/project.pbxproj, ios/UltraEdge/Info.plist, ios/UltraEdge/PrivacyInfo.xcprivacy
Updates CocoaPods post-install handling, Xcode build phase inputs/outputs, enables RCTNewArchEnabled, and reorders privacy manifest entries.
Estimated code review effort: 4 (Complex) ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Developer
  participant Fastfile
  participant Xcode
  participant TestFlight

  Developer->>Fastfile: fastlane ios beta
  Fastfile->>Fastfile: asc_api_key (validate env vars)
  Fastfile->>Fastfile: ensure_pods
  Fastfile->>Xcode: configure_signing
  Fastfile->>TestFlight: bump_build_number (latest build + 1)
  Fastfile->>Xcode: archive (build_app)
  Fastfile->>TestFlight: upload_to_testflight
Loading

Related issues: None found in the provided context.

Related PRs: None found in the provided context.

Suggested labels: ios, fastlane, ci

Suggested reviewers: None found in the provided context.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding Fastlane support for TestFlight distribution.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/fastlane-testflight

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

beaux-riel and others added 2 commits July 3, 2026 13:17
The committed Podfile.lock predated the current react-native version,
so pod install failed on fast_float (and Sentry spec resolution).
Generated by `pod update fast_float` + pod install: updated lockfile,
codegen/autolinking build phases, RCTNewArchEnabled in Info.plist,
and privacy manifest sync. No hand-written app code touched.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- Sign with an explicit Apple Distribution cert + App Store profile via
  cert/sigh using the ASC API key (automatic signing fails at archive
  time: Xcode requests a development profile and the team has no
  registered devices).
- Patch fmt 11.0.2 in pod post_install to disable consteval format
  checks, which Xcode 26 clang rejects; fmt hardcodes FMT_USE_CONSTEVAL
  so a -D override is not possible.
- Keep fastlane-regenerated README in sync with lanes.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
ios/Podfile (1)

63-70: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Patch silently no-ops if the fmt source line changes.

src.sub returns the string unchanged when the target #if line isn't found, so a future fmt bump (or any wording change) would leave the header unpatched with no warning — reintroducing the Xcode 26 consteval build failure in a hard-to-diagnose way. Consider asserting the substitution actually applied and surfacing a warning otherwise:

🔧 Proposed hardening
       unless src.include?(marker)
-        src = src.sub(
+        patched = src.sub(
           '`#if` !defined(__cpp_lib_is_constant_evaluated)',
           "`#if` 1 #{marker}"
         )
-        FileUtils.chmod('u+w', fmt_base) # CocoaPods installs pod sources read-only
-        File.write(fmt_base, src)
+        if patched == src
+          Pod::UI.warn("fmt base.h consteval patch did not match — verify fmt version/base.h layout.")
+        else
+          FileUtils.chmod('u+w', fmt_base) # CocoaPods installs pod sources read-only
+          File.write(fmt_base, patched)
+        end
       end
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ios/Podfile` around lines 63 - 70, The Podfile patching logic can silently
fail when the expected fmt preprocessor line changes, leaving the header
unmodified and the build issue unresolved. Update the patch block around the
src.sub/File.write flow to verify the substitution actually happened before
writing, and if it did not, surface a clear warning or error tied to the Podfile
patch step so future fmt bumps are caught immediately.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@ios/Podfile`:
- Around line 63-70: The Podfile patching logic can silently fail when the
expected fmt preprocessor line changes, leaving the header unmodified and the
build issue unresolved. Update the patch block around the src.sub/File.write
flow to verify the substitution actually happened before writing, and if it did
not, surface a clear warning or error tied to the Podfile patch step so future
fmt bumps are caught immediately.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d7577df9-62a9-461b-abad-8f0b3d8d2579

📥 Commits

Reviewing files that changed from the base of the PR and between 677d5a4 and 4bcf5ca.

⛔ Files ignored due to path filters (1)
  • ios/Podfile.lock is excluded by !**/*.lock
📒 Files selected for processing (6)
  • fastlane/Fastfile
  • fastlane/README.md
  • ios/Podfile
  • ios/UltraEdge.xcodeproj/project.pbxproj
  • ios/UltraEdge/Info.plist
  • ios/UltraEdge/PrivacyInfo.xcprivacy
✅ Files skipped from review due to trivial changes (1)
  • ios/UltraEdge/PrivacyInfo.xcprivacy

beaux-riel and others added 2 commits July 3, 2026 19:23
The committed ios/ project still used the legacy Objective-C
AppDelegate (EXAppDelegateWrapper subclass). In Expo SDK 54 that
wrapper is deprecated and no longer creates the window or starts
React Native, so release builds launched to an empty black screen
while the main thread idled with no JS runtime.

Migrate AppDelegate to the SDK 54 Swift template (ExpoAppDelegate +
ExpoReactNativeFactory, which explicitly creates the window and
starts React Native), and add a root ErrorBoundary so future fatal
render errors surface a message instead of a black screen.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@heybeaux heybeaux merged commit dcf46b4 into main Jul 4, 2026
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants