Elevar CI en github para Android en un día

¡Hola!

Con el advenimiento de Github Actions, tomó la iniciativa e integró el CI / CD simple (pero bastante efectivo) en nuestro pequeño, pero ya de 2 años, proyecto Flowwow en vivo .

¿Para qué?



Tal vez hay algunos desarrolladores que no cometen errores, pero aquí no soy uno de ellos, así que ocasionalmente, pero ocurren pequeñas explosiones y hay que lanzar urgentemente una nueva versión con edición o revertir a la versión anterior. Pero esas horas-días en que los usuarios tropiezan con bloqueos de aplicaciones no se quedan sin rastros tanto entre los clientes como en el estado de ánimo de un desarrollador responsable.

Cómo minimizar el fakapy en la producción, lo diré a continuación.

¿Por qué personalmente tengo ese fakap?

  1. Fragmento de código inseguro
  2. Trajeron una biblioteca y se bloquea situacionalmente
  3. Se actualizó alguna biblioteca (generalmente análisis) a una versión inestable

Con 1 punto, revisión de código, pruebas unitarias, análisis de código estático, pruebas de IU, pruebas manuales nos ayudarán.

Con 2-3 puntos: solo pruebas de IU y pruebas manuales.

Solo queda automatizar esto. En esta etapa, la elección recayó en las acciones de Github que aparecieron en ese momento , el beneficio y el código del proyecto están en Github. Debo decir de inmediato, para una cuenta de github gratuita, hay 2,000 minutos de acción gratis por mes.

¿Donde empezar?


Está lleno de ejemplos listos para varios lenguajes y marcos. Esto se configura a través del archivo de configuración YAML , que se encuentra en el repositorio del proyecto.



Ejemplo 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

Descripción: por cada impulso, se inicia una tarea en cualquier rama de la máquina virtual github con ubuntu OS. Pasos de la tarea: verifique nuestro código, configure jdk, ejecute tareas de gradle para el ensamblaje.

En caso de que un paso no sea exitoso, veremos una imagen de



este tipo donde puede ver los registros.

Es conveniente que con Pull Request se nos muestre de inmediato que nuestra secuencia de prueba ha fracasado.



Y si tiene la integración de Github con Slack, entonces también es



Ahora punto por punto


1. Pruebas unitarias

Usted escribió pruebas unitarias usando junit, mockito, etc.

Ahora sus pruebas están incluidas en la secuencia de prueba agregando la tarea gradle adecuada.

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

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

Puede usar linters simples ( detekt - para kotlin, pmd - para java).
O una opción más complicada es sonarqube .

En el caso de linters simples (por ejemplo, tenemos java y kotlin):

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

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

en caso de sonarqube - más sobre afinación - aquí

- 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. Pruebas de IU

Escribir una prueba de IU es producto de su imaginación, mi enfoque es una prueba de "humo" que imita las acciones estándar del usuario en la aplicación: inicie sesión, seleccione un producto, haga un pedido, haga un seguimiento del pedido. Puede usar UIAutomator, Espresso, Kaspresso.

También hay 2 opciones para iniciar aquí: un emulador en una máquina virtual github o servicios en la nube como Firebase Test Lab.
Para usar el emulador dentro de github, hay implementaciones listas para usar: una y dos .

En el caso de Firebase Test Lab, debe trabajar con Google Cloud Platform a través de la CLI de 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 esto funcione, debe crear un proyecto en Firebase, crear una cuenta de servicio con derechos de administrador en Google Cloud Console y cargar la clave json recibida en base64 en los secretos de github para su autorización en gcloud .

La configuración general en mi caso se veía así. La tarea se desencadena por el evento PR en master

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 simple La eficiencia depende de las pruebas escritas y las reglas de análisis de código seleccionadas. Puede escribir varias tareas independientes (trabajo) para ejecutarlas en paralelo. En mi caso, todo va secuencialmente. El proceso de verificación tarda unos 15 minutos en nuestro proyecto (máquina virtual github CPU de 2 núcleos, 7 GB de RAM, 14 GB de SSD), pero no es realmente crítico, siempre y cuando lo "codifique" con los ojos, los resultados de estas pruebas también llegan.

Las pruebas de IU son las que más ayudan: sucede que durante su aprobación los análisis se bloquean después de actualizar la biblioteca y usted comprende que no vale la pena actualizarla.

A través de gcloud, también puede entregar compilaciones a Distribución de aplicaciones Firebase, lanzamiento a Google Play, etc.

Muchos ejemplos útiles se pueden ver aquí y aquí .
Espero que este artículo sea útil para alguien. ¡Buena suerte y menos accidentes en la producción!

All Articles