61 lines
5.2 KiB
Markdown
61 lines
5.2 KiB
Markdown
---
|
|
name: migrate-from-fastlane
|
|
description: Move a mobile app or game from fastlane (deliver, supply, snapshot / screengrab, Appfile, Deliverfile) to storebound with `storebound import fastlane` - store ids, App Store and Google Play listing text in every language, categories, review notes, Play icon and feature graphic, screenshots as frames - without copying keys, team ids or the App Review demo account. Use when a project has a fastlane/ (or ios/fastlane, android/fastlane) folder, when the user says "we use fastlane", "migrate from fastlane", or before running `storebound init` in such a project.
|
|
---
|
|
|
|
# Migrate from fastlane
|
|
|
|
CLI: `storebound import fastlane [--dir fastlane] [--out .] [--profile app|game|subscription-app] [--dry]` (MCP:
|
|
`import_fastlane`, `dry_run` defaults to true). It only reads fastlane's files and never runs Ruby. Default `--dir`:
|
|
every one of `fastlane/`, `ios/fastlane/`, `android/fastlane/` that exists; pass several with commas.
|
|
|
|
## Steps
|
|
1. `storebound import fastlane --dry`. Show the owner the plan and the report. The report has five parts:
|
|
**mapped** (source -> target), **not mapped** (with where each item goes by hand), **keys, accounts and personal
|
|
data** (named only), **placeholders** and **warnings** (missing fields, store limits, unknown locale codes).
|
|
2. With the owner's yes, run it without `--dry`. Nothing that exists is overwritten:
|
|
- a text file that exists gets a `<name>.imported.<ext>` copy next to it. Compare with
|
|
`git diff --no-index store/listing.md store/listing.imported.md` and merge what the owner wants;
|
|
- an image that exists is kept.
|
|
3. `storebound init --profile <same profile>`: it adds the remaining templates (declarations, App Privacy, Data
|
|
safety CSV, privacy policy, `.storebound/credentials.json`) and keeps the imported files.
|
|
4. Secrets, done by the owner (never in chat, never in the config; AGENTS.md rules 4 and 9):
|
|
- Play `json_key_file`: move the key into `.storebound/`, set `PLAY_SERVICE_ACCOUNT` to its path. If the key was
|
|
ever committed, rotate it in Google Cloud.
|
|
- `app_store_connect_api_key` in the Fastfile: `ASC_KEY_ID`, `ASC_ISSUER_ID`, `ASC_P8` (the .p8 path).
|
|
- `review_information/` contact and demo account: `reviewContact` and `reviewDemoAccount` in
|
|
`.storebound/credentials.json`. The import sets `reviewAccess.signInRequired: true` when fastlane had a demo user.
|
|
5. Replace the placeholders the report lists (`app.contactEmail` always: the App Review contact is personal data and
|
|
is not used for it).
|
|
6. `storebound check`, then `storebound shots capture --source folder` to check the imported frames.
|
|
|
|
## What maps where
|
|
| fastlane | storebound |
|
|
|---|---|
|
|
| Appfile `app_identifier` / `package_name` | `apple.bundleId` / `play.packageName` |
|
|
| deliver locale folders + supply language folders | `languages[]`, one entry per language with both codes (`tr` + `tr-TR`, `zh-Hans` + `zh-CN`, `he` + `iw-IL`, `es-MX` + `es-419`) |
|
|
| `metadata/<locale>/name, subtitle, promotional_text, keywords, description, release_notes` (+ `default/`) | `store/appstore.md` (`name`, `subtitle`, `promotionalText`, `keywords` without spaces after commas, `description`, `whatsNew`) |
|
|
| `privacy_url`, `support_url`, `marketing_url` | `app.privacyPolicyUrl`, `app.supportUrl`, `app.marketingUrl` + `app.website` (one for all languages) |
|
|
| `copyright.txt`, `primary_category.txt` ... | `app.copyright`, `apple.info.categories` (`GAMES` picks the game profile) |
|
|
| `review_information/notes.txt` | `apple.info.reviewNotes` |
|
|
| `metadata/android/<lang>/title, short_description, full_description` | `store/listing.md` |
|
|
| newest `changelogs/<versionCode>.txt` (else `default.txt`) | Play "What's new" |
|
|
| `video.txt` (YouTube) | `play.video` |
|
|
| `images/icon.png`, `images/featureGraphic.*` | `store/icons/play-512.png` (`play.icon`), `store/renders/<lang>/feature/1024x500.*` |
|
|
| `screenshots/<locale>/` (largest iPhone set, iPad), else `phoneScreenshots/`, `tenInchScreenshots/` | `store/shots/frames/<lang>/<phone\|tablet>/NN.png`, scenes `shot-01`..., `shots.capture.source: 'folder'`, empty copy in `store/shots/copy.json` |
|
|
|
|
## Not imported (on purpose)
|
|
- `submit_for_review`, `automatic_release`, `reject_if_possible`: the owner submits and releases (AGENTS.md rule 1);
|
|
phased release is `release-management`.
|
|
- `price_tier`: products and the prices CSV (`store-iap-setup`). Age rating config: `store-declarations`.
|
|
Export compliance: `export-compliance` (`apple.usesNonExemptEncryption` stays commented out).
|
|
- Lanes, `match`, `gym` / `gradle`: building and signing stay where they are; storebound has no lanes.
|
|
- Ruby logic (`for_platform`, `for_lane`, `ENV[...]`, interpolation): reported by key and line; set those in storebound.config.ts.
|
|
- Promo graphic, TV banner, TV / Wear screenshots, Apple TV privacy policy, Korean trade representative contact:
|
|
consoles.
|
|
|
|
## Screenshots
|
|
fastlane screenshots are often finished store art (framed, captioned). The import puts them in the frames folder so
|
|
`shots render` can rebuild them from one source in every size; full-screen captures usually need the status bar cut
|
|
(`shots capture --source folder` reports the aspect ratio per frame). If the owner prefers to keep the finished art,
|
|
leave the copy empty and upload as before. JPEG screenshots are listed, not copied (frames are PNG).
|