Aumentando o IC no github para Android em um dia

Olá!

Com o advento das ações do Github, ele tomou a iniciativa e integrou um CI / CD simples (mas bastante eficaz) em nosso projeto ao vivo pequeno, mas já com 2 anos de idade, do Flowwow .

Pelo que?



Talvez haja alguns desenvolvedores que não cometem erros, mas aqui não sou um deles, então ocasionalmente, mas essas pequenas explosões acontecem e é necessário lançar urgentemente uma nova versão com edição ou reversão para a versão anterior. Mas as horas-dias em que os usuários tropeçam em travamentos de aplicativos não ficam sem vestígios, tanto entre os clientes quanto no humor de um desenvolvedor responsável.

Como minimizar o fakapy na produção, direi abaixo.

Por que eu pessoalmente tenho esse tipo de fakap?

  1. Snippet de código não seguro
  2. Eles trouxeram alguma biblioteca e ela trava situacionalmente
  3. Atualizadas algumas bibliotecas (geralmente análises) para uma versão instável

Com 1 ponto, revisão de código, testes de unidade, análise de código estático, testes de interface do usuário, teste manual nos ajudarão.

Com 2 a 3 pontos - apenas testes de interface do usuário e testes manuais.

Resta apenas automatizar isso. Nesse estágio, a escolha recaiu sobre as ações do Github que apareceram na época , já que o código do projeto está no Github. Devo dizer imediatamente que, para uma conta gratuita no Github, existem 2.000 minutos de ação grátis por mês.

Onde começar?


Está cheio de exemplos prontos para várias linguagens e estruturas. Essa coisa é configurada através do arquivo de configuração YAML , localizado no repositório do projeto.



Exemplo mínimo para Android:

name: Android CI

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - name: set up JDK 1.8
        uses: actions/setup-java@v1
        with:
          java-version: 1.8
      - name: Build with Gradle
        run: ./gradlew assembleDebug

Descrição: para cada push, uma tarefa é iniciada em qualquer filial da máquina virtual github com o ubuntu OS. Etapas da tarefa: confira nosso código, configure o jdk, execute tarefas gradle para montagem.

Em caso de passagem mal sucedida de uma etapa, veremos uma figura



lá, você pode ver os logs.

É conveniente que, com o Pull Request, seja imediatamente mostrado que nossa sequência de testes fracassou.



E se você tem uma integração do github com o Slack, também é



Agora ponto por ponto


1. Testes de unidade

Você escreveu testes de unidade usando junit, mockito etc.

Agora seus testes estão incluídos na sequência de testes, adicionando a tarefa gradle apropriada.

- name: Run some unit tests
  run: ./gradlew testStageDebugUnitTest

2. Análise de código estático

Você pode usar linters simples ( detekt - para kotlin, pmd - para java).
Ou uma opção mais complicada é sonarqube .

No caso de linters simples (por exemplo, temos java e kotlin):

task("checkAll") {
    group "Verify"
    description "Runs all static checks on the build"
    dependsOn "pmd", "detekt"
}

- name: Run some unit tests
  run: ./gradlew checkAll

no caso de sonarqube - mais sobre ajuste - aqui

- uses: actions/checkout@v1
- name: SonarCloud Scan
   run: ./gradlew jacocoUnitTestReport sonarqube -Dsonar.login=${{ secrets.SONAR_TOKEN }} --stacktrace
   env:
     GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Link to SonarCloud Report
   run: echo "https://sonarcloud.io/dashboard?id=.."

3. Testes de interface do usuário

Escrever um teste de interface do usuário é uma invenção da sua imaginação. Minha abordagem é um teste de "fumaça" que imita as ações padrão do usuário no aplicativo - faça login, selecione um produto, faça um pedido, acompanhe o pedido. Você pode usar UIAutomator, Espresso, Kaspresso.

Existem também duas opções para iniciar aqui - um emulador em uma máquina virtual do github ou serviços em nuvem, como o Firebase Test Lab.
Para usar o emulador no github, existem implementações prontas: uma e duas .

No caso do Firebase Test Lab, você deve trabalhar com o Google Cloud Platform por meio da CLI do gcloud

- name: prepare gcloud
  uses: GoogleCloudPlatform/github-actions/setup-gcloud@master
  with:
    version: latest
    service_account_email:  ${{ secrets.SA_EMAIL }}
    service_account_key: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }}
- name: gcloud Set up project
  run: |
    gcloud config set project ${{ secrets.PROJECT_ID }}
- name: Assemble apks for smoke test
  run: ./gradlew Smoke
- name: Run tests in test lab
  run: |
     gcloud firebase test android run \
       --app app/build/outputs/apk/production/debug/app.apk \
       --test app/build/outputs/apk/androidTest/production/debug/appTest.apk \
       --device model=Nexus6P,version=25,orientation=portrait,locale=en_US \
       --device model=athene,version=23,orientation=portrait,locale=en_US \
       --device model=sailfish,version=26,orientation=portrait,locale=en_US

Para que isso funcione, você precisa criar um projeto no Firebase, criar uma conta de serviço com direitos de administrador no Google Cloud Console e carregar a chave json recebida na base64 nos segredos do github para obter autorização no gcloud .

A configuração geral no meu caso era assim. A tarefa é acionada pelo evento PR no mestre

name: Android CI

on:
  pull_request:
    branches:
      - 'master'

jobs:
  build:

    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v1
      - name: set up JDK 1.8
        uses: actions/setup-java@v1
        with:
          java-version: 1.8
      - name: Run static checks
        run: ./gradlew checkAll
      - name: Run some unit tests
        run: ./gradlew testStageDebugUnitTest

      - name: prepare gcloud
        uses: GoogleCloudPlatform/github-actions/setup-gcloud@master
        with:
          version: latest
          service_account_email:  ${{ secrets.SA_EMAIL }}
          service_account_key: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }}
      - name: gcloud Set up project
        run: |
          gcloud config set project ${{ secrets.PROJECT_ID }}
      - name: Assemble apks for smoke test
        run: ./gradlew Smoke
      - name: Run tests in test lab
        run: |
          gcloud firebase test android run \
            --app app/build/outputs/apk/production/debug/app.apk \
            --test app/build/outputs/apk/androidTest/production/debug/appTest.apk \
            --device model=Nexus6P,version=25,orientation=portrait,locale=en_US \
            --device model=athene,version=23,orientation=portrait,locale=en_US \
            --device model=sailfish,version=26,orientation=portrait,locale=en_US

Parece simples. A eficiência depende dos testes escritos e das regras de análise de código selecionadas. Você pode gravar várias tarefas independentes (tarefa) para executá-las em paralelo. No meu caso, tudo acontece sequencialmente. O processo de verificação leva cerca de 15 minutos em nosso projeto (CPU de dois núcleos da máquina virtual github, 7 GB de RAM, 14 GB de SSD), mas não é realmente crítico, desde que você "codifique" com seus olhos, os resultados desses testes também chegarão.

Os testes de interface do usuário são os que mais ajudam - acontece que durante a passagem deles, a análise falha após a atualização da biblioteca e você entende que não deve atualizá-la.

Através do gcloud, você também pode fornecer versões para o Firebase App Distribution, lançar para o Google Play, etc.

Muitos exemplos úteis podem ser vistos aqui e aqui .
Espero que este artigo seja útil para alguém. Boa sorte e menos falhas na produção!

All Articles