build(screenshots): use versioned device templates

This commit is contained in:
Kaede Akino committed 2026-10-07 23:56:39 +08:00
1 parent 22a4b8b7a3
commit f1e524166e
3 files changed
+38 -11

No files matched your search

+25 -2
View File
@@ -299,7 +299,7 @@ class ScreenshotFramesTests < Minitest::Test
File.write(File.join(@root, "com.akinokaede.termind/.git"), "gitdir: fixture")
FileUtils.mkdir_p(File.join(@root, "fastlane"))
FileUtils.cp(File.expand_path("../../fastlane/Framefile.json", __dir__), File.join(@root, "fastlane"))
frame_template(File.join(@root, ".build/frameit-assets/iphone-18-pro.png"), 1350, 2760)
frame_template(File.join(@root, "com.akinokaede.termind/assets/device_templates/iphone-18-pro.png"), 1350, 2760)
@templates = File.join(@root, "templates")
FileUtils.mkdir_p(@templates)
end
@@ -400,12 +400,14 @@ class ScreenshotFramesTests < Minitest::Test
end
def test_explicit_frame_paths_work_without_submodule_and_keep_source_bytes
template = File.join(@root, "external-template.png")
FileUtils.mv(File.join(@root, "com.akinokaede.termind/assets/device_templates/iphone-18-pro.png"), template)
FileUtils.remove_entry(File.join(@root, "com.akinokaede.termind"))
source = File.join(@root, "review-input/en/iphone-6.3/vault.png")
png(source, 1206, 2622)
original_hash = Digest::SHA256.file(source).hexdigest
runner = ScreenshotFrames.new({ devices: "iphone", scenes: "vault", locales: "en",
input: "review-input", output: "review-output" }, root: @root)
input: "review-input", output: "review-output", iphone_frame: template }, root: @root)
downloader = Object.new
downloader.define_singleton_method(:frames_exist?) { true }
Frameit::FrameDownloader.stub(:templates_path, @templates) do
@@ -423,6 +425,26 @@ class ScreenshotFramesTests < Minitest::Test
refute Dir.exist?(File.join(@root, "com.akinokaede.termind"))
end
def test_default_template_works_without_a_local_build_cache
source = File.join(@root, "com.akinokaede.termind/assets/captures/en/iphone-6.3/vault.png")
png(source, 1206, 2622)
refute Dir.exist?(File.join(@root, ".build"))
runner = ScreenshotFrames.new({ devices: "iphone", scenes: "vault", locales: "en" }, root: @root)
downloader = Object.new
downloader.define_singleton_method(:frames_exist?) { true }
Frameit::FrameDownloader.stub(:templates_path, @templates) do
Frameit::FrameDownloader.stub(:new, downloader) do
runner.run do |options|
installed = File.join(@templates, "Apple iPhone 18 Pro Silver.png")
assert_equal Digest::SHA256.file(File.join(@root, "com.akinokaede.termind/assets/device_templates/iphone-18-pro.png")).hexdigest,
Digest::SHA256.file(installed).hexdigest
png(File.join(options.fetch(:path), "iphone_framed.png"), 1350, 2760)
end
end
end
assert_equal [1350, 2760], FastImage.size(File.join(@root, "com.akinokaede.termind/assets/device_frames/en/iphone-6.3/vault.png"))
end
def test_rejects_pro_max_sources_before_calling_frameit
source = File.join(@root, "com.akinokaede.termind/assets/captures/en/iphone-6.3/vault.png")
png(source, 1320, 2868)
@@ -471,6 +493,7 @@ class ScreenshotFramesTests < Minitest::Test
runner = ScreenshotFrames.new({ devices: "iphone-duo-inner", locales: "en" }, root: @root)
error = assert_raises(RuntimeError) { runner.run { flunk "frameit must not start" } }
assert_includes error.message, "iphone_duo_inner_frame:"
assert_includes error.message, "git submodule update --init com.akinokaede.termind"
refute Dir.exist?(File.join(@root, "com.akinokaede.termind/assets/device_frames"))
end
+12 -8
View File
@@ -5,6 +5,7 @@ require_relative "screenshots"
# read-only, and the website's existing feature/file names remain stable.
class ScreenshotFrames
DEVICES = %w[iphone iphone-duo-outer iphone-duo-inner ipad mac].freeze
TEMPLATE_DIRECTORY = "com.akinokaede.termind/assets/device_templates".freeze
CUSTOM_FRAMES = {
"iphone" => { name: "iPhone 18 Pro", size: [1350, 2760], offset: "+72+69", width: 1206,
color: "Silver", template: "iphone-18-pro" },
@@ -18,11 +19,11 @@ class ScreenshotFrames
def initialize(options = {}, root: Screenshots::ROOT)
@root = root
@mac_frame = File.expand_path(options[:mac_frame] || ".build/frameit-assets/macbook-pro-14-template.png", root)
@ipad_frame = File.expand_path(options[:ipad_frame] || ".build/frameit-assets/ipad-pro-13-m5.png", root)
@mac_frame = File.expand_path(options[:mac_frame] || "#{TEMPLATE_DIRECTORY}/macbook-pro-14-template.png", root)
@ipad_frame = File.expand_path(options[:ipad_frame] || "#{TEMPLATE_DIRECTORY}/ipad-pro-13-m5.png", root)
@custom_frames = CUSTOM_FRAMES.to_h do |device, specification|
option = device.tr("-", "_").concat("_frame").to_sym
[device, File.expand_path(options[option] || ".build/frameit-assets/#{specification[:template] || device}.png", root)]
[device, File.expand_path(options[option] || "#{TEMPLATE_DIRECTORY}/#{specification[:template] || device}.png", root)]
end
selector = Screenshots.new(:ios, {}, environment: {}, root: root)
@devices = selector.selection(options[:devices], %w[iphone ipad mac], DEVICES, "devices")
@@ -53,8 +54,9 @@ class ScreenshotFrames
(@devices & CUSTOM_FRAMES.keys).each do |device|
specification = CUSTOM_FRAMES.fetch(device)
unless FastImage.size(@custom_frames.fetch(device)) == specification.fetch(:size)
raise "Import the official #{specification.fetch(:name)} #{specification.fetch(:color)} portrait PNG first; " \
"see openwiki/operations/marketing-assets-and-app-icons.md or pass #{device.tr('-', '_')}_frame:/path/to/frame.png"
raise "Missing or invalid #{specification.fetch(:name)} template: #{@custom_frames.fetch(device)}. " \
"Restore templates from the assets repository (git submodule update --init com.akinokaede.termind); " \
"or pass #{device.tr('-', '_')}_frame:/path/to/frame.png"
end
constant = device.tr("-", "_").upcase
unless Frameit::Devices.const_defined?(constant)
@@ -72,11 +74,13 @@ class ScreenshotFrames
))
end
if @devices.include?("ipad") && FastImage.size(@ipad_frame) != [2300, 3000]
raise "Import the official iPad Pro (M5) 13-inch Space Black portrait PNG first; " \
"see openwiki/operations/marketing-assets-and-app-icons.md or pass ipad_frame:/path/to/frame.png"
raise "Missing or invalid iPad template: #{@ipad_frame}. " \
"Restore templates from the assets repository (git submodule update --init com.akinokaede.termind); " \
"or pass ipad_frame:/path/to/frame.png"
end
if @devices.include?("mac") && FastImage.size(@mac_frame) != [3860, 2320]
raise "Import the narrow MacBook Pro template first; see openwiki/operations/marketing-assets-and-app-icons.md " \
raise "Missing or invalid Mac template: #{@mac_frame}. " \
"Restore templates from the assets repository (git submodule update --init com.akinokaede.termind); " \
"or pass mac_frame:/path/to/frame.png"
end
@jobs.each do |job|