Mobile

9 abr, 2026

Pipeline Android + iOS pronto pra produção (sem gambiarra)

Publicidade

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.