Files
pleno-vue/.github/workflows/app-store-readiness.yml
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

73 lines
2.1 KiB
YAML

name: App Store Readiness
on:
pull_request:
push:
branches: [master]
paths:
- "fastlane/**"
- "ios/**"
- "scripts/mobile/**"
- "Gemfile*"
workflow_dispatch:
permissions:
contents: read
concurrency:
group: app-store-readiness-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
validate:
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- name: Checkout repository
uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5
with:
persist-credentials: false
- name: Setup Node.js
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5
with:
node-version: 22
- name: Setup Ruby
uses: ruby/setup-ruby@003a5c4d8d6321bd302e38f6f0ec593f77f06600 # v1
with:
ruby-version: "3.3"
- name: Resolve the pinned Fastlane dependency graph
run: bundle lock
- name: Check the committed Fastlane dependency lock
id: fastlane-lock
continue-on-error: true
run: test -z "$(git status --porcelain -- Gemfile.lock)"
- name: Preserve a generated lock for review
if: steps.fastlane-lock.outcome == 'failure'
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: generated-fastlane-lock
path: Gemfile.lock
if-no-files-found: error
retention-days: 1
- name: Require a current committed Fastlane dependency lock
if: steps.fastlane-lock.outcome == 'failure'
run: |
echo 'Gemfile.lock is missing or stale. Download generated-fastlane-lock and commit it.' >&2
exit 1
- name: Validate App Store metadata and available assets
run: node scripts/mobile/validate-app-store.mjs
- name: Validate JavaScript syntax
run: |
node --check scripts/mobile/validate-app-store.mjs
node --check scripts/mobile/app-store-connect.mjs
node --check scripts/mobile/create-ios-release-manifest.mjs
node scripts/mobile/app-store-connect.mjs self-test-jwt