Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions scripts/artifacts-utils/ios/patched_ios_artifacts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,43 @@ def self.setup
ReactNativeCoreUtils.class_variable_set(:@@patched_artifact_url_prefix, resolution['artifactUrlPrefix'])
ReactNativeCoreUtils.class_variable_set(:@@patched_github_token, resolution['githubToken'])
ReactNativeCoreUtils.class_variable_set(:@@patched_build_from_source, resolution['buildFromSource'])

# Content identity of this install's artifacts; '+dsym' so flipping the flag counts as a change.
@artifacts_stamp = @using_prebuilt ?
"#{resolution['version']}#{ENV['RCT_SYMBOLICATE_PREBUILT_FRAMEWORKS'] == '1' ? '+dsym' : ''}" : nil
Comment thread
mateuuszzzzz marked this conversation as resolved.

force_rncore_podspec_reevaluation if @using_prebuilt
end

def self.artifacts_stamp_path
File.join(Pod::Config.instance.project_pods_root, 'ReactNativeCore-artifacts', '.artifacts-version')
end

# CocoaPods memoizes external :podspec sources and may skip re-reading ours, whose source is
# resolved dynamically. When the tarballs in Pods don't match this install's resolution, drop
# the memoized copy so CocoaPods re-evaluates the podspec, re-running our download (and dSYM
# merge). The re-read podspec is byte-identical, so Podfile.lock stays put.
def self.force_rncore_podspec_reevaluation
return if File.exist?(artifacts_stamp_path) && File.read(artifacts_stamp_path) == @artifacts_stamp

Pod::Config.instance.sandbox.remove_local_podspec('React-Core-prebuilt')
log("Artifacts changed to #{@artifacts_stamp}; the React-Core-prebuilt podspec will be re-evaluated.")
end

# Prepends sync-prebuilt-rncore.sh to react-native's '[RNCore] Replace ...' build phase, so a
# build re-extracts the prebuilt React Core when the artifact version changed — CocoaPods won't,
# as its caches key on our never-changing source URL. Prepended into that phase (not added as
# its own) because CocoaPods sorts phases by name on save, which would push ours after [RNCore].
def self.add_sync_prebuilt_script_phase(installer)
return unless @using_prebuilt

target = installer.pods_project.targets.find { |t| t.name == 'React-Core-prebuilt' }
phase = target&.shell_script_build_phases&.find { |p| p.name.to_s.include?('[RNCore] Replace') }
raise "#{LOG_PREFIX} The [RNCore] Replace build phase was not found on the React-Core-prebuilt target, " \
'so the extracted prebuilt React Core would keep following a stale artifact version.' unless phase

prelude = %(bash "#{File.join(NEW_DOT_ROOT, 'scripts/artifacts-utils/ios/sync-prebuilt-rncore.sh')}" || exit 1\n)
phase.shell_script = prelude + phase.shell_script unless phase.shell_script.start_with?(prelude)
end

# True only when a matching prebuilt artifact resolved and prebuilds are enabled.
Expand Down Expand Up @@ -225,6 +262,10 @@ def self.podspec_source_download_prebuild_stable_tarball
process_dsyms(release, download_stable_rncore(@@react_native_path, @@react_native_version, :release, true))
end

# Content version of the flat tarballs — their names can't carry it, replace-rncore-version.js hardcodes them.
File.write(File.join(File.dirname(debug), '.artifacts-version'),
"#{@@patched_version}#{@@download_dsyms ? '+dsym' : ''}")

# URI::File.build validates path components as ASCII, so escape the filesystem path first —
# matches RN 0.86's own ReactNativePodsUtils.local_file_uri, which this replaces.
{:http => URI::File.build(path: URI::DEFAULT_PARSER.escape(debug)).to_s}
Expand Down
31 changes: 31 additions & 0 deletions scripts/artifacts-utils/ios/sync-prebuilt-rncore.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/bash
# Prelude of react-native's '[RNCore] Replace ...' build phase (prepended by
# PatchedIOSArtifacts.add_sync_prebuilt_script_phase). When the extracted prebuilt React Core
# is a different patched artifact version than the tarballs in Pods, invalidates the
# .last_build_configuration marker so replace-rncore-version.js, running right after this,
# re-extracts from the tarballs. Needed because our tarball path carries no patches version,
# so a version change is invisible to CocoaPods and it can keep a stale extraction.
#
# Expected Xcode environment variables:
# PODS_ROOT
set -euo pipefail

TARBALLS_STAMP="$PODS_ROOT/ReactNativeCore-artifacts/.artifacts-version"
PREBUILT_DIR="$PODS_ROOT/React-Core-prebuilt"
readonly TARBALLS_STAMP PREBUILT_DIR

# No stamp: the last install built react-native from source — nothing to sync.
[ -f "$TARBALLS_STAMP" ] || exit 0

TARBALLS=$(cat "$TARBALLS_STAMP")
EXTRACTED=$(cat "$PREBUILT_DIR/.patched-version" 2>/dev/null || true)
# Fast path, taken on every build: what is extracted matches the tarballs.
[ "$TARBALLS" = "$EXTRACTED" ] && exit 0

echo "[PatchedArtifacts] Extracted prebuilt React Core is '${EXTRACTED:-<none>}', tarballs are '$TARBALLS' — marking for re-extraction."
mkdir -p "$PREBUILT_DIR"
# 'stale' matches no configuration, so replace-rncore-version.js re-extracts; it stays until
# an extraction succeeds and writes a real configuration back, so a failed build retries.
# No trailing newlines: replace-rncore-version.js compares its marker verbatim.
printf 'stale' > "$PREBUILT_DIR/.last_build_configuration"
printf '%s' "$TARBALLS" > "$PREBUILT_DIR/.patched-version"
Loading