Se tem uma coisa que todo time mobile aprende tarde demais é que build não é entrega. Você pode ter o melhor app do mundo.
Se o seu pipeline depende de:
- alguém rodar build local
- alguém assinar manualmente
- alguém subir na loja
Você não tem um processo. Você tem um risco operacional. E risco operacional em mobile custa caro, porque erro não volta em minutos — volta em dias.
O que é um pipeline mobile “pronto pra produção” de verdade
Não é só automatizar build.
É garantir que qualquer commit relevante consiga, de forma confiável:
- gerar builds reproduzíveis
- rodar testes essenciais
- versionar automaticamente
- distribuir para QA
- publicar com controle gradual
E, principalmente, permitir rollback sem desespero.
Estrutura do pipeline (visão realista)
Antes de código, pensa no fluxo:
commit → build → testes → assinatura → versionamento → distribuição → store → rollout
Se qualquer etapa depende de humano, você tem um gargalo escondido.
Pipeline Android completo (GitHub Actions)
Agora sim — um exemplo que você colocaria em produção sem medo.
Workflow completo
name: Android Production Pipeline
on:
push:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout do código
uses: actions/checkout@v3
- name: Setup do Java
uses: actions/setup-java@v3
with:
java-version: '17'
- name: Cache do Gradle
uses: actions/cache@v3
with:
path: ~/.gradle
key: gradle-${{ hashFiles('**/*.gradle*') }}
- name: Rodar testes
run: ./gradlew test
- name: Decode do keystore
run: echo "${{ secrets.KEYSTORE_BASE64 }}" | base64 --decode > keystore.jks
- name: Build assinado
run: |
./gradlew bundleRelease \
-Pandroid.injected.signing.store.file=keystore.jks \
-Pandroid.injected.signing.store.password=${{ secrets.KEYSTORE_PASSWORD }} \
-Pandroid.injected.signing.key.alias=${{ secrets.KEY_ALIAS }} \
-Pandroid.injected.signing.key.password=${{ secrets.KEY_PASSWORD }}
- name: Upload para Firebase
uses: wzieba/Firebase-Distribution-Github-Action@v1
with:
appId: ${{ secrets.FIREBASE_APP_ID }}
token: ${{ secrets.FIREBASE_TOKEN }}
groups: testers
file: app/build/outputs/bundle/release/app-release.aab
Esse pipeline já resolve vários problemas reais ao mesmo tempo, porque ele garante que todo build gerado é consistente, testado e distribuído automaticamente, eliminando completamente aquela dependência clássia de “roda aí na sua máquina e me manda o APK”.
Versionamento automático no Android (sem erro humano)
Aqui entra um detalhe que parece pequeno, mas quebra muita pipeline em produção.
Gradle com versionamento dinâmico
def versionCode = System.getenv("GITHUB_RUN_NUMBER") as Integer ?: 1
android {
defaultConfig {
versionCode versionCode
versionName "2.0.${versionCode}"
}
}
Esse tipo de abordagem resolve um problema crítico: duas builds nunca entram em conflito na Play Store, e você nunca mais precisa lembrar de atualizar versão manualmente — o que, em times grandes, inevitavelmente dá problema.
Pipeline iOS completo (Fastlane + GitHub Actions)
Agora vem a parte onde muita gente sofre mais do que deveria.
Porque iOS não quebra só build.
Ele quebra emocional também 😅
Gerenciamento de certificados com Fastlane Match
Se você ainda gerencia certificado manualmente, você está operando no modo caos.
Configuração do Match
lane :certificates do
match(
type: "appstore",
readonly: false
)
end
Aqui o segredo é simples, mas poderoso: certificados ficam versionados (criptografados) e sincronizados entre o time e o pipeline, eliminando completamente aquele cenário clássico de “funciona na máquina do iOS guy”.
Build e distribuição com Fastlane
Lane completa
lane :release do
match(type: "appstore")
build_app(
scheme: "MyApp",
export_method: "app-store"
)
upload_to_testflight
end
Esse fluxo garante que o build já sai pronto para TestFlight, sem intervenção manual, o que reduz drasticamente o tempo entre commit e validação real por usuários internos.
Pipeline iOS no GitHub Actions
name: iOS Production Pipeline
on:
push:
branches: [ "main" ]
jobs:
build:
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Instalar dependências
run: |
brew install fastlane
bundle install
- name: Rodar testes
run: fastlane test
- name: Build e deploy
run: fastlane release
Esse pipeline, apesar de parecer simples, encapsula uma complexidade absurda que normalmente ficaria espalhada em máquinas locais, scripts improvisados e conhecimento tribal dentro do time.
Distribuição contínua: QA nunca mais espera build
Aqui está uma mudança de mentalidade importante: QA não deveria pedir build.
Build deveria chegar automaticamente.
No Android, usamos Firebase App Distribution.
No iOS, usamos TestFlight.
E o impacto disso no fluxo do time é enorme, porque elimina completamente gargalos de comunicação e espera entre desenvolvimento e validação.
Publicação com rollout gradual (produção sem pânico)
Publicar mobile direto pra 100% dos usuários é pedir problema.
Um pipeline maduro precisa suportar rollout controlado.
Estratégia real
- 5% dos usuários inicialmente
- monitoramento de crash e métricas
- aumento progressivo
Isso não é só técnica.
É gestão de risco aplicada ao software.
Feature flags: desacoplando deploy de release
Aqui está o nível que poucos times atingem.
Exemplo com Remote Config
const isNewFeatureEnabled = await remoteConfig.getBoolean('new_feature')
if (isNewFeatureEnabled) {
enableNewFeature()
}
Isso permite algo poderoso: você pode ter código em produção que ainda não está ativo, e ativar ou desativar funcionalidades sem depender de aprovação da loja.
O que esse pipeline resolve de verdade
Quando você junta tudo isso, você elimina:
- builds inconsistentes
- erros de versão
- dependência de máquina local
- gargalos humanos
- medo de deploy
E substitui por:
- previsibilidade
- automação
- confiança
O mindset que muda o jogo
CI/CD mobile não é sobre ferramenta. É sobre remover variáveis humanas do processo. Porque quanto mais o seu pipeline depende de pessoas, mais ele depende de erro.
Um pipeline mobile pronto pra produção não é aquele que “funciona”. É aquele que:
- qualquer dev consegue usar
- qualquer build é reproduzível
- qualquer release é previsível
- qualquer problema é reversível
Se hoje o seu time ainda depende de “quem sabe subir pra loja”, “quem tem o certificado” e “quem sabe rodar o build certo”, então você não tem um pipeline. Você tem um ponto único de falha.




