TheNoiseClock/scripts/run-screenshot-matrix.sh

175 lines
5.1 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
WORKSPACE_ROOT="$(cd "${PROJECT_ROOT}/.." && pwd)"
PROJECT_PATH="${PROJECT_ROOT}/TheNoiseClock.xcodeproj"
SCHEME="${SCHEME:-TheNoiseClock}"
TEST_IDENTIFIER="${TEST_IDENTIFIER:-TheNoiseClockUITests/TheNoiseClockUITests/testAppStoreScreenshots_iPhone69}"
RUNTIME_ID="${RUNTIME_ID:-com.apple.CoreSimulator.SimRuntime.iOS-26-2}"
OUTPUT_ROOT="${OUTPUT_ROOT:-${WORKSPACE_ROOT}/Screenshots}"
EXPECTED_COUNT=5
expected_files=(
"01-clock-view-portrait.png"
"02-clock-view-landscape.png"
"03-alarms-view-portrait.png"
"04-noise-view-portrait.png"
"05-clock-settings-portrait.png"
)
locales=(
"fr-CA|fr|CA"
"es-MX|es|MX"
)
devices=(
"iPhone-6.3|AppStore iPhone 17 Pro 26.2|com.apple.CoreSimulator.SimDeviceType.iPhone-17-Pro"
"iPhone-6.5|AppStore iPhone 11 Pro Max 26.2|com.apple.CoreSimulator.SimDeviceType.iPhone-11-Pro-Max"
"iPhone-6.9|AppStore iPhone 17 Pro Max 26.2|com.apple.CoreSimulator.SimDeviceType.iPhone-17-Pro-Max"
"iPad-13|AppStore iPad Pro 13-inch (M5) 26.2|com.apple.CoreSimulator.SimDeviceType.iPad-Pro-13-inch-M5-12GB"
)
simctl_json() {
xcrun simctl list devices available -j
}
find_sim_udid() {
local runtime_id="$1"
local name="$2"
simctl_json | jq -r --arg runtime_id "$runtime_id" --arg name "$name" '
.devices[$runtime_id][]? | select(.isAvailable == true and .name == $name) | .udid
' | head -n1
}
ensure_simulator() {
local name="$1"
local device_type="$2"
local runtime_id="$3"
local udid
udid="$(find_sim_udid "$runtime_id" "$name")"
if [[ -n "$udid" ]]; then
echo "$udid"
return 0
fi
udid="$(xcrun simctl create "$name" "$device_type" "$runtime_id")"
echo "$udid"
}
validate_output_folder() {
local folder="$1"
local png_count
png_count="$(find "$folder" -maxdepth 1 -name '*.png' | wc -l | tr -d ' ')"
if [[ "$png_count" -ne "$EXPECTED_COUNT" ]]; then
echo "Expected ${EXPECTED_COUNT} screenshots in ${folder}, found ${png_count}." >&2
return 1
fi
local missing=0
for file_name in "${expected_files[@]}"; do
if [[ ! -f "${folder}/${file_name}" ]]; then
echo "Missing ${folder}/${file_name}" >&2
missing=1
fi
done
if [[ "$missing" -ne 0 ]]; then
return 1
fi
}
export_attachments_to_output_folder() {
local result_bundle="$1"
local folder="$2"
local attachments_tmp
attachments_tmp="$(mktemp -d "/tmp/noiseclock-attachments.XXXXXX")"
xcrun xcresulttool export attachments \
--path "$result_bundle" \
--output-path "$attachments_tmp" >/dev/null
local manifest_path="${attachments_tmp}/manifest.json"
if [[ ! -f "$manifest_path" ]]; then
echo "Missing attachment manifest at ${manifest_path}" >&2
rm -rf "$attachments_tmp"
return 1
fi
local missing=0
for file_name in "${expected_files[@]}"; do
local base_name="${file_name%.png}"
local exported_name
exported_name="$(jq -r --arg base_name "$base_name" '
[.[].attachments[]?
| select((.suggestedHumanReadableName // "") | startswith($base_name + "_"))
| .exportedFileName][0] // empty
' "$manifest_path")"
if [[ -z "$exported_name" || ! -f "${attachments_tmp}/${exported_name}" ]]; then
echo "Missing exported attachment for ${file_name} in ${result_bundle}" >&2
missing=1
continue
fi
cp "${attachments_tmp}/${exported_name}" "${folder}/${file_name}"
done
if [[ "$missing" -ne 0 ]]; then
rm -rf "$attachments_tmp"
return 1
fi
rm -rf "$attachments_tmp"
}
echo "Using project: ${PROJECT_PATH}"
echo "Using scheme: ${SCHEME}"
echo "Output root: ${OUTPUT_ROOT}"
echo "Runtime: ${RUNTIME_ID}"
mkdir -p "$OUTPUT_ROOT"
for locale_entry in "${locales[@]}"; do
IFS='|' read -r locale_folder language_code region_code <<< "$locale_entry"
echo ""
echo "=== Locale ${locale_folder} (${language_code}-${region_code}) ==="
for device_entry in "${devices[@]}"; do
IFS='|' read -r device_folder sim_name device_type <<< "$device_entry"
echo "--- Device ${device_folder} (${sim_name}) ---"
udid="$(ensure_simulator "$sim_name" "$device_type" "$RUNTIME_ID")"
output_dir="${OUTPUT_ROOT}/${locale_folder}/${device_folder}"
result_bundle="/tmp/TheNoiseClock-${locale_folder}-${device_folder}.xcresult"
rm -rf "$result_bundle"
mkdir -p "$output_dir"
rm -f "${output_dir}"/*.png
xcrun simctl shutdown "$udid" >/dev/null 2>&1 || true
xcrun simctl erase "$udid" >/dev/null 2>&1 || true
SCREENSHOT_OUTPUT_DIR="$output_dir" xcodebuild \
-project "$PROJECT_PATH" \
-scheme "$SCHEME" \
-destination "platform=iOS Simulator,id=${udid}" \
-testLanguage "$language_code" \
-testRegion "$region_code" \
-only-testing:"${TEST_IDENTIFIER}" \
-parallel-testing-enabled NO \
-resultBundlePath "$result_bundle" \
test
export_attachments_to_output_folder "$result_bundle" "$output_dir"
validate_output_folder "$output_dir"
echo "Saved ${EXPECTED_COUNT} screenshots to ${output_dir}"
done
done
echo ""
echo "Screenshot matrix completed successfully."