Skip to content

Take the store screenshots during the release, and upload them - #164

Draft
andiwand wants to merge 1 commit into
mainfrom
claude/app-screenshots-metadata-ul8mq3
Draft

Take the store screenshots during the release, and upload them#164
andiwand wants to merge 1 commit into
mainfrom
claude/app-screenshots-metadata-ul8mq3

Conversation

@andiwand

@andiwand andiwand commented Aug 16, 2026

Copy link
Copy Markdown
Member

Stacked on #163, which carries #162. The diff is the one commit; the store copy and the test folder are those two.

The copy beside them is written, so it lives in git and the release uploads what is committed. A screenshot is not written, it is taken: it is worth what the build it came off is worth, and a picture of 1.38 sitting in git through 1.41 is a picture of an app nobody can install. So these are taken during the release run, from the build going out, and handed to deliver from there. Nothing is committed; .gitignore already said as much.

bundle exec fastlane ios screenshots

What a set is

Four pictures per device — the onboarding pages, a text document, a spreadsheet with its sheet tabs, and a presentation — on a 6.9" iPhone and a 13" iPad. Both, because an app that runs on both has to hand in both.

Nine of the eleven store locales are photographed in their own language. hi and sv are given the English set, because the app has no Hindi or Swedish UI either — copied in rather than left out, since a locale deliver uploads nothing for keeps whatever the last release put there.

Nothing is tapped to get there

The way to a document is the document browser, which is Apple's UI in eleven languages and a different tap in each. So the app takes -ODRScreenshot text in Debug builds and puts itself on that screen: one launch per picture, and each waits for the view to say it has something to show rather than for a number of seconds — translating a document takes as long as the simulator takes. ScreenshotMode.swift is the whole of it, and it reads nil in a Release build.

The documents in the pictures are localized too, which is most of what a reader has to show. scripts/make-screenshot-documents.py writes 27 packages of about 1.7 KB, byte for byte reproducible so a rerun that changes no wording leaves no diff, and EXCLUDED_SOURCE_FILE_NAMES = "sample-*" keeps them out of the archive that ships. Their wording is short and plain on purpose — it is a document over someone's shoulder, not copy that has to sell anything.

The release run

A screenshots job beside build rather than behind it: it signs nothing, it just drives simulators, and it takes about as long. It runs on a dry run too, and archives the set as an artifact — which is how to look at the pictures before the store does.

scripts/store-screenshots.py owns what a full set is: which locales, which screens, and the sizes App Store Connect accepts. It reads the size off each PNG rather than trusting the simulator's name, because what a simulator is called changes with every Xcode and how many pixels it has does not; the Fastfile looks for the newest one the runner has and says what is installed instead when it finds none. The listing job then stages the set for both apps and uploads it with the text it already uploads.

Both apps get the same pictures. They are one app built twice, and the one thing that differs on screen — the banner Lite carries — is not in a screenshot either way. The set is taken with the Pro scheme, which links no ad sdk and so cannot raise a consent form in front of the camera.

A listing upload with nothing captured writes the text alone, so fixing a word in a description by hand does not cost a quarter hour of simulators. A release run always captures first, so it always sends both.

Checked

  • the staging script round trips: a full tree passes, a missing shot and a wrong size are both named, hi and sv come out of en-US, and the staged names sort into the order the store shows
  • every generated package is a valid ODF zip — mimetype first and uncompressed, well formed content.xml, styles.xml and manifest
  • Fastfile parses and the simulator resolution picks the right two out of real simctl list devices output
  • both workflows parse, and project.pbxproj reopens with the UI test target, its dependency, its sync group and TEST_TARGET_NAME intact
  • scripts/format.sh now skips SnapshotHelper.swift, which is fastlane's file kept as they ship it (MIT, not our MPL); every other Swift source stays in the check

Two things a Linux container cannot do: compile the UI test target and look at what comes out. So build_test now builds the screenshot target on every pull request — a target that no longer compiles should not wait for a release to say so — and the first dry_run release run is the first look at the pictures. Expect to iterate once on framing there.

One more thing worth a second pair of eyes: the sample documents are worded in nine languages by me, and did not get the translator-and-reviewer pass the store copy in #162 got.

🤖 Generated with Claude Code

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6de18f86bd

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread OpenDocumentReader/DocumentViewController.swift Outdated
@andiwand andiwand changed the title Write the store copy before the release, not during it Take the store screenshots during the release, and upload them Aug 16, 2026
@andiwand
andiwand changed the base branch from main to sync-the-test-folder August 16, 2026 13:43
@andiwand
andiwand force-pushed the claude/app-screenshots-metadata-ul8mq3 branch from 6de18f8 to ab5d603 Compare August 16, 2026 15:09
@andiwand
andiwand force-pushed the sync-the-test-folder branch from 9caa01b to 1ddc055 Compare August 16, 2026 15:09
@andiwand
andiwand force-pushed the claude/app-screenshots-metadata-ul8mq3 branch from ab5d603 to d6323f4 Compare August 16, 2026 15:40
Base automatically changed from sync-the-test-folder to main August 16, 2026 15:49
The store copy is written and committed; the pictures beside it were made
by hand, and the eleven storefronts shared one English set of them.

A screenshot is not written, it is taken: it is worth what the build it
came off is worth, and a picture of 1.38 sitting in git through 1.41 is a
picture of an app nobody can install. So they are taken during the
release run, from the build going out, and handed to deliver from there.
The run archives the set it took, on a dry run too, which is how to look
at them before the store does.

`fastlane ios screenshots` drives the app on a 6.9" iPhone and a 13" iPad
in the nine store locales the app is translated into; hi and sv are given
the English set, because the app has no UI in either. Four pictures each:
the onboarding pages, a text document, a spreadsheet with its sheet tabs,
and a presentation.

Nothing is tapped to get there. The document browser is Apple's UI in
eleven languages, so the app takes `-ODRScreenshot <screen>` in Debug
builds and puts itself on that screen instead - one launch per picture,
each waiting on the view saying it has something to show rather than on a
number of seconds. The documents are localized too, which is most of what
a reader has to show, and small enough to be worth generating:
`scripts/make-screenshot-documents.py` writes twenty-seven packages of
about 1.7 KB, and `EXCLUDED_SOURCE_FILE_NAMES` keeps them out of the
archive that ships.

`scripts/store-screenshots.py` owns what a full set is - which locales,
which screens, and the sizes App Store Connect accepts, read off each
PNG rather than off the simulator's name, since that changes with every
Xcode. The `listing` job stages the set for both apps: they are one app
built twice, and the banner Lite carries is not in a screenshot either
way. A listing upload with nothing captured still writes the text, so
fixing a word does not cost a quarter hour of simulators.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YANh5F8FnQHJUrPL2TiFn4
@andiwand
andiwand force-pushed the claude/app-screenshots-metadata-ul8mq3 branch from d6323f4 to 35e717e Compare August 16, 2026 15:50
@andiwand
andiwand marked this pull request as draft August 16, 2026 16:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants