Executando verificação de segurança...
11

Criando um fluxo de CI/CD completo para apps Flutter com GitHub Actions e Firebase App Distribution

A cada semana surgem novas ferramentas, mas a dor de distribuir versões de teste continua a mesma: alguém envia um .apk no grupo do WhatsApp, outra pessoa instala a versão errada e, quando o bug é reportado, ninguém sabe exatamente qual commit ele está usando.
A boa notícia é que o Flutter, o GitHub Actions e o Firebase App Distribution formam uma tríade que resolve esse problema de forma gratuita e automatizada. A receita abaixo leva menos de 30 minutos para rodar e, depois de configurada, publica um .apk novo no grupo de teste toda vez que você der git push.

Por que Flutter + GitHub Actions + Firebase?

  • Flutter: um único código, builds para Android e iOS.
  • GitHub Actions: funciona dentro do seu repositório, não precisa de servidor extra.
  • Firebase App Distribution: disponibiliza builds internas para testadores com um link simples — sem Google Play ou TestFlight.

Essa combinação é tão eficaz que muitas empresas deixaram de usar o Fastlane para casos mais simples. A configuração é direta e, mantendo-se no plano Spark (gratuito) do Firebase, não gera custos.

Passo a passo em 5 etapas

1. Preparando o app e o Firebase

  1. No Firebase Console crie um projeto novo ou selecione um já existente.
  2. Adicione os aplicativos Android e iOS com os pacotes corretos (com.suaempresa.nomeapp).
  3. Baixe os arquivos google-services.json (Android) e GoogleService-Info.plist (iOS) e deixe-os na raiz dos respectivos módulos dentro do projeto Flutter.

Dica de segurança: em vez de commitar os arquivos de configuração, use as secrets do GitHub para armazenar o conteúdo dos arquivos como variáveis de ambiente. Assim você evita expor IDs privados no histórico do git.

2. Gerando uma chave de upload para Android

O Firebase App Distribution aceita .apk ou .aab. Para equipes pequenas, o .apk costuma ser suficiente.

# Dentro do diretório android
keytool -genkey -v -keystore upload-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload

Coloque o arquivo upload-keystore.jks na pasta android/app e crie um arquivo key.properties:

storePassword=SENHA
keyPassword=SENHA
keyAlias=upload
storeFile=upload-keystore.jks

Adicione essas senhas como secrets também (KEYSTORE_PASSWORD, KEY_PASSWORD, KEY_ALIAS).

3. Workflow básico no GitHub Actions

Crie .github/workflows/deploy.yml:

name: Deploy to Firebase App Distribution

on:
  push:
    branches: [ develop ]   # ou outra branch de teste

jobs:
  build-android:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4
      - uses: subosito/flutter-action@v2
        with:
          flutter-version: '3.19.6'   # ou a versão que seu projeto usa
          channel: 'stable'

      - name: Flutter pub get
        run: flutter pub get

      - name: Build APK
        run: flutter build apk --release

      - name: Upload to Firebase App Distribution
        uses: wzieba/Firebase-Distribution-Github-Action@v1
        with:
          appId: ${{ secrets.FIREBASE_ANDROID_APP_ID }}
          token: ${{ secrets.FIREBASE_TOKEN }}
          groups: testers
          file: build/app/outputs/flutter-apk/app-release.apk

Como gerar FIREBASE_TOKEN? No terminal:

npm install -g firebase-tools
firebase login:ci

Copie o token e guarde como FIREBASE_TOKEN nas secrets do repositório.

4. Agrupando testadores

No Firebase Console, clique em App Distribution → Testers & Groups → New Group. Crie um grupo chamado testers e adicione os e-mails. Toda vez que o workflow rodar, cada pessoa receberá um e-mail ou notificação no aplicativo Firebase com link direto para instalar.

5. Evoluindo: separando builds de homologação e produção

Após validar o fluxo básico, crie dois workflows:

  • deploy-dev.yml: dispara em pushes para develop, gera .apk com sufixo -dev no nome.
  • deploy-release.yml: dispara ao criar uma tag que comece com v, gera .aab e sobe para a Google Play internamente (usando o mesmo token do Firebase).

Exemplo de condição no YAML:

on:
  push:
    tags:
      - 'v*'

Dessa forma, ninguém manda build de release sem querer.

Dicas para evitar surpresas na semana de lançamento

  1. Cache de dependências
    Adicione o seguinte no workflow para economizar 3-4 minutos por execução:

    - name: Cache Flutter
      uses: actions/cache@v4
      with:
        path: |
          ~/.pub-cache
          build/
        key: ${{ runner.os }}-flutter-${{ hashFiles('**/pubspec.lock') }}
    
  2. Notificações no Slack
    Configure um step final para postar no canal avisando que um novo build está disponível.

    - name: Notify Slack
      run: |
        curl -X POST \
        -H 'Content-type: application/json' \
        --data '{"text":"📦 APK novo enviado para teste: ${{ github.sha }}"}' \
        ${{ secrets.SLACK_WEBHOOK }}
    
  3. Teste de regressão automática
    Antes do upload, execute flutter test integration_test para garantir que a build não quebrou funcionalidades críticas.

Resultado prático no dia a dia

Depois de implementar esse fluxo, o seu time:

  • Nunca mais precisa abrir o Android Studio para gerar APK.
  • Sabe exatamente qual commit está em cada build disponibilizada.
  • Recebe feedback por meio de crashlytics e performance monitoring automaticamente atrelados ao número da versão.
  • Consegue entregar hotfixes em minutos, basta fazer git cherry-pick e dar push.

Mesmo que Google ou Apple lancem novos requisitos de loja amanhã, a infra que você construiu hoje continuará funcional: basta ajustar o step de build ou adicionar mais secrets. Em outras palavras, o ganho é atemporal — e, para quem ainda envia .apk no WhatsApp, representa um salto de qualidade imediato.

Carregando publicação patrocinada...
1

Legal, poderia fazer um post ensinando como enviar para play store e app store usando git actions, até hj não consegui fazer essa coisa funfar e estou postergando, kkkkk. Já tentei várias soluções e meio q desisti.
Atualmente criei um script em bash msm para automatizar o build e testes na minha máquina local, mas a parte da entrega ainda faço de modo manual, só isso demora um pouco.