Cách tự động hóa ảnh chụp màn hình App Store trong CI/CD
Một quy trình thực tiễn toàn diện để tạo ảnh chụp màn hình App Store và Google Play từ hệ thống CI của bạn bằng Fastlane, GitHub Actions và Bitrise — kèm cấu hình cụ thể bạn có thể dán thẳng vào kho lưu trữ của mình.
Tóm tắt nhanh
Chụp ảnh màn hình ứng dụng thô trong trình chạy thử nghiệm của bạn, gửi chúng tới API của Screenshots.live cùng với một mã ID mẫu và danh sách ngôn ngữ, rồi Fastlane ghi đầu ra đã được kết xuất, đóng khung và bản địa hóa trở lại kho lưu trữ của bạn. Fastlane deliver / supply sẽ đẩy chúng lên các cửa hàng. Toàn bộ quy trình chạy khi đẩy thẻ tag hoặc cron hằng đêm trong chưa đầy năm phút.
Tại sao phải tự động hóa ảnh chụp màn hình?
Hầu hết các nhóm coi ảnh chụp màn hình App Store và Google Play là tài sản làm thủ công một lần: một nhà thiết kế dựng chúng trong Figma, một nhân viên marketing tải lên App Store Connect, và không ai đụng vào chúng nữa cho đến lần thiết kế lại lớn tiếp theo. Mô hình đó sụp đổ ngay khi bạn phát hành cho hơn một ngôn ngữ. Với 13 ngôn ngữ được hỗ trợ, ba kích thước iPhone bắt buộc, hai kích thước iPad, cộng thêm điện thoại và máy tính bảng trên Google Play, bạn đang đối diện với hơn 100 tệp PNG cho một lần phát hành duy nhất. Nhân lên với mỗi thay đổi văn bản, mỗi đợt khuyến mãi, mỗi biến thể thử nghiệm A/B, và bài toán không còn khả thi nữa.
Tự động hóa trong CI/CD biến ảnh chụp màn hình thành một sản phẩm đầu ra của bản dựng giống như bất kỳ tệp nhị phân nào khác. Chúng được phiên bản hóa, có thể tái tạo và gắn liền với một commit. Khi marketing thay đổi một câu chú thích, quy trình sẽ dựng lại mọi ngôn ngữ và tải lên — không cần phiên Photoshop thủ công, không có sự lệch tài sản giữa các ngôn ngữ, không bị từ chối khi nộp vì có người quên mất biến thể iPhone 6.7 inch.
Quy trình thực tế trông như thế nào?
Hình hài của một quy trình ảnh chụp màn hình CI sạch gồm ba giai đoạn: chụp, kết xuất, và giao. Chụp là bộ kiểm thử giao diện hiện có của bạn — XCUITest trên iOS, Espresso trên Android, Detox hoặc Maestro cho React Native. Kết xuất là một lệnh gọi API Screenshots.live cho mỗi ngôn ngữ, ghép các khung thô của bạn lên một mẫu bạn đã thiết kế sẵn một lần. Giao là các action deliver và supply sẵn có của Fastlane mà bạn vẫn dùng để đẩy tệp nhị phân.
API kết xuất REST của Screenshots.live là viên đá nền tảng. Bạn gửi ảnh chụp màn hình thô một lần và nhận về mọi kích thước thiết bị, mọi ngôn ngữ và mọi biến thể — đã được đóng khung, gắn chú thích và bản địa hóa đầy đủ. Không cần trình duyệt headless, không cần Puppeteer, không cần đổi kích thước thủ công.
Làm sao để kết nối với Fastlane?
Fastlane là công cụ chuẩn mực để tự động hóa phát hành iOS / Android. Chúng tôi phát hành một plugin Fastlane chính thức bao bọc API kết xuất trong một action duy nhất. Cài đặt nó từ thư mục gốc dự án của bạn:
fastlane add_plugin screenshotsliveSau đó thêm một lane vào Fastfile của bạn để chụp, kết xuất và ghi kết quả đã kết xuất:
lane :render_screenshots do
# 1. Capture raw frames with XCUITest
capture_screenshots(
workspace: "MyApp.xcworkspace",
scheme: "MyAppUITests",
devices: ["iPhone 16 Pro Max", "iPad Pro 12.9-inch"],
languages: ["en-US", "de-DE", "es-ES", "fr-FR", "pt-BR"]
)
# 2. Send raw frames to Screenshots.live, get framed PNGs back
screenshotslive_render(
api_token: ENV["SCREENSHOTSLIVE_API_TOKEN"],
template_id: "tpl_app_release_v3",
input_dir: "./fastlane/screenshots",
output_dir: "./fastlane/rendered",
locales: ["en", "de", "es", "fr", "pt"],
devices: ["iphone-6.7", "iphone-6.1", "ipad-12.9"]
)
# 3. Push to App Store Connect
deliver(
screenshots_path: "./fastlane/rendered",
skip_binary_upload: true,
skip_metadata: false
)
endPlugin xử lý việc tải lên, thăm dò trạng thái hoàn tất và tải xuống song song. Một lượt kết xuất 5 ngôn ngữ, 3 thiết bị tiêu biểu hoàn tất trong 60–90 giây.
Làm sao để chạy việc này trên GitHub Actions?
Đưa lane vào một tệp workflow. Workflow bên dưới chạy trên mỗi lần đẩy thẻ tag khớp với v* và theo lịch hằng đêm, vì vậy chỉ cần thực hiện thủ công git tag v1.2.0 && git push --tags là đủ để kích hoạt một lượt kết xuất mới.
name: Render Store Screenshots
on:
push:
tags: ["v*"]
schedule:
- cron: "0 4 * * *" # nightly at 04:00 UTC
workflow_dispatch:
jobs:
render:
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
ruby-version: "3.2"
bundler-cache: true
- name: Render screenshots
env:
SCREENSHOTSLIVE_API_TOKEN: ${{ secrets.SCREENSHOTSLIVE_API_TOKEN }}
FASTLANE_USER: ${{ secrets.FASTLANE_USER }}
FASTLANE_PASSWORD: ${{ secrets.FASTLANE_PASSWORD }}
run: bundle exec fastlane render_screenshots
- name: Upload rendered artifacts
uses: actions/upload-artifact@v4
with:
name: store-screenshots
path: fastlane/rendered/Đối với các nhóm thích dùng GitHub Action mà không cần Fastlane, chúng tôi cũng phát hành một GitHub Action độc lập giao tiếp trực tiếp với API:
- uses: Screenshots-Live/render-screenshots-action@v1
with:
api-token: ${{ secrets.SCREENSHOTSLIVE_API_TOKEN }}
template-id: tpl_app_release_v3
locales: en,de,es,fr,pt,it,nl
devices: iphone-6.7,iphone-6.1,ipad-12.9
output-dir: ./screenshotsCòn Bitrise thì sao?
Người dùng Bitrise có cùng một lane thông qua bước Fastlane hiện có. Thêm một Secret tên SCREENSHOTSLIVE_API_TOKEN trong workspace Bitrise của bạn, rồi đưa đoạn này vào bitrise.yml:
workflows:
render-screenshots:
steps:
- activate-ssh-key@4: {}
- git-clone@8: {}
- script@1:
title: Install Fastlane plugins
inputs:
- content: |-
#!/usr/bin/env bash
bundle install
bundle exec fastlane add_plugin screenshotslive
- fastlane@3:
inputs:
- lane: render_screenshots
- work_dir: "$BITRISE_SOURCE_DIR"
- deploy-to-bitrise-io@2:
inputs:
- deploy_path: ./fastlane/renderedLàm sao để giữ thời gian dựng ở mức thấp?
Phần chậm của bất kỳ quy trình ảnh chụp màn hình CI nào là kết xuất, không phải tải lên. Mẹo là cache các lượt kết xuất theo hash nội dung để các ngôn ngữ không thay đổi tái sử dụng đầu ra trước đó. Screenshots.live trả về một renderHash ổn định trong phản hồi — hãy dùng nó làm khóa cache:
- Phiên bản mẫu + ngôn ngữ + hash biến thể → khóa cache
- Byte PNG đã kết xuất → giá trị cache
- Thời gian sống cache: 30 ngày, hoặc cho đến khi mẫu được phát hành lại
Trên GitHub Actions, hãy dùng actions/cache@v4 với khóa được dẫn xuất từ ID mẫu và danh sách ngôn ngữ của bạn. Hầu hết các bản dựng phát hành sẽ bỏ qua hoàn toàn việc kết xuất và chỉ dựng lại ngôn ngữ thực sự đã thay đổi.
Làm sao để xác thực đầu ra trước khi nộp?
Apple và Google đều âm thầm từ chối ảnh chụp màn hình khi chúng không qua kiểm tra định dạng: một tệp PNG có kênh alpha, một tệp JPEG được mã hóa dạng CMYK, hoặc một ảnh chụp màn hình iPhone 6.7 inch thiếu một pixel. Hãy xây dựng một bước lint dài 20 dòng để bắt những lỗi này trước khi nộp:
require "chunky_png"
Dir.glob("./fastlane/rendered/**/*.png").each do |path|
png = ChunkyPNG::Image.from_file(path)
raise "alpha channel: #{path}" if png.metadata["ColorType"] == 6
raise "too large: #{path}" if File.size(path) > 30 * 1024 * 1024
raise "wrong size: #{path}" if png.width < 1242
endCó nên chạy theo lịch không?
Có. Một cron hằng đêm có nghĩa là ảnh chụp màn hình được tạo lại bất cứ khi nào mẫu của bạn thay đổi — dù thay đổi đến từ một nhà thiết kế trong trình chỉnh sửa, một bản cập nhật văn bản từ marketing, hay một ngôn ngữ mới được thêm vào. Không có lịch, các trang giới thiệu trên cửa hàng sẽ lệch khỏi sản phẩm thực tế của bạn, và ai đó phải nhớ đẩy một bản dựng mới trước mỗi lần nộp.
Kết hợp lịch với cảnh báo Slack hoặc email khi thất bại. Một lượt kết xuất hỏng vào lúc 04:00 UTC sẽ là một thông báo lúc 07:00 giờ địa phương — không phải là một sự cố chặn phát hành phát hiện vào lúc 17:00 vào ngày bạn muốn phát hành.
Còn Android, React Native và Flutter thì sao?
Quy trình này không phụ thuộc nền tảng ở phía kết xuất — chỉ giai đoạn chụp là thay đổi. Đối với Android, hãy thay capture_screenshots bằng Fastlane screengrab và bộ kiểm thử Espresso của bạn. Đối với React Native, hãy dùng ảnh chụp Detox. Đối với Flutter, hãy dùng ảnh chụp integration_test. Tất cả đều tạo ra các tệp PNG thô mà Screenshots.live xử lý y hệt nhau.
Đọc thêm trong hướng dẫn hỗ trợ đa nền tảng của chúng tôi để biết cấu hình chụp trên từng ngăn xếp.
Bạn nên đi tiếp đâu?
Khi quy trình CI của bạn đã giao ảnh chụp màn hình một cách đáng tin cậy, câu hỏi tiếp theo là ảnh chụp nào sẽ thắng. Hãy kết hợp quy trình này với hướng dẫn thử nghiệm A/B để phát hành các biến thể theo lịch và đo tỷ lệ chuyển đổi. Ghép nó với hướng dẫn bản địa hóa để thêm hơn 30 ngôn ngữ mà không cần hơn 30 quy trình.
Tham khảo có thẩm quyền để đọc thêm: tài liệu ảnh chụp màn hình iOS của Fastlane, action deliver của Fastlane, và thông số kỹ thuật ảnh chụp màn hình chính thức của App Store Connect.
Tự động tạo tất cả các kích thước này
Đừng thay đổi kích thước ảnh chụp màn hình thủ công nữa. Thiết kế một mẫu duy nhất và kết xuất mọi kích thước, thiết bị và ngôn ngữ chỉ với một lệnh gọi API.
Bắt đầu Miễn phí — Dùng thử Screenshots.live