Phase 2 of multi-environment setup. Adds Firebase core, Crashlytics, Analytics, Remote Config, Performance, Messaging and flutter_local_notifications, plus full APNs configuration for iOS push. - Wire setupFirebase(env) and setupNotifications() in initApp - Add firebase_options for dev and staging via flutterfire (sf-platform-pre) - Register google-services / firebase-perf / crashlytics gradle plugins - Add per-flavor GoogleService-Info.plist with Build Phase script that copies the right plist into the .app bundle based on \$CONFIGURATION - Bump iOS deployment target 13.0 -> 15.0 (required by firebase_analytics) - Pin flutter_local_notifications to ^19.4.2 (v20+ needs Dart SDK >=3.10) - Add aps-environment to staging (development) and production entitlements; development flavor intentionally excluded (no App Store Connect entry) - Fix AppDelegate.swift to call super.application after forwarding to AntelopAppDelegate, otherwise Firebase Messaging swizzling breaks and the APNs token is never captured - Crashlytics reports in all builds (debug + release) for early detection - Tag analytics events with env user property per flavor - App Check intentionally not included (debug-token friction with large QA team); can be re-added release-only later
86 lines
2.8 KiB
Ruby
86 lines
2.8 KiB
Ruby
#!/usr/bin/env ruby
|
|
#
|
|
# Adds a "Copy GoogleService-Info" Run Script Build Phase to the Runner target.
|
|
# The script copies ios/flavors/{flavor}/GoogleService-Info.plist to the .app
|
|
# bundle based on the build CONFIGURATION (Debug-development, Release-staging, etc.).
|
|
#
|
|
# Idempotent: if the build phase already exists, does nothing.
|
|
#
|
|
# Usage:
|
|
# ruby ios/scripts/add-copy-google-service-build-phase.rb
|
|
|
|
require 'xcodeproj'
|
|
|
|
PROJECT_PATH = File.expand_path('../../Runner.xcodeproj', __FILE__)
|
|
TARGET_NAME = 'Runner'
|
|
PHASE_NAME = 'Copy GoogleService-Info'
|
|
SHELL_SCRIPT = '"${SRCROOT}/scripts/copy-google-service-plist.sh"'
|
|
|
|
project = Xcodeproj::Project.open(PROJECT_PATH)
|
|
target = project.targets.find { |t| t.name == TARGET_NAME }
|
|
|
|
unless target
|
|
abort "ERROR: Target '#{TARGET_NAME}' not found in project."
|
|
end
|
|
|
|
# Check if the build phase already exists (idempotency)
|
|
existing = target.build_phases.find do |phase|
|
|
phase.is_a?(Xcodeproj::Project::Object::PBXShellScriptBuildPhase) && phase.name == PHASE_NAME
|
|
end
|
|
|
|
if existing
|
|
puts "OK: Build phase '#{PHASE_NAME}' already exists. No changes needed."
|
|
exit 0
|
|
end
|
|
|
|
# Create the new build phase
|
|
phase = target.new_shell_script_build_phase(PHASE_NAME)
|
|
phase.shell_path = '/bin/sh'
|
|
phase.shell_script = SHELL_SCRIPT
|
|
phase.input_paths = []
|
|
phase.output_paths = []
|
|
phase.run_only_for_deployment_postprocessing = '0'
|
|
|
|
# Move it before the embed frameworks phase (or at the end if no such phase)
|
|
# Order: Sources -> Frameworks -> Resources -> ... -> ThinBinary -> CopyGoogleService -> EmbedPodsFrameworks -> CopyPodsResources
|
|
build_phases = target.build_phases
|
|
|
|
# Find the index of "Thin Binary" if it exists
|
|
thin_binary_idx = build_phases.find_index do |p|
|
|
p.respond_to?(:name) && p.name == 'Thin Binary'
|
|
end
|
|
|
|
# Find the index of "[CP] Embed Pods Frameworks" if it exists
|
|
embed_pods_idx = build_phases.find_index do |p|
|
|
p.respond_to?(:name) && p.name && p.name.include?('Embed Pods Frameworks')
|
|
end
|
|
|
|
# Remove the just-added phase from its current position (it gets appended at the end)
|
|
build_phases.delete(phase)
|
|
|
|
# Insert at the right spot
|
|
target_idx = if thin_binary_idx && embed_pods_idx && thin_binary_idx < embed_pods_idx
|
|
# Place between Thin Binary and Embed Pods Frameworks
|
|
embed_pods_idx
|
|
elsif thin_binary_idx
|
|
# Place right after Thin Binary
|
|
thin_binary_idx + 1
|
|
elsif embed_pods_idx
|
|
# Place right before Embed Pods Frameworks
|
|
embed_pods_idx
|
|
else
|
|
# Append at the end
|
|
build_phases.length
|
|
end
|
|
|
|
build_phases.insert(target_idx, phase)
|
|
|
|
project.save
|
|
|
|
puts "OK: Added build phase '#{PHASE_NAME}' at position #{target_idx}."
|
|
puts "Build phases order:"
|
|
target.build_phases.each_with_index do |p, i|
|
|
name = p.respond_to?(:name) && p.name ? p.name : p.class.name
|
|
puts " #{i}: #{name}"
|
|
end
|