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

CI/CD Flutter: do push ao envio nas lojas com GitHub Actions e Fastlane

Este post nasceu a partir de um comentário no meu artigo anterior:

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

"Legal, poderia fazer um post ensinando como enviar para Play Store e App Store usando GitHub Actions… até hoje não consegui fazer essa coisa funfar e estou postergando…"

Missão aceita. Vamos criar um pipeline completo: do push no GitHub até a publicação automática do app nas lojas.


Pré-requisitos

Antes de tudo, é necessário:

  • Projeto Flutter com build release funcionando para Android e iOS.
  • Conta no Google Play Console, app criado e chave de acesso via Service Account (JSON).
  • Conta de desenvolvedor Apple, app registrado no App Store Connect, API Key configurada.
  • Secrets configurados no GitHub:
    • PLAY_STORE_KEY: chave JSON do Google Play codificada em base64.
    • APP_STORE_API_KEY_ID, APP_STORE_ISSUER_ID, APP_STORE_API_KEY: credenciais da Apple.
    • MATCH_PASSWORD: senha do repositório de certificados (caso use match).

Ferramentas utilizadas

  • GitHub Actions: automação do build e deploy via YAML.
  • Fastlane: automação de publicação nas lojas.
  • Flutter: build dos binários .aab e .ipa.

Estrutura esperada no projeto

No seu repositório Flutter, crie os diretórios de Fastlane:

cd android && fastlane init
cd ../ios && fastlane init

Você vai editar os arquivos android/fastlane/Fastfile e ios/fastlane/Fastfile.


Pipeline Android — Play Store

Exemplo de Fastfile (Android)

default_platform(:android)

platform :android do
  desc "Deploy para o Google Play"
  lane :beta_release do
    upload_to_play_store(
      track: 'internal',
      json_key: 'playstore.json',
      aab: '../build/app/outputs/bundle/release/app-release.aab',
      skip_upload_metadata: true,
      skip_upload_changelogs: true,
      skip_upload_images: true,
      skip_upload_screenshots: true
    )
  end
end

Workflow no GitHub Actions

name: Deploy Android

on:
  push:
    tags:
      - 'v*'

jobs:
  deploy-android:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: subosito/flutter-action@v2
        with:
          flutter-version: '3.19.6'

      - run: flutter pub get
      - run: flutter build appbundle --release

      - name: Decode Play Store key
        run: echo "$PLAY_STORE_KEY" | base64 --decode > android/fastlane/playstore.json
        env:
          PLAY_STORE_KEY: ${{ secrets.PLAY_STORE_KEY }}

      - name: Setup Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: '3.2'

      - name: Install Fastlane
        run: gem install fastlane

      - name: Deploy to Play Store
        working-directory: android
        run: fastlane beta_release

Pipeline iOS — App Store / TestFlight

Exemplo de Fastfile (iOS)

default_platform(:ios)

platform :ios do
  desc "Deploy para TestFlight"
  lane :testflight do
    build_app(
      scheme: "Runner",
      export_method: "app-store"
    )
    upload_to_testflight
  end
end

Workflow no GitHub Actions

name: Deploy iOS

on:
  push:
    tags:
      - 'v*'

jobs:
  deploy-ios:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v4

      - uses: subosito/flutter-action@v2
        with:
          flutter-version: '3.19.6'

      - run: flutter pub get
      - run: flutter build ios --release --no-codesign

      - name: Setup Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: '3.2'

      - name: Install Fastlane
        run: gem install fastlane

      - name: Setup App Store Connect API key
        run: |
          mkdir -p ~/.appstoreconnect
          echo "${{ secrets.APP_STORE_API_KEY }}" > ~/.appstoreconnect/AuthKey_${{ secrets.APP_STORE_API_KEY_ID }}.p8

      - name: Deploy to TestFlight
        working-directory: ios
        run: fastlane testflight
        env:
          APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.APP_STORE_API_KEY_ID }}
          APP_STORE_CONNECT_API_ISSUER_ID: ${{ secrets.APP_STORE_API_ISSUER_ID }}

Conclusão

Com este fluxo completo, você poderá publicar seus apps diretamente nas lojas com um simples push de tag. É segurança, controle e velocidade no seu pipeline de entrega!

Tem dúvidas ou sugestões? Comenta aqui embaixo! 👇

Referências

Flutter + GitHub Actions

Fastlane

App Store Connect (Apple)

Google Play Console

Outros conteúdos úteis

Carregando publicação patrocinada...
1

Eita q legal, ahahah. Já deixei anotado aqui uma task para finalizar o CI/CD dos meus apps.
Dei uma rápida olhada, vc separou em 2 workflow diferente, não sei pq não tinha pensado nisso. O q estava tentando fazer antes era criar um workflow e a partir dele só separar um novo workflow para o deploy do ios. Mas imagino agora q se usar o msm tag para ativar, ele irá ativar os 2.