From 828b582f1366b3b8c84c36d0de4a302c202b919b Mon Sep 17 00:00:00 2001 From: Jeremy Massel <1123407+jkmassel@users.noreply.github.com> Date: Fri, 6 Mar 2026 11:04:22 -0700 Subject: [PATCH 1/5] Cache Gutenberg XCFramework downloads on disk Replace the Ruby download/extract logic in the Rakefile with a bash script that caches the extracted XCFrameworks in ~/Library/Caches. On subsequent runs the script copies from cache instead of re-downloading. curl --progress-bar provides download feedback that was previously missing. Also adds a Makefile with a `dependencies` target for convenience. Co-Authored-By: Claude Opus 4.6 --- Makefile | 7 +++ Rakefile | 51 +--------------------- Scripts/download-gutenberg-xcframeworks.sh | 45 +++++++++++++++++++ 3 files changed, 53 insertions(+), 50 deletions(-) create mode 100644 Makefile create mode 100755 Scripts/download-gutenberg-xcframeworks.sh diff --git a/Makefile b/Makefile new file mode 100644 index 000000000000..c983e05f6991 --- /dev/null +++ b/Makefile @@ -0,0 +1,7 @@ +GUTENBERG_VERSION := v1.121.0 +FRAMEWORKS_DIR := WordPress/Frameworks + +.PHONY: dependencies + +dependencies: + ./Scripts/download-gutenberg-xcframeworks.sh $(GUTENBERG_VERSION) $(FRAMEWORKS_DIR) diff --git a/Rakefile b/Rakefile index ee86adc9f01e..bb1b8ba9bda9 100644 --- a/Rakefile +++ b/Rakefile @@ -6,9 +6,6 @@ require 'tmpdir' require 'rake/clean' require 'yaml' require 'digest' -require 'open-uri' -require 'rubygems/package' -require 'zlib' RUBY_REPO_VERSION = File.read('./.ruby-version').rstrip XCODE_WORKSPACE = 'WordPress.xcworkspace' @@ -101,53 +98,7 @@ bundle exec fastlane run configure_apply force:true desc 'Download and extract Gutenberg xcframeworks' task :gutenberg_xcframeworks do - puts 'Setting up Gutenberg xcframeworks...' - - frameworks_dir = 'WordPress/Frameworks' - - # Clean the slate - FileUtils.rm_rf(frameworks_dir) - FileUtils.mkdir_p(frameworks_dir) - - gutenberg_tar_gz_download_path = "#{frameworks_dir}/Gutenberg.tar.gz" - - URI.open("https://cdn.a8c-ci.services/gutenberg-mobile/Gutenberg-#{GUTENBERG_VERSION}.tar.gz") do |remote_file| - File.binwrite(gutenberg_tar_gz_download_path, remote_file.read) - end - - # Extract the archive - Zlib::GzipReader.open(gutenberg_tar_gz_download_path) do |gz| - Gem::Package::TarReader.new(gz) do |tar| - tar.each do |entry| - next unless entry.file? - - dest_path = File.join(frameworks_dir, entry.full_name) - FileUtils.mkdir_p(File.dirname(dest_path)) - - File.binwrite(dest_path, entry.read) - end - end - end - - # Move xcframeworks to the correct location - Dir.glob("#{frameworks_dir}/Frameworks/*.xcframework").each do |framework| - FileUtils.mv(framework, frameworks_dir, force: false) - end - - # Create dSYMs directories - FileUtils.mkdir_p [ - "#{frameworks_dir}/hermes.xcframework/ios-arm64/dSYMs", - "#{frameworks_dir}/hermes.xcframework/ios-arm64_x86_64-simulator/dSYMs" - ] - - # Cleanup - FileUtils.rm_rf [ - gutenberg_tar_gz_download_path, - "#{frameworks_dir}/Frameworks", - "#{frameworks_dir}/dummy.txt" - ] - - puts 'Gutenberg xcframeworks setup complete' + sh("#{PROJECT_DIR}/Scripts/download-gutenberg-xcframeworks.sh", GUTENBERG_VERSION, 'WordPress/Frameworks') end end diff --git a/Scripts/download-gutenberg-xcframeworks.sh b/Scripts/download-gutenberg-xcframeworks.sh new file mode 100755 index 000000000000..f7700961d4a4 --- /dev/null +++ b/Scripts/download-gutenberg-xcframeworks.sh @@ -0,0 +1,45 @@ +#!/bin/bash +set -euo pipefail + +# Downloads and installs Gutenberg XCFrameworks with progress and on-disk caching. +# +# Usage: download-gutenberg-xcframeworks.sh +# Example: download-gutenberg-xcframeworks.sh v1.121.0 WordPress/Frameworks + +VERSION="${1:?Usage: $0 }" +FRAMEWORKS_DIR="${2:?Usage: $0 }" + +CACHE_DIR="${HOME}/Library/Caches/WordPress-iOS/Gutenberg/${VERSION}" +DOWNLOAD_URL="https://cdn.a8c-ci.services/gutenberg-mobile/Gutenberg-${VERSION}.tar.gz" + +# Download and extract into the cache if this version isn't cached yet. +if [[ -d "${CACHE_DIR}" ]]; then + echo "Using cached Gutenberg ${VERSION}" +else + echo "Downloading Gutenberg ${VERSION}..." + mkdir -p "${CACHE_DIR}" + + curl --fail --location --progress-bar "${DOWNLOAD_URL}" \ + | tar xzf - -C "${CACHE_DIR}" + + # Move xcframeworks up from the nested Frameworks/ directory. + if [[ -d "${CACHE_DIR}/Frameworks" ]]; then + mv "${CACHE_DIR}"/Frameworks/*.xcframework "${CACHE_DIR}/" + rm -rf "${CACHE_DIR}/Frameworks" + fi + + # Create dSYMs directories that Xcode expects for hermes. + mkdir -p \ + "${CACHE_DIR}/hermes.xcframework/ios-arm64/dSYMs" \ + "${CACHE_DIR}/hermes.xcframework/ios-arm64_x86_64-simulator/dSYMs" + + # Clean up leftover files from the archive. + rm -f "${CACHE_DIR}/dummy.txt" +fi + +# Copy cached frameworks into the project. +rm -rf "${FRAMEWORKS_DIR}" +mkdir -p "${FRAMEWORKS_DIR}" +cp -a "${CACHE_DIR}/"*.xcframework "${FRAMEWORKS_DIR}/" + +echo "Gutenberg ${VERSION} setup complete." From aa5f84b28b9e19eae64605490227471fc45ef7a1 Mon Sep 17 00:00:00 2001 From: Jeremy Massel <1123407+jkmassel@users.noreply.github.com> Date: Fri, 6 Mar 2026 11:14:25 -0700 Subject: [PATCH 2/5] Fix corrupted cache from partial downloads Extract into a temp directory and only move it to the final cache path after the download and extraction succeed. A partial download no longer leaves a corrupt cache directory that would be reused on every subsequent run. Co-Authored-By: Claude Opus 4.6 --- Scripts/download-gutenberg-xcframeworks.sh | 25 +++++++++++++++------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/Scripts/download-gutenberg-xcframeworks.sh b/Scripts/download-gutenberg-xcframeworks.sh index f7700961d4a4..099802d35b01 100755 --- a/Scripts/download-gutenberg-xcframeworks.sh +++ b/Scripts/download-gutenberg-xcframeworks.sh @@ -17,24 +17,33 @@ if [[ -d "${CACHE_DIR}" ]]; then echo "Using cached Gutenberg ${VERSION}" else echo "Downloading Gutenberg ${VERSION}..." - mkdir -p "${CACHE_DIR}" + + # Extract into a temp directory first so a partial download doesn't + # leave a corrupt cache that persists across runs. + TEMP_DIR="$(mktemp -d "${CACHE_DIR}.XXXXXX")" + trap 'rm -rf "${TEMP_DIR}"' EXIT curl --fail --location --progress-bar "${DOWNLOAD_URL}" \ - | tar xzf - -C "${CACHE_DIR}" + | tar xzf - -C "${TEMP_DIR}" # Move xcframeworks up from the nested Frameworks/ directory. - if [[ -d "${CACHE_DIR}/Frameworks" ]]; then - mv "${CACHE_DIR}"/Frameworks/*.xcframework "${CACHE_DIR}/" - rm -rf "${CACHE_DIR}/Frameworks" + if [[ -d "${TEMP_DIR}/Frameworks" ]]; then + mv "${TEMP_DIR}"/Frameworks/*.xcframework "${TEMP_DIR}/" + rm -rf "${TEMP_DIR}/Frameworks" fi # Create dSYMs directories that Xcode expects for hermes. mkdir -p \ - "${CACHE_DIR}/hermes.xcframework/ios-arm64/dSYMs" \ - "${CACHE_DIR}/hermes.xcframework/ios-arm64_x86_64-simulator/dSYMs" + "${TEMP_DIR}/hermes.xcframework/ios-arm64/dSYMs" \ + "${TEMP_DIR}/hermes.xcframework/ios-arm64_x86_64-simulator/dSYMs" # Clean up leftover files from the archive. - rm -f "${CACHE_DIR}/dummy.txt" + rm -f "${TEMP_DIR}/dummy.txt" + + # Atomically promote the temp directory to the final cache path. + mkdir -p "$(dirname "${CACHE_DIR}")" + mv "${TEMP_DIR}" "${CACHE_DIR}" + trap - EXIT fi # Copy cached frameworks into the project. From 27c0c0811b843183646b69d477cb25221b59e93b Mon Sep 17 00:00:00 2001 From: Jeremy Massel <1123407+jkmassel@users.noreply.github.com> Date: Fri, 6 Mar 2026 11:15:49 -0700 Subject: [PATCH 3/5] Make the script the single source of truth for Gutenberg version Move GUTENBERG_VERSION into the bash script and default the frameworks directory so neither the Rakefile nor the Makefile need to know about it. One place to update when bumping the version. Co-Authored-By: Claude Opus 4.6 --- Makefile | 5 +---- Rakefile | 4 +--- Scripts/download-gutenberg-xcframeworks.sh | 8 ++++---- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index c983e05f6991..ec8f8b3beca9 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,4 @@ -GUTENBERG_VERSION := v1.121.0 -FRAMEWORKS_DIR := WordPress/Frameworks - .PHONY: dependencies dependencies: - ./Scripts/download-gutenberg-xcframeworks.sh $(GUTENBERG_VERSION) $(FRAMEWORKS_DIR) + ./Scripts/download-gutenberg-xcframeworks.sh diff --git a/Rakefile b/Rakefile index bb1b8ba9bda9..17a94f225791 100644 --- a/Rakefile +++ b/Rakefile @@ -10,8 +10,6 @@ require 'digest' RUBY_REPO_VERSION = File.read('./.ruby-version').rstrip XCODE_WORKSPACE = 'WordPress.xcworkspace' EXPECTED_XCODE_VERSION = File.read('.xcode-version').rstrip -GUTENBERG_VERSION = 'v1.121.0' - PROJECT_DIR = __dir__ abort('Project directory contains one or more spaces – unable to continue.') if PROJECT_DIR.include?(' ') @@ -98,7 +96,7 @@ bundle exec fastlane run configure_apply force:true desc 'Download and extract Gutenberg xcframeworks' task :gutenberg_xcframeworks do - sh("#{PROJECT_DIR}/Scripts/download-gutenberg-xcframeworks.sh", GUTENBERG_VERSION, 'WordPress/Frameworks') + sh("#{PROJECT_DIR}/Scripts/download-gutenberg-xcframeworks.sh") end end diff --git a/Scripts/download-gutenberg-xcframeworks.sh b/Scripts/download-gutenberg-xcframeworks.sh index 099802d35b01..bac10b7c9b65 100755 --- a/Scripts/download-gutenberg-xcframeworks.sh +++ b/Scripts/download-gutenberg-xcframeworks.sh @@ -3,11 +3,11 @@ set -euo pipefail # Downloads and installs Gutenberg XCFrameworks with progress and on-disk caching. # -# Usage: download-gutenberg-xcframeworks.sh -# Example: download-gutenberg-xcframeworks.sh v1.121.0 WordPress/Frameworks +# Usage: download-gutenberg-xcframeworks.sh [frameworks_dir] +# frameworks_dir defaults to WordPress/Frameworks -VERSION="${1:?Usage: $0 }" -FRAMEWORKS_DIR="${2:?Usage: $0 }" +VERSION="v1.121.0" +FRAMEWORKS_DIR="${1:-WordPress/Frameworks}" CACHE_DIR="${HOME}/Library/Caches/WordPress-iOS/Gutenberg/${VERSION}" DOWNLOAD_URL="https://cdn.a8c-ci.services/gutenberg-mobile/Gutenberg-${VERSION}.tar.gz" From 15a96bad880f77d702638a536b0cb1c52754b0a8 Mon Sep 17 00:00:00 2001 From: Jeremy Massel <1123407+jkmassel@users.noreply.github.com> Date: Fri, 6 Mar 2026 11:35:41 -0700 Subject: [PATCH 4/5] Create cache parent directory before mktemp mktemp requires the parent directory to exist. Move the mkdir -p before the mktemp call so it works on fresh CI agents where the Caches directory doesn't exist yet. Co-Authored-By: Claude Opus 4.6 --- Scripts/download-gutenberg-xcframeworks.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/download-gutenberg-xcframeworks.sh b/Scripts/download-gutenberg-xcframeworks.sh index bac10b7c9b65..1e550c77a419 100755 --- a/Scripts/download-gutenberg-xcframeworks.sh +++ b/Scripts/download-gutenberg-xcframeworks.sh @@ -20,6 +20,7 @@ else # Extract into a temp directory first so a partial download doesn't # leave a corrupt cache that persists across runs. + mkdir -p "$(dirname "${CACHE_DIR}")" TEMP_DIR="$(mktemp -d "${CACHE_DIR}.XXXXXX")" trap 'rm -rf "${TEMP_DIR}"' EXIT @@ -41,7 +42,6 @@ else rm -f "${TEMP_DIR}/dummy.txt" # Atomically promote the temp directory to the final cache path. - mkdir -p "$(dirname "${CACHE_DIR}")" mv "${TEMP_DIR}" "${CACHE_DIR}" trap - EXIT fi From 8b128435b513359d1c87c4812b58e48a9f932b01 Mon Sep 17 00:00:00 2001 From: Jeremy Massel <1123407+jkmassel@users.noreply.github.com> Date: Fri, 6 Mar 2026 13:20:15 -0700 Subject: [PATCH 5/5] Copy all archive contents, not just xcframeworks The archive also contains react-native-bundle-source-map which is needed for Sentry sourcemap uploads. Copy everything from the cache directory instead of only *.xcframework. Co-Authored-By: Claude Opus 4.6 --- Scripts/download-gutenberg-xcframeworks.sh | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Scripts/download-gutenberg-xcframeworks.sh b/Scripts/download-gutenberg-xcframeworks.sh index 1e550c77a419..925fde48cd47 100755 --- a/Scripts/download-gutenberg-xcframeworks.sh +++ b/Scripts/download-gutenberg-xcframeworks.sh @@ -27,9 +27,9 @@ else curl --fail --location --progress-bar "${DOWNLOAD_URL}" \ | tar xzf - -C "${TEMP_DIR}" - # Move xcframeworks up from the nested Frameworks/ directory. + # Move contents up from the nested Frameworks/ directory. if [[ -d "${TEMP_DIR}/Frameworks" ]]; then - mv "${TEMP_DIR}"/Frameworks/*.xcframework "${TEMP_DIR}/" + mv "${TEMP_DIR}"/Frameworks/* "${TEMP_DIR}/" rm -rf "${TEMP_DIR}/Frameworks" fi @@ -46,9 +46,8 @@ else trap - EXIT fi -# Copy cached frameworks into the project. +# Copy cached contents into the project. rm -rf "${FRAMEWORKS_DIR}" -mkdir -p "${FRAMEWORKS_DIR}" -cp -a "${CACHE_DIR}/"*.xcframework "${FRAMEWORKS_DIR}/" +cp -a "${CACHE_DIR}" "${FRAMEWORKS_DIR}" echo "Gutenberg ${VERSION} setup complete."