mit GitHub Actions und EAS
Eine solide CI/CD-Pipeline verwandelt jeden Merge in einen reproduzierbaren, signierten Build, statt sich auf manuell gebaute Binaries von einzelnen Entwicklerrechnern zu verlassen. Dieser Artikel zeigt, wie GitHub Actions und Expo Application Services zusammen Lint, Tests, Cloud-Builds, Code-Signing und Store-Submission für eine React Native App automatisieren.
Inhaltsverzeichnis
- 1. Warum eine CI/CD-Pipeline für React Native unverzichtbar ist
- 2. GitHub Actions Workflow-Struktur: Trigger und Jobs
- 3. Lint, Typecheck und Tests automatisiert ausführen
- 4. EAS Build: native Binaries ohne lokales Xcode
- 5. Build-Profile in eas.json: Development, Preview, Production
- 6. Code-Signing und Credentials-Verwaltung über EAS
- 7. EAS Submit und EAS Update für Auslieferung
- 8. Caching und Branch-Strategie für schnellere Pipelines
- 9. Lokale Builds im Vergleich zu EAS Build in der Cloud
- 10. Zusammenfassung
- 11. FAQ
1. Warum eine CI/CD-Pipeline für React Native unverzichtbar ist
Ohne eine funktionierende CI/CD-Pipeline hängt jeder Release einer React Native App von einem einzelnen Entwicklerrechner ab: der richtigen Xcode-Version, den passenden Zertifikaten, einer sauberen node_modules-Installation. Ein einziger falsch konfigurierter Rechner reicht, um einen Build zu produzieren, der sich nicht reproduzieren lässt oder subtil anders funktioniert als der letzte Release. Eine automatisierte Pipeline entfernt diese Abhängigkeit von individuellen Maschinen vollständig.
Für React Native kommt eine Besonderheit hinzu: Anders als eine reine Web-App braucht ein Release native Kompilierung für iOS und Android, inklusive Code-Signing mit echten Zertifikaten. Genau hier setzt EAS an, Expos Cloud-Infrastruktur für Builds, Submissions und Over-the-Air-Updates, kombiniert mit GitHub Actions als Orchestrierungsebene für Trigger, Tests und Freigabelogik.
Der Aufbau einer CI/CD-Pipeline mit GitHub Actions und EAS lohnt sich bereits für Ein-Personen-Projekte, weil sie Fehler vor dem Release abfängt, die sonst erst im App-Store-Review oder schlimmer, bei echten Nutzern auffallen würden. Für Teams ab zwei Entwicklern wird sie schnell zur Pflicht, da sonst niemand mehr sicher sagen kann, welcher Code tatsächlich in welchem veröffentlichten Build steckt.
2. GitHub Actions Workflow-Struktur: Trigger und Jobs
Ein GitHub-Actions-Workflow für React Native gliedert sich typischerweise in mehrere Jobs: einen schnellen Lint- und Typecheck-Job, der bei jedem Push läuft, einen Test-Job für Unit- und Integrationstests, und einen deutlich langsameren Build-Job, der nur bei bestimmten Ereignissen wie einem Merge in den Main-Branch oder einem manuellen Trigger ausgeführt wird. Diese Staffelung verhindert, dass jeder kleine Commit einen vollen, minutenlangen Cloud-Build auslöst.
Trigger-Konfiguration über on: push und on: pull_request steuert, wann welcher Job anläuft, während workflow_dispatch einen manuellen Start über die GitHub-Oberfläche erlaubt, etwa für einen gezielten Preview-Build zum Testen einer einzelnen Funktion. Matrix-Jobs ermöglichen es zusätzlich, Tests parallel gegen mehrere Node-Versionen oder Betriebssystem-Runner laufen zu lassen, was besonders bei plattformübergreifenden Bibliotheken frühzeitig Inkompatibilitäten aufdeckt.
name: React Native CI
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
jobs:
lint-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: yarn
- run: yarn install --frozen-lockfile
- run: yarn lint
- run: yarn typecheck
- run: yarn test --ci --coverage
eas-build-preview:
needs: lint-and-test
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm install -g eas-cli
- run: eas build --platform all --profile preview --non-interactive
env:
# EXPO_TOKEN is injected here from a GitHub repository secret of the same name
EXPO_TOKEN: FROM_REPOSITORY_SECRET
3. Lint, Typecheck und Tests automatisiert ausführen
Bevor überhaupt ein nativer Build angestoßen wird, sollte die CI/CD-Pipeline die günstigen, schnellen Prüfungen zuerst ausführen: ESLint für Stilregeln, TypeScript-Typprüfung für strukturelle Fehler, Jest für Unit-Tests der Geschäftslogik. Diese Schritte laufen typischerweise in unter zwei Minuten und fangen die überwältigende Mehrheit aller Fehler ab, bevor teure Cloud-Build-Minuten verbraucht werden.
Für End-to-End-Smoke-Tests mit Detox oder Maestro ist die Reihenfolge wichtig: Diese Tests benötigen einen fertigen, nativen Build, laufen also erst nach einem erfolgreichen EAS-Build-Schritt und typischerweise nicht bei jedem Pull Request, sondern gezielt vor einem Production-Release. Ein sinnvoller Kompromiss ist, E2E-Smoke-Tests nächtlich oder bei jedem Merge in den Main-Branch laufen zu lassen, statt bei jedem einzelnen Commit, da sie deutlich länger laufen als reine Unit-Tests.
// checkoutFlow.test.tsx — Jest unit test run on every push in CI
import { render, screen } from '@testing-library/react-native';
import { CheckoutSummary } from '../CheckoutSummary';
describe('CheckoutSummary', () => {
it('shows the total price formatted with currency', () => {
render(<CheckoutSummary items={[{ price: 19.99, qty: 2 }]} />);
expect(screen.getByText('39.98 EUR')).toBeTruthy();
});
it('disables the pay button while a payment request is in flight', () => {
render(<CheckoutSummary items={[]} isSubmitting />);
expect(screen.getByRole('button', { name: /pay/i })).toBeDisabled();
});
});
4. EAS Build: native Binaries ohne lokales Xcode
EAS Build löst ein Problem, das jedes React-Native-Team kennt: Native iOS-Builds benötigen einen Mac mit installiertem Xcode, was in klassischen CI-Umgebungen entweder teure Mac-Runner oder komplizierte Hackintosh-Setups erfordert. EAS Build übernimmt die komplette native Kompilierung in Expos eigener Cloud-Infrastruktur, sowohl für iOS als auch Android, sodass der GitHub-Actions-Runner selbst nur den eas build-Befehl anstößt und auf das fertige Ergebnis wartet, ohne selbst über native Toolchains verfügen zu müssen.
Diese Architektur bedeutet auch, dass ein Build auf einem günstigen Linux-Runner ausgelöst werden kann, selbst wenn das Ergebnis ein iOS-Binary ist. Die eigentliche Kompilierung findet vollständig in EAS' verwalteter Infrastruktur statt, inklusive der korrekten Xcode-Version passend zum jeweiligen Expo-SDK. Für Teams ohne eigene Mac-Hardware ist das oft der entscheidende Grund, überhaupt auf EAS zu setzen, statt eine eigene Mac-Mini-Build-Farm zu betreiben.
5. Build-Profile in eas.json: Development, Preview, Production
Die Datei eas.json definiert Build-Profile, die jeweils unterschiedliche Umgebungsvariablen, Signierungseinstellungen und Distributionskanäle repräsentieren. Ein Development-Profil produziert einen Debug-Build mit aktiviertem Dev-Client für lokale Entwicklung, ein Preview-Profil einen internen Verteilungsbuild für Tester über TestFlight oder direkte APK-Installation, ein Production-Profil den finalen, für den Store bestimmten Release-Build mit Produktions-API-Endpunkten.
Der entscheidende Vorteil dieser Profile in einer CI/CD-Pipeline: Ein Pull Request kann automatisch einen Preview-Build mit der Staging-API auslösen, während ein Merge in Main einen Production-Build mit der echten API-Basis-URL erzeugt, ohne dass irgendwo im Code eine manuelle Umschaltung nötig wäre. Die Umgebungsvariablen werden direkt im jeweiligen Profil oder über EAS-Secrets hinterlegt und sind damit sauber von der eigentlichen Codebasis getrennt.
{
"build": {
"development": {
"developmentClient": true,
"distribution": "internal",
"env": { "API_URL": "https://dev-api.example.com" }
},
"preview": {
"distribution": "internal",
"channel": "preview",
"env": { "API_URL": "https://staging-api.example.com" }
},
"production": {
"autoIncrement": true,
"channel": "production",
"env": { "API_URL": "https://api.example.com" }
}
},
"submit": {
"production": {}
}
}
6. Code-Signing und Credentials-Verwaltung über EAS
Code-Signing ist historisch eine der größten Fehlerquellen bei mobilen Releases: abgelaufene Zertifikate, falsch zugeordnete Provisioning-Profile, versehentlich committete Keystores im Git-Repository. EAS übernimmt die Verwaltung dieser Credentials zentral in einem verschlüsselten Speicher, entweder generiert und verwaltet vollständig durch EAS selbst, oder als eigene, hochgeladene Zertifikate, falls das Team bereits ein bestehendes Apple-Entwicklerkonto mit vorhandenen Provisioning-Profilen nutzt.
In der CI-Pipeline selbst tauchen diese Credentials nie im Klartext auf. Der GitHub-Actions-Runner authentifiziert sich lediglich über ein EXPO_TOKEN, das als verschlüsseltes Repository-Secret hinterlegt wird, und EAS Build lädt daraufhin die passenden Zertifikate und Keystores serverseitig aus dem eigenen, gesicherten Speicher. Das reduziert die Angriffsfläche erheblich gegenüber einem klassischen Setup, in dem Signierungsdateien als CI-Artefakte durch mehrere Systeme wandern.
# Configure credentials interactively once, EAS stores them securely afterward
eas credentials
# List currently stored credentials for a specific platform
eas credentials --platform ios
# In CI, authentication happens purely through the EXPO_TOKEN environment variable
# stored as a GitHub repository secret, never through interactive prompts
export EXPO_TOKEN="your-expo-access-token-here"
eas build --platform ios --profile production --non-interactive
7. EAS Submit und EAS Update für Auslieferung
Nach einem erfolgreichen Production-Build übernimmt eas submit das automatische Hochladen zu App Store Connect beziehungsweise zur Google Play Console, inklusive der nötigen API-Authentifizierung über App Store Connect API Keys oder einen Google-Service-Account. Das ersetzt den manuellen Upload über Transporter oder die Play-Console-Oberfläche vollständig und macht Submission zu einem einzigen, wiederholbaren Pipeline-Schritt.
EAS Update ergänzt diesen Prozess um eine zweite Auslieferungsart: Für reine JavaScript-Bundle-Änderungen, die keine neue native Kompilierung erfordern, etwa einen Textfehler oder eine kleine Logikänderung, kann ein Update direkt an bereits installierte Apps ausgeliefert werden, ohne einen vollständigen Store-Review-Zyklus zu durchlaufen. Das ist kein Ersatz für native Releases, aber ein wertvolles Werkzeug, um kleine Fehler innerhalb von Minuten statt Tagen zu korrigieren.
8. Caching und Branch-Strategie für schnellere Pipelines
Eine CI-Pipeline, die bei jedem Lauf node_modules komplett neu installiert, verschwendet unnötig Zeit und CI-Minuten. GitHub Actions' eingebautes Caching über actions/setup-node mit cache: yarn oder ein expliziter actions/cache-Schritt für den Yarn- oder npm-Cache-Ordner reduziert die Installationszeit oft von mehreren Minuten auf wenige Sekunden bei unveränderten Abhängigkeiten.
Eine klare Branch-Strategie rundet die CI/CD-Pipeline ab: Feature-Branches lösen bei jedem Push nur Lint, Typecheck und Unit-Tests aus, ein Preview-Build entsteht gezielt bei einem Pull Request gegen Main, und ausschließlich ein Merge in Main triggert den vollständigen Production-Build mit anschließendem EAS Submit. Diese Staffelung hält die Pipeline für die tägliche Entwicklung schnell und reserviert die teuren, langsamen Schritte für tatsächliche Release-Kandidaten.
9. Lokale Builds im Vergleich zu EAS Build in der Cloud
Ob eine Migration von lokalen, manuell ausgeführten Builds zu einer vollautomatisierten EAS-Pipeline lohnt, zeigt sich am deutlichsten im direkten Vergleich der wichtigsten Betriebsdimensionen.
| Dimension | Lokale Builds (manuell) | EAS Build in der Cloud-Pipeline |
|---|---|---|
| Setup-Aufwand | Xcode, Android Studio, Zertifikate pro Rechner | Ein eas.json, keine lokale Toolchain nötig |
| Reproduzierbarkeit | Abhängig vom Zustand des jeweiligen Rechners | Identische, versionierte Build-Umgebung |
| Signierung | Manuelle Zertifikatsverwaltung, Fehleranfällig | Zentral verwaltet, nie im Klartext in CI |
| Parallelisierung | Ein Build blockiert den Entwicklerrechner | Mehrere Builds parallel in der Cloud |
| Team-Skalierung | Jeder Entwickler braucht vollständiges Setup | Ein zentraler Pipeline-Zugang für alle |
Für kleine Prototypen mag ein lokaler Build noch ausreichen, doch sobald ein Team wächst oder ein Release regelmäßig an einen Store geht, überwiegen die Vorteile einer Cloud-Pipeline fast immer die anfängliche Einrichtungszeit. Der größte, oft unterschätzte Gewinn ist nicht Geschwindigkeit, sondern Nachvollziehbarkeit: Jeder Build lässt sich exakt einem Commit und einer Pipeline-Ausführung zuordnen.
Mironsoft
React Native Entwicklung, CI/CD-Pipelines und App-Release-Automatisierung
CI/CD-Pipeline für eure React Native App aufbauen?
Wir richten GitHub Actions und EAS für euer Team ein, inklusive Build-Profilen, Code-Signing, automatisierter Store-Submission und EAS Update für schnelle Bugfixes ohne vollen Review-Zyklus.
Workflow-Design
GitHub-Actions-Workflows mit sinnvoller Trigger- und Job-Struktur
EAS-Konfiguration
Build-Profile, Credentials-Verwaltung und Submission-Automatisierung
Release-Strategie
Branch-Strategie, Caching und EAS-Update-Rollout-Planung
10. Zusammenfassung
Eine funktionierende React Native CI/CD-Pipeline mit GitHub Actions und EAS beginnt mit einer klaren Job-Staffelung: schnelle Lint- und Typecheck-Prüfungen bei jedem Push, gezielte Preview-Builds bei Pull Requests, vollständige Production-Builds nur bei Merges in Main. EAS Build übernimmt die eigentliche native Kompilierung in der Cloud, ohne dass ein Team eigene Mac-Hardware für iOS-Builds vorhalten muss, und Build-Profile in eas.json trennen Development, Preview und Production sauber über eigene Umgebungsvariablen.
Code-Signing, historisch eine der größten Fehlerquellen mobiler Releases, wird durch EAS' zentrale Credentials-Verwaltung entschärft, da Zertifikate und Keystores nie im Klartext durch die CI-Pipeline wandern. EAS Submit automatisiert die Store-Einreichung, EAS Update ermöglicht schnelle Bugfixes ohne vollen Review-Zyklus. Zusammen entsteht eine Pipeline, in der jeder Release exakt einem Commit zuordenbar und jederzeit reproduzierbar ist.
React Native CI/CD-Pipeline — Das Wichtigste auf einen Blick
Job-Staffelung
Schnelle Checks bei jedem Push, teure Cloud-Builds nur bei Pull Requests und Main-Merges.
EAS Build
Native Kompilierung in der Cloud, kein eigenes Mac für iOS-Builds nötig.
Code-Signing
Zentral von EAS verwaltet, Zertifikate erscheinen nie im Klartext in der Pipeline.
Submit & Update
Automatisierte Store-Einreichung plus Over-the-Air-Fixes ohne vollen Review-Zyklus.