metactl — App Review metadata
metactl is the metadata sibling of iapctl: same plan/apply idempotent model,
same env-based auth, same machine-readable report. It provisions App Review
text metadata from a single metadata.yaml.
metactl plan -config metadata.yaml # preview — no published writesmetactl apply -config metadata.yaml # write metadata (idempotent)metactl plan -config metadata.yaml -o jsonWhat it manages
Section titled “What it manages”Per locale and per store:
| Field | App Store | Google Play |
|---|---|---|
| name / title | ✓ | ✓ |
| subtitle | ✓ | — |
| short description | — | ✓ (≤80) |
| description / full description | ✓ (≤4000) | ✓ (≤4000) |
| keywords | ✓ (≤100) | — |
| promotional text | ✓ (≤170) | — |
| what’s new | ✓ | — |
| support / marketing / privacy URL | ✓ | — |
Plus the review detail (contact, demo account, notes), the age rating
(App Store — preset: none or a full declarations passthrough), the App Store
category (primary/secondary), and the Play store-listing contact block.
It also uploads store-listing screenshots (both stores) and the Google Play feature graphic + icon — placed, not generated. See Screenshots & graphics.
When appStoreVersion is set and that version doesn’t exist yet, apply creates
it (platform from platform, default IOS). metactl does not pick a build.
Out of scope (manual): build selection + Submit-for-Review, Play content-rating questionnaire, and Data Safety.
metadata.yaml (shape)
Section titled “metadata.yaml (shape)”appName: SonirbundleId: app.sonir.apppackageName: app.sonir.appappStoreVersion: "1.0" # version to edit; created if missing (apply)platform: IOS # platform if metactl creates the version (default IOS)primaryCategory: MUSIC # App Store appCategory id (Play category: Console only)secondaryCategory: UTILITIES
review: # iOS App Review contact / demo / notes contactEmail: review@example.com demoAccountRequired: false notes: "Tap Measure to start."
playContact: # Play store-listing contact (details) email: support@example.com website: https://sonir.app
defaultLanguage: ja-JPlocales: - locale: ja # ASC "ja"; Play normalized to ja-JP name: "Sonir" subtitle: "空気録音 × 音響測定" shortDescription: "録って、測って、比べる。" description: "…" keywords: "録音,音響,RTA" supportUrl: https://sonir.app/supportDrift detection
Section titled “Drift detection”Like iapctl, metactl plan flags drift (~) when text was changed in a
console. It reports which fields drifted (it does not echo the full text):
~ localization sonir [ja] — changed: description,keywords~ details app.sonir.app — changed: contactEmailThe same exit codes apply (-detailed-exitcode: 0 clean / 2 pending-or-drift
/ 1 error; -drift-only for cron). See Drift detection.
GitOps & cron (reuse the same action)
Section titled “GitOps & cron (reuse the same action)”Everything on the GitOps and Drift detection pages works
for metadata — just point the action at metactl + metadata.yaml:
- uses: storectl-dev/storectl/.github/actions/storectl-comment@v1 with: tool: metactl command: plan # or apply config: metadata.yaml env: { /* your ASC / Play secrets */ }Full flag and JSON details are in the CLI reference.
Full example
Section titled “Full example”A complete metadata.yaml — text metadata, review/contact blocks, and
screenshots, across four locales. Copy it and swap in your values.
# metactl desired-state. Drives App Store Connect + Google Play store listings.appName: SonirbundleId: app.sonir.app # App Store bundle idpackageName: app.sonir.app # Google Play package nameappStoreVersion: "1.0" # version to edit; created if missing (apply)platform: IOS # platform if metactl creates the versionprimaryCategory: MUSIC # App Store appCategory id (App Store only)secondaryCategory: UTILITIES
review: # iOS App Review contact / demo / notes contactFirstName: Taiki contactLastName: Noda contactPhone: "+81-90-0000-0000" contactEmail: review@example.com demoAccountRequired: false notes: "Tap Measure to start. Mic permission required for recording."
ageRating: # only "none" supported; omit to leave untouched preset: none
playContact: # Play store-listing contact (details) email: support@example.com phone: "" website: https://sonir.app/
defaultLanguage: ja-JP # Play defaultLanguage
# Base dir for the screenshot paths below (render the PNGs with your own tooling;# metactl only uploads them). Relative to the current directory.screenshotsDir: ./screenshots
locales: - locale: ja # ASC "ja"; Play normalized to ja-JP name: "Sonir" # name/title (<=30) subtitle: "空気録音 × 音響測定" # ASC only (<=30) shortDescription: "空気録音で測る、部屋とオーディオ。" # Play only (<=80) description: "部屋に流れた音をマイクで録って測る測定アプリ。" # ASC desc / Play full (<=4000) keywords: "オーディオ,測定,RTA,SPL,残響,録音" # ASC only (<=100) promotionalText: "今すぐ部屋の周波数特性を可視化。" # ASC only (<=170) whatsNew: "初回リリース。" # ASC only (<=4000) supportUrl: https://sonir.app/ja/support marketingUrl: https://sonir.app/ privacyPolicyUrl: https://sonir.app/ja/privacy # device key -> ordered file list (display order). See the Screenshots page. screenshots: iphone69: [iphone69/ja/01-record.png, iphone69/ja/02-measure.png] ipad13: [ipad13/ja/01-measure.png] play_phone: [play_phone/ja/01-record.png, play_phone/ja/02-measure.png] play_tablet: [play_tablet/ja/01-measure.png] playGraphics: # Google Play feature graphic + icon (Play-only) featureGraphic: feature/ja/feature.png # 1024x500 JPEG / 24-bit PNG icon: icon/ja/icon.png # 512x512 32-bit PNG
- locale: en-US name: "Sonir" subtitle: "Air recording × acoustics" shortDescription: "Measure rooms and audio by recording the air." description: "Sonir measures the sound in your room by recording it with a mic." keywords: "audio,measurement,RTA,SPL,reverb,recording" promotionalText: "Visualize your room's frequency response now." whatsNew: "Initial release." supportUrl: https://sonir.app/en/support marketingUrl: https://sonir.app/ privacyPolicyUrl: https://sonir.app/en/privacy screenshots: # store-shots lang dir is en for en-US iphone69: [iphone69/en/01-record.png, iphone69/en/02-measure.png] play_phone: [play_phone/en/01-record.png, play_phone/en/02-measure.png]
- locale: de-DE name: "Sonir" subtitle: "Raumaufnahme × Akustik" shortDescription: "Räume und Audio durch Aufnahme des Raumklangs messen." description: "Sonir misst den Klang im Raum, indem es ihn mit einem Mikrofon aufnimmt." keywords: "Audio,Messung,RTA,SPL,Nachhall,Aufnahme" promotionalText: "Visualisieren Sie jetzt den Frequenzgang Ihres Raums." whatsNew: "Erste Version." supportUrl: https://sonir.app/de/support marketingUrl: https://sonir.app/ privacyPolicyUrl: https://sonir.app/de/privacy
- locale: fr-FR name: "Sonir" subtitle: "Enregistrement × acoustique" shortDescription: "Mesurez vos pièces et votre audio en enregistrant l’air." description: "Sonir mesure le son de votre pièce en l’enregistrant avec un microphone." keywords: "audio,mesure,RTA,SPL,réverbération,enregistrement" promotionalText: "Visualisez la réponse en fréquence de votre pièce." whatsNew: "Version initiale." supportUrl: https://sonir.app/fr/support marketingUrl: https://sonir.app/ privacyPolicyUrl: https://sonir.app/fr/privacy