Hopp til innhold
Alle guider
Veiledning45 min lesing

Slik automatiserer du App Store-skjermbilder i CI/CD

En praktisk, helhetlig pipeline for å generere skjermbilder til App Store og Google Play fra CI-systemet ditt med Fastlane, GitHub Actions og Bitrise — med konkret konfigurasjon du kan lime rett inn i repoet ditt.

Eric Isensee
Eric IsenseeFounder · Last updated 5. mai 2026

Kort oppsummert

Ta råe app-skjermbilder i testkjøreren din, send dem til Screenshots.live-API-et med en mal-ID og en liste over språk, så skriver Fastlane den ferdig renderte, innrammede og lokaliserte utdataen tilbake til repoet ditt. Fastlane deliver / supply sender dem videre til butikkene. Hele pipelinen kjører på en tag-push eller et nattlig cron-jobb på under fem minutter.

Hvorfor i det hele tatt automatisere skjermbilder?

De fleste team behandler skjermbilder til App Store og Google Play som et håndlaget engangsmateriale: en designer setter dem opp i Figma, en markedsfører laster dem opp i App Store Connect, og ingen rører dem igjen før neste store redesign. Den modellen knekker i det øyeblikket du leverer på mer enn ett språk. Med 13 støttede språk, tre påkrevde iPhone-størrelser, to iPad-størrelser, pluss telefon og nettbrett på Google Play, ender du opp med over 100 PNG-filer for én enkelt utgivelse. Gang det med hver tekstendring, hver kampanje, hver A/B-testvariant, og regnestykket går ikke lenger opp.

Ved å automatisere i CI/CD blir skjermbilder et byggeartefakt på linje med en hvilken som helst annen binærfil. De er versjonert, reproduserbare og knyttet til en commit. Når markedsføring endrer en bildetekst, bygger pipelinen om alle språk og laster dem opp — ingen manuelle Photoshop-økter, ingen skjevheter mellom språkene, ingen avvisning ved innsending fordi noen glemte en 6,7-tommers iPhone-variant.

Hvordan ser pipelinen egentlig ut?

En ren CI-pipeline for skjermbilder har tre faser: fangst, rendering og levering. Fangsten er testpakken for grensesnittet du allerede har — XCUITest på iOS, Espresso på Android, Detox eller Maestro for React Native. Rendering er ett Screenshots.live-API-kall per språk som komponerer de råe rammene dine på en mal du designet én gang. Levering er Fastlane-handlingene deliver og supply du allerede bruker for å sende binærfiler.

REST-rendering-API-et til Screenshots.live er hjørnesteinen. Du sender råe skjermbilder én gang og får tilbake hver enhetsstørrelse, hvert språk og hver variant — fullt innrammet, med tekster og lokalisert. Ingen headless browser, ingen Puppeteer, ingen manuell skalering.

Hvordan kobler du det opp med Fastlane?

Fastlane er det kanoniske verktøyet for å automatisere iOS- og Android-utgivelser. Vi leverer en offisiell Fastlane-plugin som pakker rendering-API-et inn i én enkelt handling. Installer den fra prosjektroten:

terminal
bash
fastlane add_plugin screenshotslive

Legg deretter til en lane i Fastfile som tar fangsten, rendrer og skriver ut den ferdige utdataen:

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

Pluginen håndterer opplastinger, polling for ferdigstillelse og parallell nedlasting. En typisk rendering med 5 språk og 3 enheter er ferdig på 60–90 sekunder.

Hvordan kjører du dette på GitHub Actions?

Slipp lanen inn i en workflow-fil. Workflowen under kjører ved hver tag-push som matcher v*, og på en nattlig tidsplan, så et manuelt git tag v1.2.0 && git push --tags er alt du trenger for å utløse en ny rendering.

.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/

For team som heller vil bruke en GitHub Action uten Fastlane, publiserer vi også en frittstående GitHub Action som snakker direkte med API-et:

.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

Hva med Bitrise?

Bitrise-brukere får den samme lanen via det eksisterende Fastlane-steget. Legg til en Secret kalt SCREENSHOTSLIVE_API_TOKEN i Bitrise-arbeidsområdet ditt, og slipp dette inn i 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

Hvordan holder du byggetiden lav?

Den trege delen av enhver CI-pipeline for skjermbilder er rendering, ikke opplasting. Trikset er å mellomlagre renderinger etter innholds-hash slik at uendrede språk gjenbruker tidligere utdata. Screenshots.live returnerer en stabil renderHash i svaret — bruk den som cache-nøkkel:

  • Malversjon + språk + varianthash → cache-nøkkel
  • Renderte PNG-byte → cache-verdi
  • Cache-TTL: 30 dager, eller til malen blir publisert på nytt

På GitHub Actions bruker du actions/cache@v4 med en nøkkel utledet fra mal-ID-en din og språk-listen. De fleste utgivelsesbygg hopper over rendering helt og bygger bare om språket som faktisk er endret.

Hvordan validerer du utdataen før innsending?

Både Apple og Google avviser skjermbilder stille når de ikke består formatkontroller: en PNG med alfa-kanal, en JPEG kodet som CMYK, eller et 6,7-tommers iPhone-skjermbilde som mangler én piksel. Bygg et 20-linjers lint-steg som fanger dette før innsending:

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

Bør du kjøre det på en tidsplan?

Ja. En nattlig cron betyr at skjermbilder regenereres hver gang malen din endres — enten endringen kom fra en designer i editoren, en tekstoppdatering fra markedsføring eller et nytt språk som ble lagt til. Uten en tidsplan kommer butikkoppføringene ut av synk med det faktiske produktet ditt, og noen må huske å sende et nytt bygg før hver innsending.

Kombiner tidsplanen med en Slack- eller e-postvarsling ved feil. En ødelagt rendering klokken 04:00 UTC er en varsling klokken 07:00 lokal tid — ikke en utgivelsesblokker som oppdages klokken 17:00 den dagen du skulle levere.

Hva med Android, React Native og Flutter?

Pipelinen er plattformuavhengig på rendering-siden — bare fangst-fasen endres. På Android bytter du ut capture_screenshots med Fastlane screengrab og Espresso-pakken din. For React Native bruker du Detox-snapshots. For Flutter bruker du integration_test-skjermbilder. Alle produserer råe PNG-er som Screenshots.live behandler likt.

Les mer i vår guide for støtte på flere plattformer for fangstkonfigurasjon på hver stack.

Hvor går du videre herfra?

Når CI-pipelinen din pålitelig leverer skjermbilder, blir neste spørsmål hvilke skjermbilder som vinner. Kombiner denne pipelinen med guiden for A/B-testing for å levere varianter på en tidsplan og måle konvertering. Par den med lokaliseringsguiden for å legge til 30+ språk uten 30+ pipelines.

Autoritative referanser for videre lesing: Fastlane iOS-skjermbilde-dokumentasjon, Fastlane deliver-handling og de offisielle App Store Connect-spesifikasjonene for skjermbilder.

Prøv det på et ekte repo

Generer alle disse størrelsene automatisk

Slutt å endre størrelse på skjermbilder manuelt. Design én mal og render hver størrelse, enhet og lokalitet med ett enkelt API-kall.

Start gratis — Prøv Screenshots.live