fix(mobile): fail fast when iOS App Store train is closed (#6633)
Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
parent
3f39d7548b
commit
584cec78c3
|
|
@ -10,7 +10,7 @@ on:
|
|||
workflow_dispatch:
|
||||
inputs:
|
||||
bump_patch_version:
|
||||
description: 'Bump the iOS marketing version patch number before release'
|
||||
description: 'Bump the iOS marketing version patch number before release. Tick this after a version has shipped to the App Store (the release fails fast if the current version''s train is already closed).'
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
|
|
|||
|
|
@ -30,6 +30,20 @@ BUNDLE_ID = "com.stably.orca.mobile"
|
|||
TESTFLIGHT_GROUPS = ["peeps"].freeze
|
||||
DEFAULT_TESTFLIGHT_CHANGELOG = "Latest Orca Mobile updates and fixes.".freeze
|
||||
|
||||
# App Store version states in which the version "train" is terminally closed to
|
||||
# new TestFlight build uploads (altool rejects with 90186 "train ... is
|
||||
# closed"). Only approved/released/removed states qualify: a version that is
|
||||
# merely IN_REVIEW / WAITING_FOR_REVIEW / PROCESSING_FOR_APP_STORE still accepts
|
||||
# TestFlight builds, so bumping on those would break normal beta iteration.
|
||||
CLOSED_APP_STORE_STATES = %w[
|
||||
READY_FOR_SALE
|
||||
PENDING_DEVELOPER_RELEASE
|
||||
PENDING_APPLE_RELEASE
|
||||
REPLACED_WITH_NEW_VERSION
|
||||
REMOVED_FROM_SALE
|
||||
DEVELOPER_REMOVED_FROM_SALE
|
||||
].freeze
|
||||
|
||||
def app_store_connect_api_key_from_env
|
||||
app_store_connect_api_key(
|
||||
key_id: ENV.fetch("ASC_KEY_ID"),
|
||||
|
|
@ -71,6 +85,24 @@ def resolve_requested_version(options, config)
|
|||
truthy_option?(options[:bump_patch]) ? bump_patch_version(current_version) : current_version
|
||||
end
|
||||
|
||||
# Returns true when `version`'s App Store train is closed to new build uploads.
|
||||
# `app` is a Spaceship::ConnectAPI::App the caller looks up (nil if lookup
|
||||
# failed). On a nil app or any API error, degrade to "open": we then proceed as
|
||||
# before this check existed — the upload either succeeds or fails with the same
|
||||
# 90186 we have always seen, never worse than today's behavior.
|
||||
def version_train_closed?(app, version)
|
||||
return false unless app
|
||||
|
||||
app
|
||||
.get_app_store_versions(filter: { versionString: version })
|
||||
.any? { |app_store_version| CLOSED_APP_STORE_STATES.include?(app_store_version.app_store_state) }
|
||||
rescue StandardError => error
|
||||
# Loud, not silent: a swallowed error here un-fixes the 90186 guard, so the
|
||||
# degraded run must be visible rather than buried.
|
||||
UI.error("Could not determine App Store state for #{version} (#{error.message}); assuming open and proceeding.")
|
||||
false
|
||||
end
|
||||
|
||||
def testflight_changelog
|
||||
changelog = ENV.fetch("TESTFLIGHT_CHANGELOG", "").strip
|
||||
changelog.empty? ? DEFAULT_TESTFLIGHT_CHANGELOG : changelog
|
||||
|
|
@ -83,6 +115,26 @@ platform :ios do
|
|||
config = load_mobile_app_config
|
||||
version = resolve_requested_version(options, config)
|
||||
|
||||
# Fail fast (seconds) if the resolved version's App Store train is already
|
||||
# closed: Apple would otherwise reject the upload ~20 min later with 90186.
|
||||
# Bumping the version is left to the human (the bump_patch input or a
|
||||
# "Prepare mobile X" commit) so the marketing version stays a deliberate,
|
||||
# release-notes-bearing decision rather than something CI invents.
|
||||
app =
|
||||
begin
|
||||
Spaceship::ConnectAPI::App.find(BUNDLE_ID)
|
||||
rescue StandardError => error
|
||||
UI.error("Could not look up App Store app #{BUNDLE_ID} (#{error.message}); skipping closed-train check.")
|
||||
nil
|
||||
end
|
||||
if version_train_closed?(app, version)
|
||||
UI.user_error!(
|
||||
"iOS version #{version} is already submitted/released on the App Store and cannot accept " \
|
||||
"new builds. Re-dispatch with bump_patch_version: true (or a higher release_version), " \
|
||||
"or land a \"Prepare mobile <version>\" commit.",
|
||||
)
|
||||
end
|
||||
|
||||
latest_build_number = latest_testflight_build_number(
|
||||
api_key: api_key,
|
||||
app_identifier: BUNDLE_ID,
|
||||
|
|
|
|||
Loading…
Reference in New Issue