I added a preflight gate to an iOS + watchOS app build this week because the build script had a small but annoying property: it mutated the repo before it proved the repo was safe to build.

The script stamps CFBundleVersion with a timestamp before generating the Xcode project and archiving for TestFlight. That is useful because every upload gets a monotonically increasing build number.

It is also exactly the wrong thing to do before quality checks.

If formatting or tests fail after that stamp, the working tree is now dirty for a reason unrelated to the change I was trying to ship. Small thing, but this is how build scripts become suspicious. You run them, they fail, then you have to separate your actual diff from the build system's leftovers.

So I moved the build into a fail-fast shape: