Screenshots.live
Team
Eine Screenshot-Pipeline in Ihrer CI/CD aufbauen: Schritt-fuer-Schritt-Anleitung
Erfahren Sie, wie Sie eine automatisierte Screenshot-Pipeline mit der Screenshots.live API, GitHub Actions und Fastlane aufbauen. Komplett mit YAML-Konfigurationen, Rendering-Skripten und Upload-Automatisierung.
Warum Screenshots in Ihre CI/CD-Pipeline gehoeren
App-Store-Screenshots werden normalerweise als Design-Aufgabe behandelt, etwas, das einmal vor dem Launch passiert und dann alle paar Monate muehsam aktualisiert wird. Dieser Ansatz scheitert, sobald Ihr Team haeufig ausliefert. Wenn Sie alle zwei Wochen releasen, fallen Ihre Screenshots nach dem ersten Sprint zurueck.
Die Loesung ist, Screenshots wie jedes andere Build-Artefakt zu behandeln. Sie sollten automatisch generiert werden, wenn sich Ihre UI aendert, versioniert neben Ihrem Code, und als Teil Ihres Release-Prozesses in die App Stores deployt werden.
Die Vorteile sind erheblich. Erstens spiegeln Ihre Screenshots immer den aktuellen Stand Ihrer App wider. Zweitens aktualisieren sich lokalisierte Screenshots automatisch. Drittens setzt Ihr Design-Team das Template einmal und Entwickler erledigen den Rest ueber Konfiguration. Viertens eliminieren Sie den manuellen Export-und-Upload-Zyklus.
Architektur-Ueberblick
Eine vollstaendige Screenshot-Pipeline hat fuenf Stufen:
- Template-Design — Ihr Design-Team erstellt Screenshot-Templates im visuellen Editor von Screenshots.live.
- Konfiguration — Eine YAML-Datei in Ihrem Repository definiert welche Templates gerendert werden, welche Sprachen generiert werden und welche Textvariablen injiziert werden.
- Rendering — Ihre CI/CD-Pipeline ruft die Screenshots.live API auf, die alle Variationen rendert und als ZIP-Archiv zurueckgibt.
- Nachbearbeitung — Die Pipeline extrahiert das ZIP und organisiert Dateien in die erwartete Verzeichnisstruktur.
- Upload — Fastlane liefert die Screenshots automatisch an App Store Connect und Google Play Console.
Konfigurationsdatei einrichten
Erstellen Sie eine Screenshot-Konfigurationsdatei im Wurzelverzeichnis Ihres Repositorys:
# .screenshots/config.yml
api_key: ${SCREENSHOTS_API_KEY}
base_url: https://api.screenshots.live/v1
templates:
- id: tpl_hero_screen
name: "Hero Screenshot"
devices:
- iphone67
- ipad129
- android_phone
- android_tablet
- id: tpl_feature_list
name: "Feature List"
devices:
- iphone67
- ipad129
- android_phone
- android_tablet
locales:
- code: en
variables:
headline: "Track Your Progress"
subtitle: "All-in-one fitness companion"
- code: de
variables:
headline: "Verfolge deinen Fortschritt"
subtitle: "Alles-in-einem Fitness-Begleiter"Speichern Sie Ihren API-Schluessel als Repository-Secret, niemals in der Konfigurationsdatei selbst.
GitHub Actions Workflow
Hier ist ein vollstaendiger GitHub Actions Workflow. Erstellen Sie diese Datei unter .github/workflows/screenshots.yml:
name: Generate App Store Screenshots
on:
push:
branches: [main]
paths:
- '.screenshots/**'
workflow_dispatch:
env:
SCREENSHOTS_API_KEY: ${{ secrets.SCREENSHOTS_API_KEY }}
SCREENSHOTS_OUTPUT_DIR: ./fastlane/screenshots
jobs:
generate-screenshots:
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Cache Screenshots
uses: actions/cache@v4
with:
path: .screenshots/cache
key: screenshots-${{ hashFiles('.screenshots/config.yml') }}
- run: npm install js-yaml node-fetch@2 adm-zip
- run: node .screenshots/generate.js
- name: Verify
run: |
TOTAL=$(find $SCREENSHOTS_OUTPUT_DIR -name "*.png" | wc -l)
echo "Total: $TOTAL"
[ "$TOTAL" -gt 0 ] || exit 1
- uses: actions/upload-artifact@v4
with:
name: app-store-screenshots
path: ${{ env.SCREENSHOTS_OUTPUT_DIR }}
upload-ios:
needs: generate-screenshots
runs-on: macos-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: app-store-screenshots
path: fastlane/screenshots
- run: gem install fastlane
- name: Upload to App Store Connect
env:
APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.ASC_KEY_ID }}
APP_STORE_CONNECT_API_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
APP_STORE_CONNECT_API_KEY: ${{ secrets.ASC_PRIVATE_KEY }}
run: fastlane ios upload_screenshots
upload-android:
needs: generate-screenshots
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: app-store-screenshots
path: fastlane/screenshots
- run: gem install fastlane
- name: Upload to Google Play
env:
SUPPLY_JSON_KEY_DATA: ${{ secrets.GOOGLE_PLAY_JSON_KEY }}
run: fastlane android upload_screenshotsDas Rendering-Skript
Der Workflow ruft ein Node.js-Skript auf, das die Konfiguration liest, die API aufruft und die Ausgabe organisiert. Erstellen Sie es unter .screenshots/generate.js:
const fs = require('fs');
const path = require('path');
const yaml = require('js-yaml');
const fetch = require('node-fetch');
const AdmZip = require('adm-zip');
const CONFIG_PATH = path.join(__dirname, 'config.yml');
const OUTPUT_DIR = process.env.SCREENSHOTS_OUTPUT_DIR || './fastlane/screenshots';
async function main() {
const config = yaml.load(fs.readFileSync(CONFIG_PATH, 'utf8'));
const apiKey = process.env.SCREENSHOTS_API_KEY;
if (!apiKey) throw new Error('SCREENSHOTS_API_KEY is required');
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
for (const template of config.templates) {
console.log(`Rendering: ${template.name}`);
const variables = {};
for (const locale of config.locales) {
variables[locale.code] = locale.variables;
}
const response = await fetch(`${config.base_url}/render`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
templateId: template.id,
locales: config.locales.map(l => l.code),
devices: template.devices,
variables,
}),
});
if (!response.ok) throw new Error(`Render failed: ${response.status}`);
const zip = new AdmZip(Buffer.from(await response.arrayBuffer()));
for (const entry of zip.getEntries()) {
if (entry.isDirectory) continue;
const outputPath = path.join(OUTPUT_DIR, entry.entryName);
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
fs.writeFileSync(outputPath, entry.getData());
}
}
console.log('Done.');
}
main().catch(err => { console.error(err); process.exit(1); });Fastlane-Integration
# fastlane/Fastfile
platform :ios do
lane :upload_screenshots do
deliver(
skip_binary_upload: true,
skip_metadata: true,
screenshots_path: "./fastlane/screenshots/ios",
overwrite_screenshots: true,
)
end
end
platform :android do
lane :upload_screenshots do
upload_to_play_store(
skip_upload_apk: true,
skip_upload_aab: true,
skip_upload_metadata: true,
images_path: "./fastlane/screenshots/android",
)
end
endLokalisierung in der Pipeline verwalten
Lokalisierungsverwaltung ist einer der groessten Vorteile einer automatisierten Pipeline. Anstatt manuell zu verfolgen, welche Screenshots uebersetzt wurden, wird Ihre Konfigurationsdatei zur einzigen Wahrheitsquelle.
Wenn Sie eine neue Sprache hinzufuegen, fuegen Sie einen Eintrag in config.yml hinzu. Der naechste Pipeline-Lauf generiert Screenshots fuer jedes Template in der neuen Sprache. Keine Designarbeit noetig.
Fuer Teams, die ein Uebersetzungsmanagement-System wie Lokalise, Phrase oder Crowdin verwenden, koennen Sie einen Pre-Render-Schritt hinzufuegen, der die neuesten Uebersetzungen zieht.
Caching und Optimierungstipps
Inhaltsbasierte Cache-Schluessel. Der Workflow verwendet hashFiles('.screenshots/config.yml') als Cache-Schluessel. Wenn sich die Konfiguration nicht geaendert hat, werden gecachte Screenshots sofort wiederverwendet.
Selektives Rendering. Wenn nur eine Sprache geaendert wurde, erwaegen Sie, Ihre Renders nach Sprache aufzuteilen und jede unabhaengig zu cachen.
Paralleles Rendering. Die Screenshots.live API kann gleichzeitige Anfragen verarbeiten:
const renderPromises = config.templates.map(template =>
renderTemplate(template, config, apiKey)
);
await Promise.all(renderPromises);Renders mit Webhooks ueberwachen
Fuer Teams, die Einblick in den Rendering-Prozess benoetigen, unterstuetzt Screenshots.live Webhooks, die Ihre Systeme benachrichtigen, wenn Renders abgeschlossen sind oder fehlschlagen. Sie koennen auch Render-Benachrichtigungen an Slack oder Microsoft Teams senden.
Alles zusammenfuegen
Eine vollstaendige Screenshot-Pipeline transformiert App-Store-Asset-Management von einem manuellen, fehleranfaelligen Prozess in ein automatisiertes, zuverlaessiges System:
- Ein Designer erstellt oder aktualisiert ein Template im visuellen Editor.
- Ein Entwickler aktualisiert die Konfiguration und pusht nach
main. - GitHub Actions erkennt die Aenderung und startet den Workflow.
- Das Rendering-Skript liest die Konfiguration, ruft die API auf und laedt Screenshots herunter.
- Fastlane laedt die Screenshots in beide Stores hoch.
- Beide Store-Eintraege sind innerhalb von Minuten aktualisiert.
Der gesamte Prozess laeuft ohne manuellen Eingriff. Ihre Screenshots sind immer aktuell, immer konsistent und immer lokalisiert.