iOS自动化截图管道Skill asc-shots-pipeline

这个技能用于自动化iOS应用的截图流程,包括使用Xcode构建工具、AXe进行UI操作、JSON配置文件、Go框架工具和asc上传功能。适用于移动应用开发中的截图自动化工作流,关键词包括:iOS开发,自动化截图,xcodebuild,AXe,框架,上传,移动开发,DevOps,测试。

移动开发 0 次安装 0 次浏览 更新于 3/13/2026

name: asc-shots-pipeline description: 使用xcodebuild/simctl进行构建运行,AXe进行UI操作,JSON设置和计划文件,基于Go的框架(asc screenshots frame)以及截图上传(asc screenshots upload)来协调iOS截图自动化。当用户请求自动化截图捕获、AXe驱动的模拟器流程、框架组合或截图到上传管道时使用。

asc screenshots pipeline (xcodebuild -> AXe -> frame -> asc)

使用此技能进行代理驱动的截图工作流,其中应用使用Xcode CLI工具构建和启动,UI使用AXe驱动,截图使用asc上传。

当前范围

默认设置

  • 设置文件:.asc/shots.settings.json
  • 捕获计划:.asc/screenshots.json
  • 原始截图目录:./screenshots/raw
  • 框架截图目录:./screenshots/framed
  • 默认框架设备:iphone-air

1) 首先创建设置JSON

创建或更新.asc/shots.settings.json

{
  "version": 1,
  "app": {
    "bundle_id": "com.example.app",
    "project": "MyApp.xcodeproj",
    "scheme": "MyApp",
    "simulator_udid": "booted"
  },
  "paths": {
    "plan": ".asc/screenshots.json",
    "raw_dir": "./screenshots/raw",
    "framed_dir": "./screenshots/framed"
  },
  "pipeline": {
    "frame_enabled": true,
    "upload_enabled": false
  },
  "upload": {
    "version_localization_id": "",
    "device_type": "IPHONE_65",
    "source_dir": "./screenshots/framed"
  }
}

如果故意跳过框架,设置:

  • "frame_enabled": false
  • "upload.source_dir": "./screenshots/raw"

2) 在模拟器上构建并运行应用

使用Xcode CLI进行构建/安装/启动:

xcrun simctl boot "$UDID" || true

xcodebuild \
  -project "MyApp.xcodeproj" \
  -scheme "MyApp" \
  -configuration Debug \
  -destination "platform=iOS Simulator,id=$UDID" \
  -derivedDataPath ".build/DerivedData" \
  build

xcrun simctl install "$UDID" ".build/DerivedData/Build/Products/Debug-iphonesimulator/MyApp.app"
xcrun simctl launch "$UDID" "com.example.app"

如果应用包路径与默认位置不同,使用xcodebuild -showBuildSettings

3) 使用AXe捕获截图(或asc screenshots run

优先使用计划驱动的捕获:

asc screenshots run --plan ".asc/screenshots.json" --udid "$UDID" --output json

在计划编写期间有用的AXe原语:

axe describe-ui --udid "$UDID"
axe tap --id "search_field" --udid "$UDID"
axe type "wwdc" --udid "$UDID"
axe screenshot --output "./screenshots/raw/home.png" --udid "$UDID"

最小化的.asc/screenshots.json示例:

{
  "version": 1,
  "app": {
    "bundle_id": "com.example.app",
    "udid": "booted",
    "output_dir": "./screenshots/raw"
  },
  "steps": [
    { "action": "launch" },
    { "action": "wait", "duration_ms": 800 },
    { "action": "screenshot", "name": "home" }
  ]
}

4) 使用asc screenshots frame框架截图

asc cli将框架固定到Koubou 0.13.0。 在运行框架步骤之前安装并验证:

pip install koubou==0.13.0
kou --version  # 期望 0.13.0

首先列出支持的框架设备值:

asc screenshots list-frame-devices --output json

框架一个截图(默认为iphone-air):

asc screenshots frame \
  --input "./screenshots/raw/home.png" \
  --output-dir "./screenshots/framed" \
  --device "iphone-air" \
  --output json

支持的--device值:

  • iphone-air (默认)
  • iphone-17-pro
  • iphone-17-pro-max
  • iphone-16e
  • iphone-17

5) 使用asc上传截图

在上传之前生成和审查工件:

asc screenshots review-generate --framed-dir "./screenshots/framed" --output-dir "./screenshots/review"
asc screenshots review-open --output-dir "./screenshots/review"
asc screenshots review-approve --all-ready --output-dir "./screenshots/review"

从配置的源目录上传(当框架启用时默认./screenshots/framed):

asc screenshots upload \
  --version-localization "LOC_ID" \
  --path "./screenshots/framed" \
  --device-type "IPHONE_65" \
  --output json

在需要时列出或验证上传:

asc screenshots sizes --output table
asc screenshots list --version-localization "LOC_ID" --output table

代理行为

  • 在运行命令之前,始终使用--help确认确切的标志。
  • 重新检查命令路径,因为截图命令正在快速演进。
  • 保持输出确定性:对机器步骤默认为JSON。
  • 在选择框架设备之前,优先使用asc screenshots list-frame-devices --output json
  • 确保截图文件在上传之前存在。
  • 使用明确的长标志(如--app--output--version-localization等)。
  • 将截图本地自动化视为实验性,并在面向用户的交接笔记中指明。
  • 如果框架因版本错误失败,重新安装固定的Koubou:pip install koubou==0.13.0

6) 多语言捕获(可选)

不要使用xcrun simctl launch ... -e AppleLanguages进行本地化。 -e是一个环境变量模式,不会可靠地切换应用语言。

对于此管道,使用每个UDID的模拟器范围内的区域设置默认值。这与asc screenshots capture一起工作,它在内部重新启动应用。

# 将每个语言映射到一个专用的模拟器UDID。
# (使用`xcrun simctl create`创建这些模拟器。)
declare -A LOCALE_UDID=(
  ["en-US"]="UDID_EN_US"
  ["de-DE"]="UDID_DE_DE"
  ["fr-FR"]="UDID_FR_FR"
  ["ja-JP"]="UDID_JA_JP"
)

set_simulator_locale() {
  local UDID="$1"
  local LOCALE="$2"            # 例如 de-DE
  local LANG="${LOCALE%%-*}"   # de
  local APPLE_LOCALE="${LOCALE/-/_}" # de_DE

  xcrun simctl boot "$UDID" || true
  xcrun simctl spawn "$UDID" defaults write NSGlobalDomain AppleLanguages -array "$LANG"
  xcrun simctl spawn "$UDID" defaults write NSGlobalDomain AppleLocale -string "$APPLE_LOCALE"
}

for LOCALE in "${!LOCALE_UDID[@]}"; do
  UDID="${LOCALE_UDID[$LOCALE]}"
  echo "捕获 $LOCALE 在 $UDID..."
  set_simulator_locale "$UDID" "$LOCALE"

  xcrun simctl terminate "$UDID" "com.example.app" || true
  asc screenshots capture \
    --bundle-id "com.example.app" \
    --name "home" \
    --udid "$UDID" \
    --output-dir "./screenshots/raw/$LOCALE" \
    --output json
done

如果手动启动(在asc screenshots capture之外),使用应用启动参数:

xcrun simctl launch "$UDID" "com.example.app" -AppleLanguages "(de)" -AppleLocale "de_DE"

7) 并行执行以提高速度

在每个模拟器UDID上并行运行一个语言:

#!/bin/bash
# parallel-capture.sh

declare -A LOCALE_UDID=(
  ["en-US"]="UDID_EN_US"
  ["de-DE"]="UDID_DE_DE"
  ["fr-FR"]="UDID_FR_FR"
  ["ja-JP"]="UDID_JA_JP"
)

capture_locale() {
  local LOCALE="$1"
  local UDID="$2"
  local LANG="${LOCALE%%-*}"
  local APPLE_LOCALE="${LOCALE/-/_}"

  echo "开始 $LOCALE 在 $UDID"
  xcrun simctl boot "$UDID" || true
  xcrun simctl spawn "$UDID" defaults write NSGlobalDomain AppleLanguages -array "$LANG"
  xcrun simctl spawn "$UDID" defaults write NSGlobalDomain AppleLocale -string "$APPLE_LOCALE"
  xcrun simctl terminate "$UDID" "com.example.app" || true

  asc screenshots capture \
    --bundle-id "com.example.app" \
    --name "home" \
    --udid "$UDID" \
    --output-dir "./screenshots/raw/$LOCALE" \
    --output json

  echo "完成 $LOCALE"
}

for LOCALE in "${!LOCALE_UDID[@]}"; do
  capture_locale "$LOCALE" "${LOCALE_UDID[$LOCALE]}" &
done

wait
echo "所有捕获完成。现在框架..."

或使用带有locale:udid对的xargs

printf "%s
" \
  "en-US:UDID_EN_US" \
  "de-DE:UDID_DE_DE" \
  "fr-FR:UDID_FR_FR" \
  "ja-JP:UDID_JA_JP" | xargs -P 4 -I {} bash -c '
    PAIR="{}"
    LOCALE="${PAIR%%:*}"
    UDID="${PAIR##*:}"
    LANG="${LOCALE%%-*}"
    APPLE_LOCALE="${LOCALE/-/_}"
    xcrun simctl boot "$UDID" || true
    xcrun simctl spawn "$UDID" defaults write NSGlobalDomain AppleLanguages -array "$LANG"
    xcrun simctl spawn "$UDID" defaults write NSGlobalDomain AppleLocale -string "$APPLE_LOCALE"
    xcrun simctl terminate "$UDID" "com.example.app" || true
    asc screenshots capture --bundle-id "com.example.app" --name "home" --udid "$UDID" --output-dir "./screenshots/raw/$LOCALE" --output json
  '

8) 完整多语言管道示例

#!/bin/bash
# full-pipeline-multi-locale.sh

declare -A LOCALE_UDID=(
  ["en-US"]="UDID_EN_US"
  ["de-DE"]="UDID_DE_DE"
  ["fr-FR"]="UDID_FR_FR"
  ["es-ES"]="UDID_ES_ES"
  ["ja-JP"]="UDID_JA_JP"
)

DEVICE="iphone-air"
RAW_DIR="./screenshots/raw"
FRAMED_DIR="./screenshots/framed"

# 步骤1:使用每个模拟器区域设置默认值进行并行捕获
for LOCALE in "${!LOCALE_UDID[@]}"; do
  (
    UDID="${LOCALE_UDID[$LOCALE]}"
    LANG="${LOCALE%%-*}"
    APPLE_LOCALE="${LOCALE/-/_}"

    xcrun simctl boot "$UDID" || true
    xcrun simctl spawn "$UDID" defaults write NSGlobalDomain AppleLanguages -array "$LANG"
    xcrun simctl spawn "$UDID" defaults write NSGlobalDomain AppleLocale -string "$APPLE_LOCALE"
    xcrun simctl terminate "$UDID" "com.example.app" || true

    asc screenshots capture \
      --bundle-id "com.example.app" \
      --name "home" \
      --udid "$UDID" \
      --output-dir "$RAW_DIR/$LOCALE" \
      --output json
    echo "捕获 $LOCALE"
  ) &
done
wait

# 步骤2:并行框架
for LOCALE in "${!LOCALE_UDID[@]}"; do
  (
    asc screenshots frame \
      --input "$RAW_DIR/$LOCALE/home.png" \
      --output-dir "$FRAMED_DIR/$LOCALE" \
      --device "$DEVICE" \
      --output json
    echo "框架 $LOCALE"
  ) &
done
wait

# 步骤3:生成审查(单次运行,聚合所有语言)
asc screenshots review-generate \
  --framed-dir "$FRAMED_DIR" \
  --output-dir "./screenshots/review"

# 步骤4:上传(如果需要,每个语言运行)
for LOCALE in "${!LOCALE_UDID[@]}"; do
  asc screenshots upload \
    --version-localization "LOC_ID_FOR_$LOCALE" \
    --path "$FRAMED_DIR/$LOCALE" \
    --device-type "IPHONE_65" \
    --output json
done