Files
capod/fastlane/generate_screenshots.sh
darken a427fcbf4e chore(screenshots): Commit only English Play Store screenshots
Only en-US screenshots are tracked from now on. The other 67 locales are
generated on demand and gitignored, which drops 35 PNGs and roughly 5 MB from
the repository and stops every screenshot refresh from churning binaries in
five languages nobody reviews.

Play Store still gets the full 68 locales. supply only uploads what is present
under fastlane/metadata/android/<locale>/images/phoneScreenshots/ and retains
whatever was last pushed for locales absent from an upload, so localization is
maintained by an occasional manual regen plus screenshots_only rather than by
every PR.

PlayStoreLocales.kt had been committed since February holding a truncated
four-locale batch slice, left behind when a run was killed before its EXIT trap
restored the file. The next run then copied that slice over its own backup and
faithfully restored the corruption, which is why the remnant survived six
months. It is replaced with a documented en-US placeholder, the generator no
longer emits an annotation nothing references, and the script now refuses to
start when a stale .bak is present instead of clobbering the only good copy.

The refresh runbook is corrected as well: it ended with a checkout that restores
tracked files from the index, which would have reverted the freshly rendered
English screenshots while the store received them, and its upload step is now
gated so a failed upload leaves them staged for a retry rather than committed as
though deployed.
2026-08-25 20:08:48 +02:00

228 lines
6.0 KiB
Bash
Executable File
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.
#!/usr/bin/env bash
set -euo pipefail
# Generates localized Play Store screenshots in batches to work around
# layoutlib ImagePoolImpl memory leak (accumulates rendered images without release).
#
# Usage:
# ./fastlane/generate_screenshots.sh # Full run (all locales, ~12 batches)
# ./fastlane/generate_screenshots.sh --smoke # Smoke test (6 locales, 1 batch)
# ./fastlane/generate_screenshots.sh --batch-size 10 # Custom batch size
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
LOCALES_FILE="$PROJECT_DIR/app/src/screenshotTest/kotlin/eu/darken/capod/screenshots/PlayStoreLocales.kt"
REF_DIR="$PROJECT_DIR/app/src/screenshotTestGplayDebug/reference"
# Default batch size — 2 locales × 7 composables = 14 renders per batch.
# Kept small to avoid layoutlib OOM (leaks ~10MB per rendered image at 1080p).
BATCH_SIZE=2
SMOKE=false
while [[ $# -gt 0 ]]; do
case "$1" in
--smoke) SMOKE=true; shift ;;
--batch-size) BATCH_SIZE="$2"; shift 2 ;;
*) echo "Unknown option: $1"; exit 1 ;;
esac
done
# Each entry: "android_locale:fastlane_name"
ALL_LOCALES=(
"en:en-US"
"af:af"
"am:am"
"ar:ar"
"az:az-AZ"
"be:be"
"bg:bg"
"bn-rBD:bn-BD"
"ca:ca"
"cs:cs-CZ"
"da:da-DK"
"de:de-DE"
"el:el-GR"
"es:es-ES"
"es-rMX:es-419"
"et-rEE:et"
"eu-rES:eu-ES"
"fa:fa"
"fi:fi-FI"
"fil:fil"
"fr:fr-FR"
"gl-rES:gl-ES"
"hi-rIN:hi-IN"
"hr:hr"
"hu:hu-HU"
"hy-rAM:hy-AM"
"in:id"
"is:is-IS"
"it:it-IT"
"iw:iw-IL"
"ja:ja-JP"
"ka-rGE:ka-GE"
"km-rKH:km-KH"
"kn-rIN:kn-IN"
"ko:ko-KR"
"ky-rKG:ky-KG"
"lo-rLA:lo-LA"
"lt:lt"
"lv:lv"
"mk-rMK:mk-MK"
"ml-rIN:ml-IN"
"mn-rMN:mn-MN"
"mr-rIN:mr-IN"
"ms:ms"
"my-rMM:my-MM"
"nb:no-NO"
"ne-rNP:ne-NP"
"nl:nl-NL"
"pl:pl-PL"
"pt:pt-PT"
"pt-rBR:pt-BR"
"rm:rm"
"ro:ro"
"ru:ru-RU"
"sk:sk"
"sl:sl"
"sr:sr"
"sv:sv-SE"
"sw:sw"
"ta-rIN:ta-IN"
"te-rIN:te-IN"
"th:th"
"tr:tr-TR"
"uk:uk"
"vi:vi"
"zh-rCN:zh-CN"
"zh-rHK:zh-HK"
"zh-rTW:zh-TW"
)
SMOKE_LOCALES=(
"en:en-US"
"de:de-DE"
"ja:ja-JP"
"ar:ar"
"zh-rCN:zh-CN"
"pt-rBR:pt-BR"
)
if $SMOKE; then
LOCALES=("${SMOKE_LOCALES[@]}")
BATCH_SIZE=${#LOCALES[@]} # Single batch for smoke
else
LOCALES=("${ALL_LOCALES[@]}")
fi
TOTAL=${#LOCALES[@]}
NUM_BATCHES=$(( (TOTAL + BATCH_SIZE - 1) / BATCH_SIZE ))
echo "=== Localized Screenshot Generation ==="
echo "Locales: $TOTAL | Batch size: $BATCH_SIZE | Batches: $NUM_BATCHES"
echo ""
# A leftover .bak means a previous run died before its trap restored the file: the real source is
# in the .bak and copying over it here would destroy the only good copy.
if [[ -e "$LOCALES_FILE.bak" ]]; then
echo "ERROR: Stale backup found: $LOCALES_FILE.bak"
echo "A previous run was interrupted. Restore it first:"
echo " mv \"$LOCALES_FILE.bak\" \"$LOCALES_FILE\""
exit 1
fi
# Back up the original file
cp "$LOCALES_FILE" "$LOCALES_FILE.bak"
trap 'mv "$LOCALES_FILE.bak" "$LOCALES_FILE"; echo "Restored original PlayStoreLocales.kt"' EXIT
# Clean reference directory from previous runs
rm -rf "$REF_DIR"
echo "Cleaned reference directory"
generate_locales_file() {
local -n batch_locales=$1
local file="$2"
cat > "$file" << 'HEADER'
package eu.darken.capod.screenshots
import android.content.res.Configuration
import androidx.compose.ui.tooling.preview.Preview
/**
* Multi-preview annotation generating one preview per Play Store-supported locale (light mode).
* Each [name] is the fastlane metadata directory name for direct use in the copy script.
*/
HEADER
# Light annotations
for entry in "${batch_locales[@]}"; do
local locale="${entry%%:*}"
local name="${entry##*:}"
echo "@Preview(locale = \"$locale\", name = \"$name\", device = DS)" >> "$file"
done
echo "annotation class PlayStoreLocales" >> "$file"
echo "" >> "$file"
# Dark annotations
echo "/**" >> "$file"
echo " * Same locales but with night mode enabled for dark theme screenshots." >> "$file"
echo " */" >> "$file"
for entry in "${batch_locales[@]}"; do
local locale="${entry%%:*}"
local name="${entry##*:}"
echo "@Preview(locale = \"$locale\", name = \"$name\", device = DS, uiMode = Configuration.UI_MODE_NIGHT_YES)" >> "$file"
done
echo "annotation class PlayStoreLocalesDark" >> "$file"
echo "" >> "$file"
}
for (( batch=0; batch < NUM_BATCHES; batch++ )); do
start=$(( batch * BATCH_SIZE ))
end=$(( start + BATCH_SIZE ))
if (( end > TOTAL )); then
end=$TOTAL
fi
# Extract batch slice
BATCH_SLICE=("${LOCALES[@]:$start:$((end - start))}")
batch_num=$(( batch + 1 ))
echo "--- Batch $batch_num/$NUM_BATCHES (locales $((start+1))-$end of $TOTAL) ---"
# Generate locales file for this batch
generate_locales_file BATCH_SLICE "$LOCALES_FILE"
# Stop daemon to release memory from previous batch
echo "Stopping Gradle daemon..."
cd "$PROJECT_DIR"
./gradlew --stop 2>/dev/null || true
# Run screenshot generation
echo "Generating screenshots..."
if ! ./gradlew updateGplayDebugScreenshotTest --no-daemon 2>&1; then
echo "ERROR: Batch $batch_num failed! Check output above."
echo "Generated images so far are preserved in: $REF_DIR"
exit 1
fi
count=$(find "$REF_DIR" -name "*.png" 2>/dev/null | wc -l)
echo "Batch $batch_num complete. Total images so far: $count"
echo ""
done
# Count final results
FINAL_COUNT=$(find "$REF_DIR" -name "*.png" 2>/dev/null | wc -l)
EXPECTED=$(( TOTAL * 7 )) # 7 composables per locale
echo "=== Generation Complete ==="
echo "Generated: $FINAL_COUNT images (expected: $EXPECTED)"
if (( FINAL_COUNT != EXPECTED )); then
echo "WARNING: Count mismatch! Some screenshots may be missing."
echo "Check $REF_DIR for details."
fi
echo ""
echo "Next step: run ./fastlane/copy_screenshots.sh to sort into fastlane directories."