Files
pleno-vue/fastlane/Fastfile
T
Jeppe B 88eda43560 Automate signed iOS App Store releases (#192)
## What changed

- adds production iOS identity, localized storefront metadata, native
privacy declarations, App Store-safe artwork, and account-deletion UX
- mirrors the live Danish Google Play title, short description, and long
description in the App Store metadata source
- generates Android launcher/store icons from the opaque iOS marketing
master so both platforms use the same white background
- adds guarded GitHub Actions workflows for storefront readiness,
credential health, signed TestFlight uploads, and App Store candidate
preparation
- adds pinned Fastlane configuration with a committed dependency lock,
release manifest tooling, and an operational App Store runbook
- preserves the upstream iOS safe-area implementation while retaining
opaque App Store icon assets

## Why

The repository previously supported development-signed device bundles
but had no production App Store identity, reproducible storefront source
of truth, or protected signed-release pipeline. Apple also requires
in-app account deletion for apps that support account creation. The
Android icon master was transparent, which rendered as black on dark
store/device surfaces.

## Impact

Automation remains fail-closed behind
`APP_STORE_AUTOMATION_ENABLED=false`. No build can upload to TestFlight
or change App Store metadata until the switch is deliberately enabled
after merge and the remaining release gates are satisfied.

## Validation

- focused App Store, iOS icon, and cross-platform icon-background tests
pass
- every generated Android store/launcher icon is opaque with pure-white
corners; iOS marketing artwork is checked the same way
- Android icon drift check passes for all 19 generated files
- production Vite build and the broader focused release checks completed
successfully
- storefront metadata is valid; only the two expected screenshot-set
warnings remain
- App Store Readiness is green at head `4445fecc`
- Apple Distribution certificate and App Store profile were
independently verified for `HP3FJ4GVL7.io.truckwash.app`
- live App Store Connect API authentication succeeded for app
`6792777794`
- App Store record, free Denmark-only availability, and automatic
`Internal QA` TestFlight group are configured
- EU trader status, Content Rights, 4+ age rating, and the published App
Privacy label are completed in App Store Connect
- iPhone and iPad accessibility declarations are configured honestly as
pre-release drafts

## Remaining external gates

- reviewed iPhone and iPad screenshot sets are still required
- an App Review login must be supplied without creating or exposing
customer credentials
- the first signed TestFlight candidate must run after merge and
deliberate automation enablement
2026-07-20 17:59:43 +02:00

56 lines
1.8 KiB
Ruby

default_platform(:ios)
def app_store_api_key
issuer_id = ENV["APP_STORE_CONNECT_ISSUER_ID"].to_s.strip
app_store_connect_api_key(
key_id: ENV.fetch("APP_STORE_CONNECT_API_KEY_ID"),
issuer_id: issuer_id.empty? ? nil : issuer_id,
key_content: ENV.fetch("APP_STORE_CONNECT_API_PRIVATE_KEY_BASE64"),
is_key_content_base64: true,
duration: 1200,
in_house: false
)
end
platform :ios do
desc "Validate and upload the signed IPA, then wait for App Store Connect processing"
lane :upload_internal do
api_key = app_store_api_key
upload_to_testflight(
api_key: api_key,
app_identifier: ENV.fetch("IOS_BUNDLE_ID"),
ipa: ENV.fetch("IOS_IPA_PATH"),
changelog: ENV.fetch("TESTFLIGHT_WHAT_TO_TEST", "Automatisk intern build fra verificeret master."),
distribute_external: false,
notify_external_testers: false,
skip_submission: true,
skip_waiting_for_build_processing: false,
wait_processing_interval: 30,
reject_build_waiting_for_review: false
)
end
desc "Create/update the Denmark App Store candidate without submitting it for review"
lane :prepare_candidate do
api_key = app_store_api_key
deliver(
api_key: api_key,
app_identifier: ENV.fetch("IOS_BUNDLE_ID"),
app_version: ENV.fetch("IOS_MARKETING_VERSION"),
build_number: ENV.fetch("IOS_BUILD_NUMBER"),
metadata_path: "fastlane/metadata",
screenshots_path: "fastlane/screenshots",
skip_binary_upload: true,
skip_metadata: false,
skip_screenshots: false,
overwrite_screenshots: true,
force: true,
submit_for_review: false,
automatic_release: false,
phased_release: false,
run_precheck_before_submit: false,
precheck_include_in_app_purchases: false
)
end
end