diff --git a/docs/release.md b/docs/release.md index 07c6e1b16f..328c189f7b 100644 --- a/docs/release.md +++ b/docs/release.md @@ -380,7 +380,8 @@ There is no mobile-release workflow under `.github/workflows`. The EAS GitHub ap Each stable release publishes the screenshots committed under `assets/store-screenshots/output/` (see [its README](../assets/store-screenshots/README.md) for how they are made). To change the store screenshots, re-render and commit them before you tag. - **App Store:** `submit_review` uploads `output/apple/` and `output/apple-ipad/` to the version it submits, replacing that version's `en-US` screenshots. Apple ties screenshots to an app version, so a version that is already live keeps the ones it shipped with. `Resubmit iOS for App Store review` uploads them again. -- **Google Play:** `upload_android_screenshots` runs `fastlane android upload_screenshots` after `submit_android`. It replaces only the phone and 10-inch tablet screenshots, never the listing text or changelogs, and skips images whose checksum already matches. + - When `submit_review` fails with `appStoreVersions … is not in valid state`, the reason is in the API error's `meta.associatedErrors`, which fastlane does not print. Read it with a `POST /v1/reviewSubmissionItems` against the version. A required age-rating question that Apple added, such as `socialMedia`, fails this way; answer it under App Information > Age Rating in App Store Connect, then resubmit. +- **Google Play:** `upload_android_screenshots` runs `fastlane android upload_screenshots` after `submit_android`. It replaces only the `en-US` phone and 10-inch tablet screenshots, never the listing text or changelogs, and skips images whose checksum already matches. The lane stages only `en-US`: supply uploads every locale folder in one edit, and Play rejects F-Droid locales such as `ja`, which fails the whole edit. `Upload Google Play screenshots` reruns the step for the current release without a rebuild. - **F-Droid:** reads the same files as Google Play. `fastlane/metadata/android/en-US/images/phoneScreenshots/` and `tenInchScreenshots/` hold symlinks to the Google renders. `render.mjs` rewrites them on every render, so added or renamed panels reach Google Play and F-Droid as well. Fastlane cannot use the Play key Expo stores for `eas submit`. The Play lane reads its own copy of the same service-account key from the `GOOGLE_PLAY_JSON_KEY` file secret in the EAS `production` environment, and that service account needs the Play Console permission **Manage store presence**. diff --git a/packages/app/.eas/workflows/upload-android-screenshots.yml b/packages/app/.eas/workflows/upload-android-screenshots.yml new file mode 100644 index 0000000000..dbd2fdddca --- /dev/null +++ b/packages/app/.eas/workflows/upload-android-screenshots.yml @@ -0,0 +1,27 @@ +name: Upload Google Play screenshots + +# Standalone re-trigger for the release workflow's Google Play screenshot step. +# Replaces the en-US phone and tablet screenshots with the committed renders, +# without rebuilding or resubmitting the app. + +on: + workflow_dispatch: + inputs: + android_version_code: + type: string + required: false + description: "versionCode of the production release to attach the change to, e.g. 14000. Leave empty when the production track has a single release." + +jobs: + upload_android_screenshots: + name: Upload Google Play screenshots + environment: production + runs_on: macos-medium + steps: + - uses: eas/checkout + - name: Install fastlane + run: bundle install + - name: Upload screenshots + run: | + export ANDROID_VERSION_CODE="${{ inputs.android_version_code }}" + bundle exec fastlane android upload_screenshots diff --git a/packages/app/fastlane/Fastfile b/packages/app/fastlane/Fastfile index 065ca48b7f..f9f11a0e9a 100644 --- a/packages/app/fastlane/Fastfile +++ b/packages/app/fastlane/Fastfile @@ -26,6 +26,22 @@ def stage_app_store_screenshots root end +# Google Play only has en-US screenshots, and some F-Droid locales in +# ANDROID_METADATA are not Play languages (Play rejects "ja"). supply uploads +# every locale folder in one edit, so give it only the en-US images. +def stage_google_play_screenshots + root = Dir.mktmpdir("google-play-screenshots") + images = File.join(ANDROID_METADATA, "en-US/images") + %w[phoneScreenshots tenInchScreenshots].each do |kind| + target = File.join(root, "en-US/images", kind) + FileUtils.mkdir_p(target) + Dir.glob(File.join(images, kind, "*.png")).sort.each do |file| + FileUtils.cp(File.realpath(file), File.join(target, File.basename(file))) + end + end + root +end + platform :ios do desc "Submit the latest TestFlight build to App Store Review" lane :submit_review do @@ -132,7 +148,7 @@ platform :android do supply( package_name: APP_IDENTIFIER, json_key: ENV.fetch("GOOGLE_PLAY_JSON_KEY"), - metadata_path: ANDROID_METADATA, + metadata_path: stage_google_play_screenshots, version_code: version_code.empty? ? nil : version_code.to_i, skip_upload_apk: true, skip_upload_aab: true,