hellbender-wallet/fastlane/Fastfile
Nick Klockenga 209750c4e5
Rebrand Wallet to Birch Wallet (#28)
* step one

* progress

* minor theme enhancements

* update screenshot and icon links in README.md

* update site link

* swiftformat fixes
2026-04-30 21:00:59 -04:00

161 lines
7.5 KiB
Ruby
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

default_platform(:ios)
DERIVED_DATA = File.expand_path("../build/DerivedData", __dir__)
PRODUCTS_DIR = "#{DERIVED_DATA}/Build/Products"
SCREENSHOT_SRC = File.expand_path("~/Library/Caches/tools.fastlane/screenshots")
# The xctestrun manifest produced by `build-for-testing`.
# Glob because the filename embeds the SDK version.
def xctestrun_path
Dir.glob("#{PRODUCTS_DIR}/*.xctestrun").first ||
UI.user_error!("No .xctestrun found — run the build step first")
end
# Device matrix — must match what is available in Simulator.
DEVICES = {
"iPhone 17 Pro Max" => "platform=iOS Simulator,name=iPhone 17 Pro Max,OS=26.4",
"iPhone 17 Pro" => "platform=iOS Simulator,name=iPhone 17 Pro,OS=26.4",
"iPhone 11 Pro Max" => "platform=iOS Simulator,name=iPhone 11 Pro Max,OS=26.4",
"iPhone 13 mini" => "platform=iOS Simulator,name=iPhone 13 mini,OS=26.4",
}
platform :ios do
desc "Capture App Store + marketing screenshots (dark first, then light)"
lane :screenshots do
# ── 0. Clear previous output so stale files don't accumulate ────────
FileUtils.rm_rf(File.expand_path("screenshots/dark", __dir__))
FileUtils.rm_rf(File.expand_path("screenshots/light", __dir__))
# ── 1. Build for testing once ────────────────────────────────────────
# Produces birch.app, birchUITests-Runner.app, and the
# .xctestrun manifest that tells xcodebuild which apps to install.
sh("xcodebuild build-for-testing " \
"-scheme birch " \
"-project ../birch.xcodeproj " \
"-destination 'generic/platform=iOS Simulator' " \
"-derivedDataPath '#{DERIVED_DATA}' " \
"-parallel-testing-enabled NO " \
"| xcpretty")
# ── 2. Dark mode ────────────────────────────────────────────────────
run_screenshot_pass(mode: "dark")
# ── 3. Light mode ───────────────────────────────────────────────────
run_screenshot_pass(mode: "light")
# ── 4. Prep captures for frameit ────────────────────────────────────
# frameit gem 2.232.2 hardcodes its device list. scripts/patch-frameit.rb
# extends it with iPhone 16/17 support (PR #29921), so iPhone 17 Pro and
# Pro Max now go through frameit at their native resolution.
#
# * iPhone 13 mini: frameit's bundled 13 Mini frame PNG has a ~3-pixel
# misalignment between the placement offset and the actual screen
# hole, leaving a visible gap on the right edge. Skip frameit for
# this device — step 7 composites it directly with ImageMagick,
# upscaling slightly so the screenshot fully covers the hole.
thirteen_mini_holding = File.expand_path("screenshots/_13mini_bare", __dir__)
FileUtils.rm_rf(thirteen_mini_holding)
FileUtils.mkdir_p(thirteen_mini_holding)
["dark", "light"].each do |mode|
dir = File.expand_path("screenshots/#{mode}/en-US", __dir__)
# Move 13 mini captures out of frameit's path; remember the mode.
mode_holding = "#{thirteen_mini_holding}/#{mode}"
FileUtils.mkdir_p(mode_holding)
Dir.glob("#{dir}/iPhone 13 mini-*.png").each do |src|
next if src.include?("_framed")
FileUtils.mv(src, "#{mode_holding}/#{File.basename(src)}")
end
end
# ── 5. Frame both passes via frameit (11 Pro Max + 17 Pro Max) ─────
frameit(path: "./fastlane/screenshots/dark", use_platform: "IOS")
frameit(path: "./fastlane/screenshots/light", use_platform: "IOS")
# ── 6. Restore original names and separate framed into subfolder ───
["dark", "light"].each do |mode|
src_dir = File.expand_path("screenshots/#{mode}/en-US", __dir__)
framed_dir = File.expand_path("screenshots/#{mode}/framed", __dir__)
FileUtils.mkdir_p(framed_dir)
# Move all _framed.png files into framed/.
Dir.glob("#{src_dir}/*_framed.png").each do |f|
FileUtils.mv(f, "#{framed_dir}/#{File.basename(f)}")
end
end
# ── 7. Custom-frame iPhone 13 mini via ImageMagick ─────────────────
# Composite each bare capture onto the 13 Mini bezel, upscaling slightly
# (1080×2340 → 1086×2353) so the screenshot fully covers the bezel's
# screen hole and no gap shows through on any edge.
mini_frame = File.expand_path("~/.fastlane/frameit/latest/Apple iPhone 13 Mini Midnight.png")
["dark", "light"].each do |mode|
src_dir = File.expand_path("screenshots/#{mode}/en-US", __dir__)
framed_dir = File.expand_path("screenshots/#{mode}/framed", __dir__)
mode_holding = "#{thirteen_mini_holding}/#{mode}"
Dir.glob("#{mode_holding}/*.png").each do |src|
base = File.basename(src, ".png")
framed = "#{framed_dir}/#{base}_framed.png"
sh("magick '#{mini_frame}' \\( '#{src}' -resize 1086x2353! \\) " \
"-gravity center -composite '#{framed}'")
# Restore bare capture to en-US/ for the normal bare output tree
FileUtils.mv(src, "#{src_dir}/#{base}.png")
end
end
FileUtils.rm_rf(thirteen_mini_holding)
end
# ────────────────────────────────────────────────────────────────────────
private_lane :run_screenshot_pass do |options|
mode = options[:mode] # "dark" or "light"
is_dark = mode == "dark"
DEVICES.each do |name, destination|
UI.header("#{mode} mode — #{name}")
# Boot
sh("xcrun simctl boot '#{name}' 2>/dev/null || true")
sleep(5) # let SpringBoard settle
# Appearance
sh("xcrun simctl ui booted appearance #{mode}")
# Clean status bar: 9:41, full battery, full signal
sh("xcrun simctl status_bar booted override " \
"--time 09:41 --dataNetwork wifi --wifiMode active --wifiBars 3 " \
"--cellularMode active --operatorName '' --cellularBars 4 " \
"--batteryState charged --batteryLevel 100 2>/dev/null || true")
# Clear previous screenshots from the cache so we don't mix passes
FileUtils.rm_rf(SCREENSHOT_SRC)
FileUtils.mkdir_p(SCREENSHOT_SRC)
# Run the test with the explicit xctestrun manifest.
# This installs all DependentProductPaths (including birch.app)
# automatically — works around the Xcode 26 bug where
# `xcodebuild build test` / `test-without-building -scheme` fail to
# install the host app.
sh("xcodebuild test-without-building " \
"-xctestrun '#{xctestrun_path}' " \
"-destination '#{destination}' " \
"-only-testing:birchUITests/ScreenshotTests/testScreenshotTour " \
"-parallel-testing-enabled NO") do |status|
UI.error("Test failed on #{name} (#{mode} mode)") unless status.success?
end
# Collect screenshots into the output directory
output_dir = File.expand_path("screenshots/#{mode}/en-US", __dir__)
FileUtils.mkdir_p(output_dir)
Dir.glob("#{SCREENSHOT_SRC}/*.png").each do |src|
FileUtils.cp(src, output_dir)
end
# Reset status bar and shut down
sh("xcrun simctl status_bar booted clear 2>/dev/null || true")
sh("xcrun simctl shutdown '#{name}' 2>/dev/null || true")
end
end
end