Vai al contenuto
Tutte le guide
Guida pratica45 min di lettura

Come automatizzare gli screenshot dell'App Store in CI/CD

Una pipeline pratica end-to-end per generare screenshot per App Store e Google Play dal tuo sistema CI utilizzando Fastlane, GitHub Actions e Bitrise — con configurazioni concrete che puoi incollare nel tuo repository.

Eric Isensee
Eric IsenseeFounder · Last updated 5 maggio 2026

In sintesi

Cattura gli screenshot grezzi dell'app nel tuo test runner, inviali all'API di Screenshots.live con un ID template e un elenco di lingue, e Fastlane scrive l'output renderizzato, incorniciato e localizzato nel tuo repository. Fastlane deliver / supply li carica sugli store. L'intera pipeline viene eseguita su un push di tag o un cron notturno in meno di cinque minuti.

Perché automatizzare gli screenshot?

La maggior parte dei team tratta gli screenshot per App Store e Google Play come un asset realizzato a mano una tantum: un designer li abbozza in Figma, un marketer li carica su App Store Connect e nessuno li tocca più fino al prossimo grande redesign. Questo modello si rompe nel momento in cui pubblichi in più di una lingua. Con 13 lingue supportate, tre dimensioni di iPhone richieste, due dimensioni di iPad, più telefono e tablet su Google Play, ti ritrovi con oltre 100 file PNG per una singola release. Moltiplica per ogni modifica di testo, ogni promozione, ogni variante di test A/B, e i conti non tornano più.

Automatizzare in CI/CD rende gli screenshot un artefatto di build come qualsiasi altro binario. Sono versionati, riproducibili e legati a un commit. Quando il marketing modifica una didascalia, la pipeline ricompila ogni lingua e li carica — niente sessioni manuali in Photoshop, nessuna deriva degli asset tra le lingue, nessun rifiuto in fase di invio perché qualcuno si è dimenticato di una variante per iPhone da 6,7 pollici.

Com'è fatta concretamente la pipeline?

La struttura di una pipeline CI per screenshot ben fatta è composta da tre fasi: cattura, render e consegna. La cattura è la tua attuale suite di test UI — XCUITest su iOS, Espresso su Android, Detox o Maestro per React Native. Il render è una chiamata API di Screenshots.live per lingua che compone i tuoi frame grezzi su un template che hai progettato una sola volta. La consegna è costituita dalle azioni Fastlane deliver e supply esistenti che già usi per pubblicare i binari.

L<link>API di rendering REST</link> di Screenshots.live è il fulcro. Invii gli screenshot grezzi una sola volta e ricevi indietro ogni dimensione di dispositivo, ogni lingua e ogni variante — completamente incorniciati, con didascalie e localizzati. Niente browser headless, niente Puppeteer, niente ridimensionamento manuale.

Come si configura con Fastlane?

Fastlane è lo strumento canonico di automazione delle release per iOS / Android. Forniamo un plugin Fastlane ufficiale che incapsula l'API di rendering in un'unica azione. Installalo dalla root del tuo progetto:

terminal
bash
fastlane add_plugin screenshotslive

Quindi aggiungi una lane al tuo Fastfile che cattura, renderizza e scrive l'output renderizzato:

fastlane/Fastfile
ruby
lane :render_screenshots do
  # 1. Capture raw frames with XCUITest
  capture_screenshots(
    workspace: "MyApp.xcworkspace",
    scheme: "MyAppUITests",
    devices: ["iPhone 16 Pro Max", "iPad Pro 12.9-inch"],
    languages: ["en-US", "de-DE", "es-ES", "fr-FR", "pt-BR"]
  )

  # 2. Send raw frames to Screenshots.live, get framed PNGs back
  screenshotslive_render(
    api_token: ENV["SCREENSHOTSLIVE_API_TOKEN"],
    template_id: "tpl_app_release_v3",
    input_dir: "./fastlane/screenshots",
    output_dir: "./fastlane/rendered",
    locales: ["en", "de", "es", "fr", "pt"],
    devices: ["iphone-6.7", "iphone-6.1", "ipad-12.9"]
  )

  # 3. Push to App Store Connect
  deliver(
    screenshots_path: "./fastlane/rendered",
    skip_binary_upload: true,
    skip_metadata: false
  )
end

Il plugin gestisce gli upload, il polling per il completamento e il download in parallelo. Un render tipico con 5 lingue e 3 dispositivi si completa in 60–90 secondi.

Come si esegue su GitHub Actions?

Inserisci la lane in un file di workflow. Il workflow qui sotto viene eseguito ad ogni push di tag che corrisponde a v* e su una pianificazione notturna, quindi un semplice git tag v1.2.0 && git push --tags manuale è tutto ciò che serve per attivare un nuovo render.

.github/workflows/screenshots.yml
yaml
name: Render Store Screenshots

on:
  push:
    tags: ["v*"]
  schedule:
    - cron: "0 4 * * *"  # nightly at 04:00 UTC
  workflow_dispatch:

jobs:
  render:
    runs-on: macos-14
    steps:
      - uses: actions/checkout@v4

      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: "3.2"
          bundler-cache: true

      - name: Render screenshots
        env:
          SCREENSHOTSLIVE_API_TOKEN: ${{ secrets.SCREENSHOTSLIVE_API_TOKEN }}
          FASTLANE_USER: ${{ secrets.FASTLANE_USER }}
          FASTLANE_PASSWORD: ${{ secrets.FASTLANE_PASSWORD }}
        run: bundle exec fastlane render_screenshots

      - name: Upload rendered artifacts
        uses: actions/upload-artifact@v4
        with:
          name: store-screenshots
          path: fastlane/rendered/

Per i team che preferiscono una GitHub Action senza Fastlane, pubblichiamo anche una GitHub Action standalone che dialoga direttamente con l'API:

.github/workflows/screenshots-direct.yml
yaml
- uses: Screenshots-Live/render-screenshots-action@v1
  with:
    api-token: ${{ secrets.SCREENSHOTSLIVE_API_TOKEN }}
    template-id: tpl_app_release_v3
    locales: en,de,es,fr,pt,it,nl
    devices: iphone-6.7,iphone-6.1,ipad-12.9
    output-dir: ./screenshots

E con Bitrise?

Gli utenti Bitrise ottengono la stessa lane attraverso lo step Fastlane esistente. Aggiungi un Secret chiamato SCREENSHOTSLIVE_API_TOKEN nel tuo workspace Bitrise, quindi inserisci questo nel tuo bitrise.yml:

bitrise.yml
yaml
workflows:
  render-screenshots:
    steps:
    - activate-ssh-key@4: {}
    - git-clone@8: {}
    - script@1:
        title: Install Fastlane plugins
        inputs:
        - content: |-
            #!/usr/bin/env bash
            bundle install
            bundle exec fastlane add_plugin screenshotslive
    - fastlane@3:
        inputs:
        - lane: render_screenshots
        - work_dir: "$BITRISE_SOURCE_DIR"
    - deploy-to-bitrise-io@2:
        inputs:
        - deploy_path: ./fastlane/rendered

Come si mantengono bassi i tempi di build?

La parte lenta di qualsiasi pipeline CI per screenshot è il rendering, non l'upload. Il trucco è memorizzare nella cache i render in base all'hash del contenuto, in modo che le lingue invariate riutilizzino l'output precedente. Screenshots.live restituisce un renderHash stabile nella risposta — usalo come chiave di cache:

  • Versione del template + lingua + hash della variante → chiave di cache
  • Byte del PNG renderizzato → valore di cache
  • TTL della cache: 30 giorni, o fino a quando il template non viene ripubblicato

Su GitHub Actions, usa actions/cache@v4 con una chiave derivata dall'ID del tuo template e dall'elenco delle lingue. La maggior parte delle build di release salta completamente il rendering e ricompila solo la lingua effettivamente modificata.

Come si valida l'output prima dell'invio?

Apple e Google rifiutano entrambi gli screenshot in modo silenzioso quando non superano i controlli di formato: un PNG con canale alpha, un JPEG codificato come CMYK, o uno screenshot di iPhone da 6,7 pollici corto di un pixel. Costruisci uno step di lint da 20 righe che intercetta questi problemi prima dell'invio:

fastlane/lint_screenshots.rb
ruby
require "chunky_png"

Dir.glob("./fastlane/rendered/**/*.png").each do |path|
  png = ChunkyPNG::Image.from_file(path)
  raise "alpha channel: #{path}" if png.metadata["ColorType"] == 6
  raise "too large: #{path}"     if File.size(path) > 30 * 1024 * 1024
  raise "wrong size: #{path}"    if png.width < 1242
end

Conviene eseguirla con una pianificazione?

Sì. Un cron notturno significa che gli screenshot vengono rigenerati ogni volta che il tuo template cambia — che la modifica provenga da un designer nell'editor, da un aggiornamento di testo del marketing o dall'aggiunta di una nuova lingua. Senza una pianificazione, le schede sugli store si disallineano dal tuo prodotto reale, e qualcuno deve ricordarsi di pubblicare una nuova build prima di ogni invio.

Combina la pianificazione con un avviso Slack o email in caso di errore. Un render fallito alle 04:00 UTC è una notifica alle 07:00 ora locale — non un blocco di release scoperto alle 17:00 del giorno in cui volevi pubblicare.

E con Android, React Native e Flutter?

La pipeline è agnostica rispetto alla piattaforma sul lato del rendering — cambia solo la fase di cattura. Per Android, sostituisci capture_screenshots con screengrab di Fastlane e la tua suite Espresso. Per React Native, usa gli snapshot di Detox. Per Flutter, usa gli screenshot di integration_test. Tutti producono PNG grezzi che Screenshots.live tratta in modo identico.

Approfondisci nella nostra guida al supporto multipiattaforma per la configurazione della cattura su ciascuno stack.

Quali sono i passi successivi?

Una volta che la tua pipeline CI pubblica gli screenshot in modo affidabile, la domanda successiva è quali screenshot vincono. Combina questa pipeline con la guida al test A/B per pubblicare varianti su una pianificazione e misurare le conversioni. Abbinala alla guida alla localizzazione per aggiungere oltre 30 lingue senza oltre 30 pipeline.

Riferimenti autorevoli per ulteriori letture: documentazione Fastlane sugli screenshot iOS, azione deliver di Fastlane e le specifiche ufficiali per gli screenshot di App Store Connect.

Provalo su un repository reale

Generi tutte queste dimensioni automaticamente

Smetta di ridimensionare gli screenshot manualmente. Progetti un solo modello e renderizzi ogni dimensione, dispositivo e lingua con una singola chiamata API.

Inizi gratuitamente — Provi Screenshots.live