Menggunakan fitur gratis Github Actions for CI / CD pada proyek Flutter

GitHub Actions adalah alat untuk mengotomatiskan tindakan rutin dengan repositori dan membantu Anda membuat CI / CD untuk proyek Anda.



Pengguna GitHub mendapatkan 2000 menit setiap bulan untuk menjalankan GitHub Actions pada infrastruktur layanan. Mari manfaatkan waktu luang ini.



Saya memberikan instruksi untuk pengembang aplikasi Flutter: cara menjalankan pengujian dan penganalisis kode untuk setiap permintaan penarikan menggunakan GitHub Actions, membuat artefak, dan menerapkannya untuk pengujian di Firebase.







Seseorang dengan sangat cepat terbiasa dengan hal-hal yang baik. Dan dia menjadi terbiasa dengan itu sehingga dia bahkan tidak berpikir tentang fakta bahwa tidak selalu seperti ini. Seperti yang dikatakan anekdot lama tentang manusia dan seekor kambing, realisasi dari semua kesenangan hidup terjadi pada saat Anda kehilangan kesenangan ini.



Jika proyek kerja Anda berjalan baik dengan CI / CD, Anda adalah orang yang beruntung.

Mungkin Anda bekerja di startup dan telah mengonfigurasi semua pipeline dan hook dengan tangan Anda sendiri.



Mungkin seluruh tim DevOps menjaga kesejahteraan Anda: setiap bulan hal itu membuat Anda senang dengan integrasi baru, waktu pembuatan yang meleleh di depan mata kami, dan teknik canggih untuk menerapkan rakitan ke semua tempat yang dapat dibayangkan dan tak terbayangkan.



Tidak masalah. Hal utama adalah bahwa Anda selalu yakin bahwa majelis Anda layak, dan pada saat yang sama Anda sendiri terhindar dari banyak tugas rutin yang sangat membosankan, pemikiran yang selalu menjerumuskan pengembang ke dalam kesedihan dan keputusasaan. Ngomong-ngomong, saya akan senang jika Anda menulis di komentar kapan terakhir kali Anda mengubah status masalah di Jira secara manual?



Meninggalkan zona nyaman Anda



Di mana mereka meninggalkan zona nyaman, dan yang terpenting, mengapa? Banyak alasan. Seorang teman meminta saya untuk membantu menulis aplikasi kecil untuk bar Anda sendiri, Anda akhirnya menemukan waktu untuk mengimplementasikan proyek hewan impian Anda, atau memutuskan untuk merilis perpustakaan yang secara tidak sengaja lahir sebagai bagian dari sebuah proyek. Akhirnya, Anda dan rekan Anda baru saja memutuskan untuk menulis proyek contoh kecil untuk lokakarya tersebut.



Saya yakin bahwa dalam skenario mana pun, inspirasi Anda dari tugas baru yang menarik akan dengan cepat bertabrakan dengan kenyataan pahit pengembangan perangkat lunak dalam "lingkungan tanpa udara" (ya, pada titik tertentu Anda akan membutuhkan kolektor yang cerdas seperti udara).



"CI / CD sulit ..."



Apa yang biasanya Anda katakan kepada diri Anda sendiri pada saat-saat seperti itu? β€œSaya tidak mengerti ini! Saya hanya menulis frontend / ponsel dan saya tidak tahu apa-apa tentang Jenkins Anda! " Bagaimana jika saya memberi tahu Anda bahwa Anda tidak perlu tahu yang seperti itu?



Ya, Anda hanya perlu dapat membangun proyek Anda menggunakan perintah konsol - dan hanya itu. Anda dapat sangat menyederhanakan hidup Anda, bahkan jika itu adalah proyek kecil pribadi, dan bukan monster multi-modul raksasa yang sudah sulit untuk mencerna IDE.



Github Actions sangat sederhana bahkan nenek Anda pun akan mengaturnya tanpa banyak kesulitan.



Lalu posting tentang apa?



Jika semuanya begitu sederhana, mengapa membuang waktu membaca karya ini? Saya akan menjawab dengan daftar poin:



  • Flutter. CI . , Flutter- . ,

  • . Github Actions β€”  . 2 000 ( ). - , .

  • . Flutter Android iOS , - . , , , .



c CI/CD , . . ($).


Github Actions, !



Github Actions adalah layanan yang memungkinkan Anda mengotomatiskan alur kerja repositori Anda. Apa pun yang Anda lakukan secara manual dengan proyek Anda - selain menulis kode secara langsung - Anda dapat mendelegasikan ke Github Actions. Jika Anda lebih suka segera berkenalan dengan sumber utama, buka dokumentasi resmi .



Seringkali kita bahkan tidak tahu apa yang kita butuhkan untuk mengotomatisasi sama sekali. Tim tidak memiliki waktu untuk memahami API layanan yang kompleks, lalu menulis dan men-debug solusinya dari awal. Marketplace memecahkan masalah ini : hampir 5 ribu Tindakan siap pakai diterbitkan di sana yang menyelesaikan banyak tugas umum (misalnya, mengirim pemberitahuan tentang acara di Telegram , menganalisis sumber proyek untuk utang teknis ,pengaturan label pada PR tergantung pada file yang diubah di dalamnya ). Berita buruk: banyak di antaranya adalah shareware - dengan batas penggunaan yang cukup ketat.



Proses kerja



Segala sesuatu di Github Actions berputar di sekitar alur kerja . Setiap alur kerja menjawab dua pertanyaan: apa yang harus dilakukan dan kapan melakukannya.



Apa yang harus dilakukan . Ada banyak sekali opsi di sini: Anda dapat membangun, menguji, dan menerapkan build Anda menggunakan skrip siap pakai atau skrip lakukan sendiri. Pelajari lebih lanjut tentang konfigurasi alur kerja



Kapan melakukannya . Anda bisa memicu alur kerja pada kejadian yang terjadi di repositori. Membuat permintaan tarik, mendorong tag komit, atau bahkan menambahkan bintang baru ke proyek Anda. Daftar lengkap hook



Jika alur kerja harus dijalankan bukan pada suatu acara, tetapi pada waktu tertentu atau pada frekuensi tertentu, Anda memiliki sintaks cron POSIX .Lebih lanjut tentang acara reguler



Di repositori, karena banyak alur kerja yang berbeda dapat hidup berdampingan pada waktu yang sama. Setiap alur kerja dijelaskan dalam file YAML terpisah, yang masing-masing harus disimpan dalam direktori .github / workflows di root repositori Anda. Pelajari lebih lanjut tentang sintaks alur kerja



Lingkungan runtime



Github Actions menawarkan dua opsi untuk menjalankan alur kerja Anda:



  • Github-hosted runners β€” , . Windows, Linux macOS. , Codemagic, ( ). , , ;

  • Self-hosted runners β€” , . Github , .



Dalam artikel saya, saya akan fokus pada opsi pertama. Kami mengikuti jalan yang paling sederhana, bukan?



Menyiapkan alur kerja dasar untuk Flutter



Sebelum kita mulai mengonfigurasi alur kerja, kita perlu menyetujui dua hal.



Pertama, peran utama alur kerja akan mempersulit pemecahan basis kode. Kode yang tidak membangun, mengandung potensi masalah, atau merusak tes tidak boleh menjadi arus utama.



Kedua: mungkin ada beberapa kehalusan dalam konfigurasi saya yang tidak akan relevan untuk proyek Anda. Saya akan mencoba menjelaskannya. Namun, jika Anda menggunakan artikel ini sebagai panduan, pinjamlah dengan cermat.



Akhirnya, mari kita putuskan apa yang seharusnya dilakukan alur kerja kita. Kami membutuhkan rencana untuk membantu kami bergerak ke arah yang benar.



Langkah demi langkah untuk menyelesaikan perakitan



Rencana di atas dapat digunakan sebagai daftar periksa saat menyiapkan alur kerja Anda sendiri. Kita harus:



  1. beri nama yang bermakna pada alur kerja;
  2. tunjukkan pada acara mana alur kerja kita akan dimulai;
  3. putuskan mesin yang akan memulai konfigurasi;
  4. putuskan langkah-langkah yang akan terdiri dari alur kerja kami:


  • menyelesaikan proyek,
  • menginstal Java;
  • memasang Flutter (seperti yang Anda ingat, setiap kali kami memiliki contoh bersih yang dapat kami gunakan),
  • mengunduh paket proyek,
  • memulai penganalisis statis,
  • menjalankan tes,
  • perakitan itu sendiri,
  • terapkan build ke suatu tempat di mana penguji bisa mendapatkannya.


Sekarang pekerjaan kami telah mengambil bentuk yang nyata. Mari kita lanjutkan ke implementasinya.



Seperti apa alur kerja kami di akhir
β€” . , , .



name: Flutter PR

on:
 pull_request:
   branches:
     - "dev/sprint-**"
   paths-ignore:
     - "docs/**"
     - "openapi/**"
     - ".vscode/**"

jobs:
 build:
   runs-on: ubuntu-latest
   steps:
     - uses: actions/checkout@v1
     - uses: actions/setup-java@v1
       with:
         java-version: "12.x"

     - uses: subosito/flutter-action@v1
       with:
         channel: "stable"

     - run: sh ./scripts/flutter_pub_get.sh

     - run: sh ./scripts/flutter_analyze.sh

     - run: flutter test

     - run: flutter build apk --release

     - uses: actions/upload-artifact@v1
       with:
         name: APK for QA
         path: build/app/outputs/apk/dev/debug/apk_name.apk

     - name: Upload artifact to Firebase App Distribution
        uses: wzieba/Firebase-Distribution-Github-Action@v1
        with:
          appId: ${{ secrets.FIREBASE_ANDROID_PROD_APP_ID }}
          token: ${{ secrets.FIREBASE_TOKEN }}
          groups: testers
          file: build/app/outputs/apk/dev/debug/apk_name.apk
          debug: true




Nama



Jelas, kita perlu memberi nama alur kerja kita sehingga nama tersebut mencerminkan esensinya seakurat mungkin. Nama ( dokumen ) adalah hal pertama yang kita lihat di Konsol Tindakan saat alur kerja dijalankan. Mengapa saya menamakan alur kerja saya seperti itu, Anda akan segera mengetahuinya.







name: Flutter PR


Acara yang memicu



Blok "on" ( docs ) memungkinkan kita untuk menentukan satu atau lebih kejadian, setelah pendaftaran yang kita inginkan untuk memulai alur kerja kita. Selain itu, beberapa acara dapat disetel dengan baik. 



Acara mana yang harus dipilih? Agar tidak melewatkan perincian, Anda dapat menentukan setidaknya semua acara yang ada. Kemudian perakitan akan berlangsung hampir terus menerus, tetapi apakah kita menginginkan ini? Tidak, karena dalam kasus ini batas rencana tarif gratis kami akan berakhir dengan sangat cepat. Kami akan mencari solusi optimal.



Mari kita asumsikan bahwa proyek kita mematuhi perjanjian yang menurutnya kode tidak dapat didorong ke cabang utama proyek secara langsung - hanya melalui pembuatan permintaan tarik. Adalah logis jika alur kerja kita menanggapi pembuatan permintaan tarik dan membangun proyek dari basis kode yang dimodifikasi:



on: pull_request


$ Ini cukup untuk pekerjaan, tetapi solusinya belum terlalu optimal. Build akan dipicu pada setiap permintaan penarikan yang dibuat. Ini berlebihan, karena kami hanya tertarik pada permintaan penarikan yang diarahkan ke cabang utama proyek. Sintaks untuk Github Actions memungkinkan kita menentukan nama (atau topeng) dari cabang yang kita minati.



on:
 pull_request:
   branches:
     - "dev/sprint-**"


$ Dan lagi-lagi kami mencari cara untuk mengoptimalkan proses tersebut. Ada file yang, bahkan secara teori, tidak dapat merusak proyek Anda: dokumentasi proyek, Kesombongan, setelan gaya kode umum, dan IDE. Untungnya, kami memiliki kemampuan untuk mengabaikan file tersebut dengan path mask. Akibatnya, blok "on" akan terlihat seperti ini:



on:
 pull_request:
   branches:
     - "dev/sprint-**"
   paths-ignore:
     - "docs/**"
     - "drz-swagger/**"
     - ".vscode/**"


Penting : hanya buat permintaan penarikan jika Anda siap untuk menggabungkannya. Setiap dorongan berikutnya ke permintaan tarik yang sudah dibuat akan memulai kembali alur kerja.

Konfigurasi pekerjaan







Terakhir, kami siap untuk mengkonfigurasi pekerjaan ( dokumen ). Sekarang adalah waktunya untuk memperjelas peran apa yang dimainkan pekerjaan dalam alur kerja.



Setiap alur kerja harus menyertakan setidaknya satu pekerjaan. Ini adalah pekerjaan yang berisi deskripsi langkah demi langkah dari langkah - langkah yang kami lakukan dengan proyek kami. Jumlah pekerjaan dalam satu alur kerja tidak dibatasi, begitu pula jumlah langkah dalam satu pekerjaan. Secara default, semua pekerjaan dijalankan secara paralel, kecuali ketergantungan satu pekerjaan pada hasil pekerjaan lain ditentukan. Proyek kami akan memiliki satu-satunya pekerjaan yang akan bertanggung jawab untuk membangun proyek tersebut.



Menyiapkan lingkungan



Setiap kali alur kerja berjalan pada instance mesin virtual yang bersih. Satu-satunya hal yang dapat kita pilih adalah sistem operasi yang akan diinstal pada mesin ini. Apa yang harus dipilih?



Sangat menggoda untuk memilih macOS, karena kami berencana membangun aplikasi Flutter untuk platform target: Android dan iOS. Kabar buruk. Satu menit penggunaan instans dengan macOS akan dianggap sebagai sepuluh (10 !!!) menit menggunakan instans dengan Ubuntu. Dalam contoh dengan Windows, dalam kasus kami, tidak ada gunanya sama sekali, karena masih tidak mungkin untuk merakit rakitan iOS di sana, dan waktu penggunaannya dua kali lebih mahal sebagai contoh dengan Ubuntu. Lebih lanjut tentang penagihan



$Bagaimana kami memastikan bahwa 2.000 menit gratis kami tidak berubah menjadi 200? Tidak ada solusi yang baik. Saya memutuskan untuk tidak membangun build di iOS saat membuat permintaan tarik. Ini berpotensi mengenai stabilitas build iOS. Ada juga opsi kompromi - untuk membangun iOS build di macOS hanya saat mengubah pubspec.yaml atau file apa pun dari direktori / ios , dalam kasus lain, hanya membangun Android build di instance dengan Ubuntu. Ini dapat dilakukan dengan analogi dengan bagaimana kita mengatur file abaikan untuk blok "on" .



jobs:
 build:
   runs-on: ubuntu-latest


Anda dapat melihat spesifikasi teknisnya , serta daftar perangkat lunak "out of the box" yang diinstal . Flutter dan Java, sayangnya, tidak termasuk dalam daftar ini. Mereka harus diinstal secara manual setiap kali alur kerja dijalankan.



Jangan terburu-buru untuk marah. Tindakan siap akan datang untuk menyelamatkan kita, yang dapat kita gunakan dalam langkah-langkah pekerjaan kita. Kami akan menggunakan dua:



  • actions / setup-java - aksi resmi untuk mengatur lingkungan Java;

  • subosito / flutter-action adalah tindakan tidak resmi untuk mengunduh dan menginstal Flutter SDK. Ini telah membuktikan dirinya dengan baik: ini memungkinkan Anda untuk melakukan apa pun yang Anda butuhkan - misalnya, menentukan saluran kerangka kerja yang diinginkan atau beralih ke versi SDK tertentu.



steps:
      - uses: actions/setup-java@v1
        with:
          java-version: "12.x"

      - uses: subosito/flutter-action@v1
        with:
          channel: "stable"


Menggandakan repositori



Kami memiliki contoh bersih mesin yang disewa dari Github selama beberapa menit. Pada langkah sebelumnya, kami menginstal semua perangkat lunak yang diperlukan di dalamnya. Sekarang kita perlu menggandakan repositori sumber untuk proyek kita. Untuk melakukan ini, kami akan menggunakan alat yang sudah jadi:



  • actions / checkout adalah tindakan resmi untuk mengkloning repositori dengan banyak pengaturan yang tidak diperlukan dalam banyak kasus. Karena alur kerja berjalan langsung di repositori yang kita kloning, kita tidak perlu menentukannya secara eksplisit.



- uses: actions/checkout@v1


Memuat dependensi



Sampai saat ini, kami belum menerapkan langkah-langkah dengan tangan kami sendiri, tetapi hanya menggunakan apa yang saya tawarkan tindakan siap pakai. Sekarang kita beralih ke implementasi fase build aktif proyek kita, jadi inilah saatnya menulis sendiri penerapan langkah tersebut.



Sebelum membangun, kita perlu mengunduh semua paket yang ditentukan di blok dependensi file pubspec.yaml kami, serta semua dependensi transitifnya. Untuk melakukan ini, Flutter SDK menawarkan perintah sederhana di luar kotak flutter pub get. Implementasi langkah dapat terdiri dari memanggil satu perintah terminal. Dalam kasus ini, langkah selanjutnya hanya akan dipanggil setelah perintah ini selesai.



- run: flutter pub get


Jika proyek Anda memiliki struktur yang kompleks dan berisi sejumlah paket dart yang terhubung secara lokal, Anda akan menghadapi masalah. Tidak flutter pub getmungkin membangun proyek tanpa panggilan eksplisit untuk masing-masing paket ini. Dalam proyek saya, paket semacam itu dikumpulkan di folder / inti yang terletak di direktori root. Di bawah ini adalah skrip yang menyelesaikan masalah ini. Ini dijelaskan di file flutter_pub_get.sh di folder / scripts di direktori root yang sama.



flutter pub get
cd core
for dir in */ ; do

    echo ${dir}
    cd ${dir}
    pwd
    flutter pub get
    cd ..
    pwd
    if [ "$#" -gt 0 ]; then shift; fi
    # shift
done


Karena penerapan langkah dapat berupa perintah terminal apa pun, tidak ada yang menghalangi kita untuk menjalankan skrip shell kita.



- run: sh ./scripts/flutter_pub_get.sh


Analisis kode statis



Flutter mengundang kita untuk menggunakan perintah bawaan flutter analyzeuntuk menjalankan penganalisis statis. Ini akan membantu mengidentifikasi potensi masalah dengan basis kode kami pada tahap awal: sebelum bug mengenai produksi, atau kode kami berubah menjadi kekacauan yang tidak dapat dibaca dan tidak didukung.



Kami dapat memanfaatkan fitur kotak tanpa perubahan apa pun, tetapi sayangnya, perilaku tim standar flutter analyzememiliki kekurangan yang merusak alur kerja kami pada waktu yang salah. 



Masalah yang ditemukan oleh penganalisis diklasifikasikan menjadi tiga tingkat keparahan: info, peringatan, kesalahan. Dalam masalah inidijelaskan bahwa meskipun selama analisis hanya masalah kelas info yang ditemukan (dan tidak selalu ada gunanya menghabiskan waktu untuk memperbaikinya di sini dan saat ini), perintah mengembalikan kode "1", akibatnya assembly Anda akan macet.



Saya sarankan menggunakan skrip berikut sebagai solusi sementara. Mulai sekarang, perakitan akan macet hanya jika ada masalah dengan tingkat kesalahan :



OUTPUT="$(flutter analyze)"
echo "$OUTPUT"
echo
if grep -q "error β€’" echo "$OUTPUT"; then
    echo "flutter analyze found errors"
    exit 1
else
    echo "flutter analyze didn't find any errors"
    exit 0
fi


Kami menjalankan skrip shell di langkah berikutnya dari alur kerja kami:



- run: sh ./scripts/flutter_analyze.sh


Menjalankan tes



Jika Anda memiliki tes dalam proyek Anda, Anda berada di jalur yang benar! Agar pengujian berfungsi, tidak cukup hanya menulisnya - pengujian harus dijalankan secara teratur untuk memperbaiki kekurangan implementasi tepat waktu atau memperbarui jika perlu. Oleh karena itu, pada langkah selanjutnya, kami akan menerapkan



- run: flutter test


Hati-hati: kelas pengujian kosong yang tidak berisi pengujian yang diimplementasikan akan merusak seluruh alur kerja. Hanya ada satu jalan keluar: jangan mendeklarasikan kelas pengujian sampai Anda siap untuk mengimplementasikan setidaknya satu pengujian di dalamnya.



Bangun dan Tanda Tangan



Semua pekerjaan persiapan sudah selesai. Kami telah memverifikasi bahwa kode tersebut kemungkinan besar tidak mengandung masalah yang jelas. Sekarang kita beralih ke tahap paling penting - produksi artefak. Dengan kata lain, kami akan membangun APK.



Perakitan itu sendiri sangat sederhana untuk diterapkan. Kami memiliki perintah terminal build flutter build, yang sangat dapat dikonfigurasi dan memungkinkan Anda membuat artefak untuk ragam tertentu, file utama, ABI. Kami tidak membahas nuansa ini di artikel, jadi gunakan tanda perintah tambahan jika perlu.



- run: flutter build apk --release


Tujuan kami adalah mendapatkan rakitan yang ditandatangani dengan kunci rilis. Dan pada tahap ini kita harus menyelesaikan masalah keamanan, karena kita perlu menyimpan keystore rilis di suatu tempat, serta semua alias dan kata sandinya.



Github memungkinkan Anda menyimpan nilai string dengan aman di repositori Rahasia khusus . Data yang tersedia di sini disimpan dalam repositori yang sesuai dan dapat dibaca secara terprogram dari langkah mana pun dalam alur kerja Anda. Namun, nilainya tidak dapat dilihat melalui antarmuka web Github. Hanya menghapus atau menimpa diperbolehkan.







Ini terlihat seperti solusi yang cocok untuk alias dan kata sandi, terutama jika Anda adalah layanan keamanan Anda sendiri, tetapi bagaimana dengan file * .jks itu sendiri? Mendorongnya ke repositori sepertinya bukan ide yang bagus, meskipun repositori Anda bersifat pribadi. Sayangnya, Github tidak menyediakan cara aman untuk menyimpan file, jadi Anda harus menghindar.



Akan bagus untuk merepresentasikan file keystore kami sebagai string. Dan ini nyata - Anda hanya perlu menyandikannya di base64. Untuk melakukan ini, buka terminal di direktori yang berisi file * .jks kami dan jalankan perintah berikut. Selanjutnya, file teks akan dibuat tempat Anda dapat menyalin representasi base64 dari keystore kami, lalu ... simpan ke Rahasia Github.



openssl base64 < key_store_filename.jks | tr -d '\n' | tee keystore.jks.base64.txt


Sekarang setelah kita memiliki semua bahan yang diperlukan untuk berhasil menandatangani rakitan, kita akan melanjutkan dengan konfigurasi langkahnya. Di blok env, kami mendeklarasikan semua variabel lingkungan untuk langkah tertentu itu. Kami akan mengambil nilai variabel ini dari Rahasia.



- run: flutter build apk --release
        env:
          STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }}
          KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
          KEY_ALIAS: ${{ secrets.KEY_ALIAS }}
          STORE_FILE: ${{ secrets.STORE_FILE }}


Di host Android kami, kami harus mendeskripsikan konfigurasi assembly sedemikian rupa sehingga kami dapat menandatangani file * .apk di CI juga, tanpa kehilangan kemampuan untuk membangun perakitan yang ditandatangani secara lokal. File keystoreConfig.gradle bertanggung jawab untuk saat ini .



Jika file keystore_release.properties ditemukan, diketahui bahwa build terjadi secara lokal, yang berarti Anda dapat menginisialisasi semua properti keystoreConfig hanya dengan membacanya dari file. Jika tidak, perakitan berlangsung di CI, yang berarti satu-satunya sumber data sensitif adalah Rahasia Github.



ext {
   def releaseKeystorePropsFile = rootProject.file("keystore/keystore_release.properties")
   if (releaseKeystorePropsFile.exists()) {
       println "Start extract release keystore config from keystore_release.properties"
       def keystoreProps = new Properties()
       keystoreProps.load(new FileInputStream(releaseKeystorePropsFile))
       keystoreConfig = [
               storePassword: keystoreProps['storePassword'],
               keyPassword  : keystoreProps['keyPassword'],
               keyAlias     : keystoreProps['keyAlias'],
               storeFile    : keystoreProps['storeFile']
       ]
   } else {
       println "Start extract release keystore config from global vars"
       keystoreConfig = [
               storePassword: "$System.env.STORE_PASSWORD",
               keyPassword  : "$System.env.KEY_PASSWORD",
               keyAlias     : "$System.env.KEY_ALIAS",
               storeFile    : "$System.env.STORE_FILE"
       ]
   }
   println "Extracted keystore config: $keystoreConfig"
}


Dan seperti inilah tampilan file keystore_release.properties :



storePassword={___}
keyPassword={___}
keyAlias={___}
storeFile=../keystore/keystore.jks


Langkah terakhir dalam file build.gradle dari host Android kita adalah menerapkan file keystoreConfig ke konfigurasi penandatanganan build rilis:



android {
   signingConfigs {
       release {
           apply from: '../keystore/keystoreConfig.gradle'

           keyAlias keystoreConfig.keyAlias
           keyPassword keystoreConfig.keyPassword
           storeFile file(keystoreConfig.storeFile)
           storePassword keystoreConfig.storePassword
       }
   }
}


Majelis yang ditandatangani sudah ada di tangan kita! Tapi bagaimana Anda memperluasnya ke kolega Anda untuk pengujian?



Bongkar



Github Actions memungkinkan Anda menyiapkan pengunggahan artefak ke hampir semua alat yang dikenal untuk mendistribusikan rakitan, tetapi kami hanya akan mempertimbangkan dua opsi:



  • Penyimpanan Github - cara termudah untuk mengunggah rakitan ke penyimpanan Github Anda sendiri, yang berfungsi di luar kotak, tetapi memiliki beberapa batasan;

  • Firebase App Distribution adalah layanan dari ekosistem Firebase yang menggantikan Beta dengan Crashlytics. Integrasi sedikit lebih sulit untuk dikonfigurasi, tetapi layanan itu sendiri jauh lebih nyaman untuk digunakan.





Penyimpanan Github Penyimpanan

Github terintegrasi dengan mudah melalui tindakan resmi. Anda hanya perlu menentukan nama rakitan karena kolega Anda akan melihatnya di antarmuka web, serta jalur ke file * .apk yang dirakit di CI.



- uses: actions/upload-artifact@v1
        with:
          name: APK for QA
          path: build/app/outputs/apk/dev/debug/apk_name.apk


Masalah utamanya adalah ruang penyimpanan yang terbatas. Pada paket gratis Anda hanya diberikan 500 MB. Hal yang paling aneh adalah saya tidak menemukan cara untuk secara manual menghapus seluruh penyimpanan sekaligus melalui antarmuka web, jadi saya keluar dari situasi tersebut melalui ... menulis alur kerja terpisah yang bertanggung jawab hanya untuk membersihkan Penyimpanan dari artefak berlumut.



Alur kerja berjalan setiap hari pada pukul 1 pagi dan menghapus semua artefak yang berusia lebih dari satu minggu:



name: Github Storage clear

on:
  schedule:
    - cron: '0 1 * * *'

jobs:
  remove-old-artifacts:
    runs-on: ubuntu-latest
    timeout-minutes: 10

    steps:
      - name: Remove old artifacts
        uses: c-hive/gha-remove-artifacts@v1
        with:
          age: '1 week'


Distribusi Aplikasi Firebase

Adapun Distribusi Aplikasi Firebase, saya menggunakan tindakan siap pakai wzieba / Firebase-Distribution-Github-Action untuk berintegrasi dengannya



- name: Upload artifact to Firebase App Distribution
        uses: wzieba/Firebase-Distribution-Github-Action@v1
        with:
          appId: ${{ secrets.FIREBASE_ANDROID_PROD_APP_ID }}
          token: ${{ secrets.FIREBASE_TOKEN }}
          groups: testers
          file: build/app/outputs/apk/dev/debug/apk_name.apk
          debug: true


Agar tindakan berfungsi dengan benar, ia perlu meneruskan parameter:



  • appId - pengenal aplikasi, yang dapat ditemukan di pengaturan proyek Firebase;







  • token - token untuk autentikasi ke project FIrebase Anda, yang diperlukan untuk memuat assembly ke dalam layanan. Anda bisa mendapatkan token hanya melalui Firebase CLI, yang dapat Anda baca lebih lanjut di dokumentasi resmi ;

  • file - path ke file * .apk yang dikompilasi pada CI;

  • grup - parameter ini opsional, tetapi memungkinkan Anda untuk menentukan alias dari grup penguji tempat perakitan yang diunggah akan dibagikan secara otomatis.



Peluncuran dan observasi



Alur kerja paling sederhana kami sudah siap! Yang harus kita lakukan hanyalah mengaktifkan peristiwa pemicu dan melihat kemajuan alur kerja.



Saran dan kata perpisahan



Sekarang Anda dapat menikmati semua keuntungan dari mekanisme CI / CD sederhana pada proyek Flutter Anda, terlepas dari ukuran, intensitas pengembangan, atau dompet Anda.



Terakhir, berikut adalah beberapa tip dan pengamatan yang saya dapatkan saat mengerjakan alur kerja ini:



  • workflow . workflow , , . - . , - workflow , .

  • step’ shell-. workflow . . .

  • Run Duration workflow. workflow , . workflow , step’. . Flutter SDK . β€” 5-6 .



Masih banyak potensi perbaikan dan perbaikan ke depan. Tuliskan di komentar ide Anda untuk meningkatkan alur kerja. Apa kekurangan Anda secara pribadi di dalamnya? Mungkin implementasi dari ide-ide pembaca yang paling menarik akan menjadi dasar artikel berikutnya tentang topik tersebut.



Semua skrip dan alur kerja dapat ditemukan di repositori dengan aplikasi pengujian .



Terima kasih atas perhatian Anda.



PS Tim Surf kami merilis banyak pustaka berguna untuk Flutter. Kami mengunggahnya ke gudang SurfGear .



All Articles