Publicação automática de um app flutter na PlayStore com Github Actions
Tags: github, flutter, devops, gha
Published: 2021-11-01 00:02:16

O objetivo desse post é detalhar o passo a passo para publicar uma aplicação Flutter na Play Store.

## Publicação da 1ª release do app

A primeira publicação deve ser feita manualmente e só depois de aprovado pela PlayStore que será possível fazer o deploy totalmente automatizado.

### 1. Crie a chave no Android Studio

Abra o Android Studio, acesse `Build/Generate Signed Bundle or Apk`, na próxima tela escolha `Android App Bundle` e clique em Next. Clique em `Create new...` para criar uma key store nova.

Lembre-se de guardar o conteúdo que for utilizado nos campos de senha e no campo `Alias`. Você vai precisar deles depois.
A imagem abaixo mostra um exemplo de como preencher os dados.

![Geração da chave](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/61qq7msloa0yqezlbkv6.png)

### 2. Gere o base64 da chave

Após concluir a geração da chave, abra o terminal do seu SO e execute os comandos abaixo. Obs: Se estiver no Windows, talvez precise instalar o openssl antes. Talvez esse [link do StackOverflow](https://stackoverflow.com/questions/50625283/how-to-install-openssl-in-windows-10) possa te ajudar.

Uma vez que você esteja com o arquivo myapp.jks disponível, execute o comando:

``` shell
openssl base64 < myapp.jks | tr -d '\n' | tee myapp.jks.base64.txt
```

Assim como as senhas e o Alias, você vai precisar do conteúdo desse arquivo quando for configurar os secrets do pipeline.

### 3. Crie um pipeline de build no gha

Nesse primeiro momento, o pipeline fará apenas o build do arquivo `.aab`, sem fazer o deploy para a Play Store.

O objetivo desse pipeline é criar o `.aab` assinado que você usará para subir na PlayStore. Mas você pode fazer isso pelo seu ambiente de desenvolvimento se quiser. Particularmente eu prefiro gerar pelo GhA para já testar essa etapa do script.

``` yaml
name: Build

on:
  push:
    branches:
      - main

# the follow line allow this script to be started manually.
  workflow_dispatch:

jobs:
  build:
    # This job will run on ubuntu virtual machine
    runs-on: ubuntu-latest
    steps:
      # Setup Java environment in order to build the Android app.
      - uses: actions/checkout@v1
      - uses: actions/setup-java@v1
        with:
          java-version: "12.x"

      # Setup the flutter environment.
      - uses: subosito/flutter-action@v1
        with:
          # channel: 'beta' # 'dev', 'alpha', default to: 'stable'
          flutter-version: "2.2.3" # you can also specify exact version of flutter

      # Get flutter dependencies.
      - run: flutter pub get

      # Build appbundle.
      - run: flutter build appbundle --target-platform android-arm,android-arm64,android-x64 --no-sound-null-safety

      - run: zip -d build/app/outputs/bundle/release/app-release.aab META-INF/\*

      - uses: r0adkll/sign-android-release@v1
        name: Sign app APK

        id: sign_app # ID used to access action output
        with:
          releaseDirectory: build/app/outputs/bundle/release
          signingKeyBase64: ${{ secrets.KEY }}
          alias: ${{ secrets.ALIAS }}
          keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}
          keyPassword: ${{ secrets.KEY_PASSWORD }}

      # Upload generated apk to the artifacts.
      - uses: actions/upload-artifact@v1
        name: Upload Artifact
        with:
          name: release-aab
          path: build/app/outputs/bundle/release/app-release.aab
``` 

### 4. Configure os secrets do pipeline

Com o script criado, você vai precisar configurar as secrets. É nesse momento que você vai precisar das informações geradas nos passos 1 e 2.

Pelo site do Github, vá no repositório do projeto e acesse o menu `Settings -> Secrets`, abrirá uma página como da imagem abaixo.

![Repositório sem nenhuma secret criada](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mlr53anxbxcpynr0yrqc.png)

Cadastre as secrets conforme as orientações abaixo:

- KEY: conteúdo do arquivo myapp.jks.base64.txt
- ALIAS: o valor que você preencheu ao criar a chave
- KEY_STORE_PASSWORD: a senha que você usou ao criar a chave
- KEY_PASSWORD: a senha que você usou ao criar a chave

Com todos os passos realizados, você deve ser capaz de executar seu pipeline com sucesso e isso irá gerar um arquivo `.zip` composto do seu `.aab`.

![Resultado do build](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6y92y22jzvgx7874ihnh.png)

### 5. Crie um app dentro da Play Store Console

Acesse a [Play Store Console](https://play.google.com/console/about/) e faça a criação do App.

Esse passo não será detalhado, porque cada tipo de aplicativo segue um fluxo diferente, podendo mudar de acordo com o público, o conteúdo, entre outros aspectos, portanto, siga os passos de acordo com as orientações da Play Store.

Quando terminar, você estará em um ponto onde será necessário subir o primeiro release do app, nesse ponto, suba o arquivo `.aab` gerado no passo anterior, suba as imagens de divulgação e envie seu release para aprovação.

Essa primeira aprovação pode demorar muitas horas, não tem muito o que fazer, apenas aguardar.

## Publicação da 2ª release em diante

Legal, agora que seu app está publicado, altere o pipeline para fazer as publicações de forma automática para você.

### 1. Inclua autenticação na Play Store

Para fazer a autenticação, você vai precisar de uma `Service Account` com acesso para fazer publicações em seu nome na Play Store. Para criar uma siga os passos da [documentação do Android](https://developers.google.com/android/management/service-account).

### 2. Crie a Secret no GhA

Para usar de forma segura sua service account, suba o conteúdo do json em uma secret chamada `SERVICE_ACCOUNT`.

Aproveite que já está nas secrets e adicione uma nova secret chamada PACKAGE_NAME e informe o valor do `applicationId` do seu projeto. Essa informação fica no arquivo `android/app/build.gradle`. Ex: `com.example.myapp`

### 3. Altere o script

Adicione os passos a seguir para incluir a publicação na Play Store.

``` yaml
      - name: Create service_account.json
        id: createServiceAccount
        run: echo '${{ secrets.SERVICE_ACCOUNT }}' > service_account.json

      - name: Deploy to Play Store (Production)
        id: deploy
        uses: r0adkll/upload-google-play@v1.0.12
        with:
          serviceAccountJson: service_account.json
          packageName: {{ secrets.PACKAGE_NAME }}
          releaseFiles: build/app/outputs/bundle/release/app-release.aab
          whatsNewDirectory: whatsnew/
```

Acesse a documentação da task [r0adkll/upload-google-play](https://github.com/r0adkll/upload-google-play) para entender melhor como funciona a configuração do whatsNewDirectory.

## Conclusão

Não sei vocês, mas eu fico fascinado quando consigo automatizar tarefas massantes como essa. E com todos esses passos realizados, você deve ser capaz de liberar novas versões desse aplicativo de forma automatizada, aproveite o tempo extra para tomar um café, você merece.

> Não seja como eu e lembre-se de atualizar o `pubspec.yaml` com a versão correta, se tentar submeter duas versões com mesmo número, sua publicação falhará.

Veja que após a primeira publicação, a tarefa que faz upload dos artefatos passa a ser desnecessária, minha recomendação é que você apenas comente ela, para que possa usar em outros aplicativos no futuro.