CI auf Github für Android an einem Tag erhöhen

Hallo!

Mit dem Aufkommen von Github Actions ergriff er die Initiative und integrierte eine einfache (aber recht effektive) CI / CD in unser kleines, aber bereits 2 Jahre altes Live- Flowwow- Projekt .

Wozu?



Vielleicht gibt es einige Entwickler, die keine Fehler machen, aber hier bin ich nicht einer von ihnen, so gelegentlich, aber so kleine Absturzausbrüche passieren und Sie müssen dringend eine neue Version mit Bearbeitung oder Rollback auf die vorherige Version veröffentlichen. Die Stunden, an denen Benutzer auf App-Abstürze stoßen, bleiben jedoch nicht spurlos, sowohl bei den Kunden als auch in der Stimmung eines verantwortungsbewussten Entwicklers.

Wie man die Fälschung in der Produktion minimiert, werde ich weiter unten erläutern.

Warum habe ich persönlich so einen Fakap?

  1. Unsicheres Code-Snippet
  2. Sie haben eine Bibliothek mitgebracht und sie stürzt situativ ab
  3. Einige Bibliotheken (normalerweise Analysen) wurden auf eine instabile Version aktualisiert

Mit 1 Punkt helfen uns Codeüberprüfung, Unit-Tests, statische Code-Analyse, UI-Tests und manuelle Tests.

Mit 2-3 Punkten - nur UI-Tests und manuelle Tests.

Es bleibt nur, dies zu automatisieren. Zu diesem Zeitpunkt fiel die Wahl auf die damals gerade erschienenen Github-Aktionen , der Nutzen und der Projektcode liegt bei Github. Ich muss sofort sagen, für ein kostenloses Github-Konto gibt es 2.000 kostenlose Aktionsminuten pro Monat.

Wo soll man anfangen?


Es ist voll von vorgefertigten Beispielen für verschiedene Sprachen und Frameworks. Dieses Ding wird über die YAML- Konfigurationsdatei konfiguriert , die sich im Projekt-Repository befindet.



Minimales Beispiel für 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

Beschreibung: Für jeden Push wird eine Aufgabe in einem beliebigen Zweig der virtuellen Github-Maschine mit Ubuntu-Betriebssystem gestartet . Aufgabenschritte: Überprüfen Sie unseren Code, konfigurieren Sie jdk, führen Sie Gradle-Aufgaben für die Assembly aus.

Im Falle eines erfolglosen Durchgangs eines Schritts sehen wir dort ein solches Bild.



Sie können die Protokolle sehen.

Es ist praktisch, dass mit Pull Request sofort angezeigt wird, dass unsere



Testsequenz fehlgeschlagen ist. Wenn Sie eine Github-Integration mit Slack haben, ist dies auch der Fall



Nun Punkt für Punkt


1. Unit-Tests

Sie haben Unit-Tests mit Junit, Mockito usw. geschrieben.

Jetzt werden Ihre Tests in die Testsequenz aufgenommen, indem Sie die entsprechende Gradle-Aufgabe hinzufügen.

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

2. Statische Code-Analyse

Sie können einfache Linters verwenden ( detekt - für kotlin, pmd - für java).
Oder eine kompliziertere Option ist Sonarqube .

Bei einfachen Lintern (zum Beispiel haben wir sowohl Java als auch Kotlin):

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

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

im Falle von Sonarqube - mehr zum Stimmen - hier

- 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. UI-Tests Das

Schreiben eines UI-Tests ist eine Erfindung Ihrer Fantasie. Mein Ansatz ist ein „Smoke“ -Test, der die Standardaktionen des Benutzers in der Anwendung simuliert - melden Sie sich an, wählen Sie ein Produkt aus, geben Sie eine Bestellung auf, verfolgen Sie die Bestellung. Sie können UIAutomator, Espresso, Kaspresso verwenden.

Hier gibt es auch zwei Optionen zum Starten: einen Emulator auf einer virtuellen Github-Maschine oder Cloud-Dienste wie das Firebase Test Lab.
Um den Emulator in Github zu verwenden, gibt es vorgefertigte Implementierungen: eine und zwei .

Im Fall des Firebase- Testlabors müssen Sie über die gcloud-CLI mit der Google Cloud-Plattform arbeiten

- 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

Damit dies funktioniert, müssen Sie ein Projekt in Firebase erstellen, ein Dienstkonto mit Administratorrechten in der Google Cloud Console erstellen und den empfangenen JSON-Schlüssel in Github-Geheimnissen zur Autorisierung in gcloud auf base64 hochladen .

Die allgemeine Konfiguration in meinem Fall sah so aus. Die Aufgabe wird durch das PR- Ereignis im Master ausgelöst

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

Es scheint einfach. Die Effizienz hängt von den schriftlichen Tests und den ausgewählten Regeln für die Codeanalyse ab. Sie können mehrere unabhängige Aufgaben (Job) schreiben, um sie parallel auszuführen. In meinem Fall läuft alles nacheinander. Der Überprüfungsprozess dauert in unserem Projekt ungefähr 15 Minuten (Github-2-Core-CPU für virtuelle Maschinen, 7 GB RAM, 14 GB SSD), ist jedoch nicht wirklich kritisch, solange Sie ihn mit Ihren Augen "codieren". Die Ergebnisse dieser Tests kommen ebenfalls an.

UI-Tests helfen am meisten - es kommt vor, dass die Analyse während des Durchlaufs nach dem Aktualisieren der Bibliothek abstürzt und Sie nur verstehen, dass Sie sie nicht aktualisieren sollten.

Über gcloud können Sie auch Builds für Firebase App Distribution bereitstellen, für Google Play freigeben usw.

Viele nützliche Beispiele sind hier und hier zu sehen .
Ich hoffe, dieser Artikel ist für jemanden nützlich. Viel Glück und weniger Abstürze bei der Produktion!

All Articles