Builds de Preview em PRs
Um guia para distribuição via QR code de builds de preview do EAS em pull requests - para que design e QA possam revisar em dispositivos reais antes do merge.
Busque em todas as páginas da documentação
Um guia para distribuição via QR code de builds de preview do EAS em pull requests - para que design e QA possam revisar em dispositivos reais antes do merge.
Cartão de receita de referência rápida - pronto para copiar e colar.
// eas.json - perfil de preview
{
"build": {
"preview": {
"distribution": "internal",
"channel": "preview",
"android": { "buildType": "apk" },
"ios": { "simulator": false }
}
}
}# .github/workflows/preview-pr.yml
name: Preview Build
on:
pull_request:
types: [labeled]
jobs:
preview:
if: contains(github.event.pull_request.labels.*.name, 'needs-preview')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: expo/expo-github-action@v8
with:
eas-version: latest
token: ${{ secrets.EXPO_TOKEN }}
- run: npm ci
- id: build
run: |
eas build --profile preview --platform android --non-interactive --json > build.json
echo "url=$(jq -r '.[0].artifacts.buildUrl' build.json)" >> $GITHUB_OUTPUT
- uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## 📱 Preview build\n\nInstall: ${{ steps.build.outputs.url }}\n\nScan QR on device or open link.`
})Quando usar isso:
Estrutura do projeto:
your-expo-app/
.github/workflows/preview-pr.yml
.eas/workflows/preview-pr.yml # alternativa opcional nativa do EAS
eas.json
app.json{
"build": {
"preview": {
"distribution": "internal",
"channel": "preview",
"env": {
"APP_VARIANT": "preview"
},
"android": {
"buildType": "apk"
},
"ios": {
"simulator": false
}
},
"preview-simulator": {
"distribution": "internal",
"ios": { "simulator": true },
"android": { "buildType": "apk" }
}
}
}// app.config.ts - banner de variante opcional
const IS_PREVIEW = process.env.APP_VARIANT === "preview";
export default {
expo: {
name: IS_PREVIEW ? "MyApp (Preview)" : "MyApp",
// ...
},
};name: Preview on PR
on:
pull_request:
types: [opened, synchronize, labeled]
concurrency:
group: preview-${{ github.event.pull_request.number }}
cancel-in-progress: true
jobs:
preview:
if: contains(github.event.pull_request.labels.*.name, 'needs-preview')
runs-on: ubuntu-latest
permissions:
pull-requests: write
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
- name: EAS preview build
id: eas
run: |
eas build \
--profile preview \
--platform android \
--non-interactive \
--json > build-output.json
BUILD_URL=$(jq -r '.[0].artifacts.buildUrl // .artifacts.buildUrl' build-output.json)
QR_URL=$(jq -r '.[0].artifacts.applicationArchiveUrl // empty' build-output.json)
echo "build_url=$BUILD_URL" >> $GITHUB_OUTPUT
- name: Comment on PR
uses: actions/github-script@v7
with:
script: |
const url = '${{ steps.eas.outputs.build_url }}';
const body = [
'## 📱 Android preview build',
'',
`**Install:** ${url}`,
'',
'1. Open the link on your Android device',
'2. Scan the QR code or download the APK',
'3. Allow install from unknown sources if prompted (internal testing only)',
'',
'_Built from commit `${{ github.sha }}` with profile `preview`._'
].join('\n');
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body
});# .eas/workflows/preview-pr.yml
name: Preview PR
on:
pull_request:
types: [labeled]
jobs:
quality:
if: ${{ github.event.pull_request.labels.*.name contains 'needs-preview' }}
steps:
- uses: eas/checkout
- uses: eas/install_node_modules
- run: npm run typecheck
build_preview:
needs: [quality]
type: build
params:
platform: android
profile: previewExecute manualmente ao testar:
npx eas-cli@latest workflow:run .eas/workflows/preview-pr.ymlO que isso demonstra:
distribution: internal - O EAS hospeda a página de instalação com QR code (Distribuição Interna).buildType: apk no Android - instalação manual sem a trilha interna do Play.needs-preview consomem créditos de build.| Plataforma | Perfil de Preview | Instalador | Ideal para |
|---|---|---|---|
| Android | apk + internal | Link QR / APK | QA em dispositivos físicos |
| Dispositivo iOS | ad hoc / internal | QR via EAS | UDIDs registrados |
| iOS | simulator: true | Tar .app | Designer no simulador do Mac |
| Ambos | + channel: preview | + eas update opcional | Correção JS no mesmo binário de preview |
# Controlado por rótulo (recomendado)
if: contains(github.event.pull_request.labels.*.name, 'needs-preview')
# Filtro de caminho - apenas alterações que impactam o nativo
on:
pull_request:
paths:
- "app/**"
- "src/**"
- "app.config.ts"
- "plugins/**"| Estratégia | Custo de Crédito | Risco |
|---|---|---|
| Cada push de PR | Alto | Melhor cobertura |
Rótulo needs-preview | Baixo | Requer disciplina |
| Filtro de caminho | Médio | Perde alterações em pacotes compartilhados se o filtro for muito restrito |
Documente em CONTRIBUTING.md:
## Builds de preview
Adicione o rótulo `needs-preview` quando QA ou design precisar de um build para dispositivo.
**Não** adicione para alterações apenas de cópia ou apenas de teste.Após o binário de preview existir, correções em JS podem ser enviadas sem reconstruir:
eas update --channel preview --message "PR-${{ github.event.pull_request.number }}"runtimeVersion - Política de Versão de RuntimeQuando houver alterações de navegação, execute um fluxo leve do Maestro no build_id de preview antes do merge:
maestro_smoke:
needs: [build_preview]
type: maestro
params:
build_id: ${{ needs.build_preview.outputs.build_id }}
flow_path: [".maestro/smoke.yml"]Preview em cada commit - Esgotamento de créditos do EAS no meio do sprint. Solução: Gatilho por rótulo + cancelamento de concorrência.
Preview iOS sem dispositivos registrados - Build ad hoc não instala em lugar nenhum. Solução: Mantenha a lista de dispositivos no portal Apple Developer ou use o perfil de simulador para designers.
QA testa o Expo Go - Bundle ID e módulos nativos diferem do build de preview. Solução: Sempre distribua o link do artefato EAS.
Comentário de PR desatualizado - Link de instalação antigo após rebase. Solução: Edite o comentário ou poste um novo comentário por build; inclua github.sha no corpo.
Credenciais de produção no perfil de preview - Assinatura acidental na loja no branch de feature. Solução: Perfil preview separado sem chaves de produção autoIncrement.
Permissão pull-requests: write ausente - O passo de comentário falha silenciosamente ou gera erro. Solução: Adicione o bloco permissions no workflow.
| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| Distribuição interna EAS QR | Padrão para QA em dispositivo | Você precisa de rollout faseado na trilha interna do Play |
eas update no canal de preview | Ajustes de PR apenas em JS | Novo módulo nativo adicionado |
| TestFlight externo + número do PR | Equipe com foco em iOS já usa ASC | Feedback rápido de APK Android necessário |
| Apenas testes de screenshot | Layout/cópia pura | Gestos, câmera, haptics |
Abra o link da página de build do EAS do comentário do PR → escaneie o QR code → instale o APK. Habilite "instalar apps desconhecidos" para o navegador, se solicitado.
eas build --profile preview --platform all --non-interactiveCusta dois builds; comente ambos os links ou construa apenas Android para feedback mais rápido.
Use o perfil preview-simulator - baixe o build do simulador; o designer executa no simulador do Xcode.
Defina env.API_URL no perfil de preview para o ambiente de staging - nunca aponte builds de preview para APIs de escrita de produção.
Versõ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