GitHub Actions + EAS
Um cookbook para conectar GitHub Actions ao EAS Build, Submit e Update - cobrindo segredos, cache, triggers de monorepo e expo-github-action.
Busque em todas as páginas da documentação
Um cookbook para conectar GitHub Actions ao EAS Build, Submit e Update - cobrindo segredos, cache, triggers de monorepo e expo-github-action.
Cartão de receita de referência rápida - pronto para copiar e colar.
# .github/workflows/eas-build.yml
name: EAS Build
on:
workflow_dispatch:
push:
tags: ["v*"]
env:
EXPO_TOKEN: ${{ secrets.EXPO_TOKEN }}
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- uses: expo/expo-github-action@v8
with:
eas-version: latest
token: ${{ secrets.EXPO_TOKEN }}
- run: npm ci
- run: npm run typecheck && npm run test -- --ci
- run: eas build --profile production --platform all --non-interactive# Cria token de robô (uma vez, localmente)
npx eas-cli@latest login
# Dashboard Expo → Access Tokens → Create token → cole em GitHub Secrets como EXPO_TOKENQuando usar isso:
v*) que não devem depender de um laptop de desenvolvedor.apps/mobile deve acionar fluxos de trabalho móveis.Layout do projeto:
your-expo-app/
.github/workflows/
pr-checks.yml
eas-release.yml
eas.json
app.json
package-lock.json# .github/workflows/pr-checks.yml
name: PR Checks
on:
pull_request:
branches: [main]
concurrency:
group: pr-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
quality:
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npx expo customize tsconfig.json
- run: npm run format:check
- run: npm run lint
- run: npm run typecheck
- run: npm run test -- --ci --passWithNoTests# .github/workflows/eas-release.yml
name: EAS Release
on:
push:
tags: ["v*"]
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- uses: expo/expo-github-action@v8
with:
eas-version: latest
token: ${{ secrets.EXPO_TOKEN }}
eas-cache: true
- run: npm ci
- run: npx expo-doctor
- run: npm run typecheck && npm run test -- --ci
- name: Build production
run: eas build --profile production --platform all --non-interactive --wait
- name: Submit iOS
run: eas submit --platform ios --latest --non-interactive
- name: Submit Android
run: eas submit --platform android --latest --non-interactive# .github/workflows/mobile-pr.yml
name: Mobile PR
on:
pull_request:
jobs:
changes:
runs-on: ubuntu-latest
outputs:
mobile: ${{ steps.filter.outputs.mobile }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: filter
with:
filters: |
mobile:
- 'apps/mobile/**'
- 'packages/ui/**'
- 'packages/api-client/**'
- 'package-lock.json'
quality:
needs: changes
if: needs.changes.outputs.mobile == 'true'
runs-on: ubuntu-latest
defaults:
run:
working-directory: apps/mobile
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: package-lock.json
- run: npm ci
- run: npm run lint && npm run typecheck && npm run test -- --ci# Alternativa de raiz de monorepo com Turborepo
npx turbo run lint typecheck test --filter=mobileO que isso demonstra:
EXPO_TOKEN autentica eas build / submit sem login interativo.eas-cache: true no expo-github-action acelera invocações repetidas do CLI.npm ci + cache: npm restaura node_modules entre as execuções do fluxo de trabalho.apps/web muda.--non-interactive é obrigatório em CI - sem prompts.| Segredo | Onde | Usado para |
|---|---|---|
EXPO_TOKEN | GitHub Secrets | eas build, submit, update, execuções de fluxo de trabalho |
NPM_TOKEN | GitHub Secrets | Pacotes privados durante npm ci |
| Chave de API do App Store Connect | Credenciais EAS | Envio iOS - não duplicado no GitHub se usar EAS Submit |
| Conta de serviço Play JSON | Credenciais EAS | Envio Android |
Crie EXPO_TOKEN a partir de um token de acesso robô ou CI do Expo - não um token pessoal de desenvolvedor vinculado a sessões 2FA.
# Verifique o token localmente antes de adicionar ao GitHub
EXPO_TOKEN=xxx npx eas-cli@latest whoami| Input | Propósito |
|---|---|
eas-version | Fixar CLI (latest ou 16.x.x) |
token | Mapeia para EXPO_TOKEN |
eas-cache | Cache do download do EAS CLI entre jobs |
packager | npm / yarn / pnpm - corresponder ao repositório |
# npm - mais simples
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
# Monorepo - apontar cache para lockfile raiz
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
cache-dependency-path: package-lock.json
# Cache remoto do Turborepo (opcional, repositórios maiores)
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}npm ci sempre - não npm install - o lockfile é o contrato| Padrão | Prós | Contras |
|---|---|---|
paths: em on.pull_request | Nativo do GitHub, zero dependências | Grosso - perde renomeações de pacotes compartilhados |
dorny/paths-filter | Saídas booleanas por job | Dependência de ação extra |
turbo --filter=[origin/main...] | Apenas afetados em repositórios grandes | Requer configuração de gráfico Turbo |
Sempre execute turbo run lint raiz | Modelo mental simples | Mais lento em PRs apenas de documentação |
Para tags de lançamento, sempre construa a partir da raiz do repositório com npm ci completo - filtros de caminho são otimizações apenas para PRs.
PR aberto → GitHub Actions (lint, tsc, test) ← barato, a cada push
Tag enviada → EAS Workflow (build → Maestro → submit) ← infra nativa, cadeia com portãoquality do Actionstype: build / maestro / submit - EAS WorkflowsEXPO_TOKEN ausente - eas build trava ou solicita e falha. Correção: Segredo da organização disponível para o fluxo de trabalho; verifique com o passo eas whoami.
npm install em CI - Instalações não determinísticas; "funciona no CI, falha localmente." Correção: npm ci quando package-lock.json existe.
Executar submit com --latest após QA testar build mais antigo - Loja recebe binário não testado. Correção: Passe --id <BUILD_ID> da saída do passo de build.
Filtro de caminho ignora lockfile - Aumento de dependência na raiz não aciona verificações móveis. Correção: Inclua package-lock.json / pnpm-lock.yaml nos caminhos do filtro.
Senha do Apple ID no GitHub Secrets - Falha com 2FA; anti-padrão de segurança. Correção: Credenciais gerenciadas pelo EAS + chave de API do App Store Connect.
Sem concurrency em fluxos de trabalho de PR - Seis execuções enfileiradas para pushes rápidos de correção. Correção: cancel-in-progress: true.
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| GitHub Actions + expo-github-action | Portões de PR + lançamentos de tags no GH | Você quer apenas build→Maestro→submit na infraestrutura EAS |
| Apenas EAS Workflows | Casa YAML única no Expo | Você precisa do ecossistema de ações do marketplace do GH |
| Bitrise / CircleCI | Padrão corporativo já pago | Equipe Expo Greenfield - EAS tem menos cerimônia |
eas build local | Emergência única | Trem de lançamento normal - não reproduzível |
GitHub → Settings → Secrets and variables → Actions → EXPO_TOKEN. Para monorepos, segredo em nível de organização compartilhado entre repositórios móveis.
Fixe (16.4.0) para reprodutibilidade; use latest quando quiser correções automáticas do CLI. Alinhe com a dependência de desenvolvimento eas-cli em package.json quando possível.
on:
pull_request:
types: [labeled]
jobs:
preview:
if: contains(github.event.pull_request.labels.*.name, 'eas-preview')Veja Preview Builds on PRs.
- uses: pnpm/action-setup@v4
with: { version: 9 }
- uses: actions/setup-node@v4
with:
node-version: 20
cache: pnpm
- run: pnpm install --frozen-lockfileDefina packager: pnpm em expo-github-action quando aplicável.
Sim - mas você gerencia a inicialização do emulador, a instalação do APK e o cache. O type: maestro do EAS Workflows tem menos cerimônia para equipes Expo - EAS Workflows
turbo run em CIVersões da Stack: Esta página foi escrita para React 19.2.3, React Native 0.86.0 e Expo SDK 57 (
expo~57.0.4).
Revisado por Chris St. John·Última atualização: 16 de jul. de 2026