Pengalaman CICD seluler: satu standar jalur cepat untuk banyak aplikasi seluler

Pengalaman CICD seluler: satu standar jalur cepat untuk banyak aplikasi seluler
Saya ingin berbicara tentang integrasi dan pengiriman berkelanjutan untuk aplikasi seluler menggunakan fastlane. Bagaimana kami menerapkan CI/CD di semua aplikasi seluler, bagaimana kami mencapainya, dan apa yang terjadi pada akhirnya.

Sudah ada cukup materi di jaringan tentang alat tersebut, yang pada awalnya sangat kurang kami miliki, jadi saya sengaja tidak akan menjelaskan alat tersebut secara detail, tetapi hanya akan merujuk pada apa yang kami miliki saat itu:

Artikel ini terdiri dari dua bagian:

  • Latar belakang munculnya mobile CI/CD di perusahaan
  • Solusi teknis untuk meluncurkan CI/CD untuk aplikasi N

Bagian pertama lebih bersifat nostalgia masa lalu, dan bagian kedua adalah pengalaman yang bisa Anda terapkan pada diri sendiri.

Begitulah yang terjadi secara historis

Tahun 2015

Kami baru saja mulai mengembangkan aplikasi seluler, lalu kami tidak tahu apa pun tentang integrasi berkelanjutan, tentang DevOps, dan hal-hal modis lainnya. Setiap pembaruan aplikasi diluncurkan oleh pengembang sendiri dari mesinnya. Dan jika untuk Android cukup sederhana - dirakit, ditandatangani .apk dan mengunggahnya ke Konsol Pengembang Google, lalu untuk iOS, alat distribusi melalui Xcode memberi kami malam yang menyenangkan - upaya untuk mengunduh arsip sering kali berakhir dengan kesalahan dan kami harus mencoba lagi. Ternyata pengembang paling maju tidak menulis kode beberapa kali dalam sebulan, melainkan merilis aplikasinya.

Tahun 2016

Kami tumbuh dewasa, kami sudah memiliki pemikiran tentang cara membebaskan pengembang dari satu hari penuh untuk rilis, dan aplikasi kedua juga muncul, yang hanya mendorong kami lebih ke arah otomatisasi. Pada tahun yang sama, kami menginstal Jenkins untuk pertama kalinya dan menulis sekumpulan skrip menakutkan, sangat mirip dengan yang ditampilkan fastlane dalam dokumentasinya.

$ xcodebuild clean archive -archivePath build/MyApp 
    -scheme MyApp

$ xcodebuild -exportArchive 
                        -exportFormat ipa 
                        -archivePath "build/MyApp.xcarchive" 
                        -exportPath "build/MyApp.ipa" 
                        -exportProvisioningProfile "ProvisioningProfileName"

$ cd /Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Versions/A/Support/

$ ./altool —upload-app 
-f {abs path to your project}/build/{release scheme}.ipa  
-u "[email protected]" 
-p "PASS_APPLE_ID"

Sayangnya, hingga saat ini hanya pengembang kami yang mengetahui cara kerja skrip ini dan mengapa tumpukan kunci yang tak ada habisnya ini diperlukan, dan ketika terjadi kerusakan lagi, mereka mendapatkan “malam yang indah” untuk menganalisis log.

Tahun 2017

Tahun ini kita mengetahui bahwa ada yang namanya fastlane. Informasi yang ada saat ini tidak sebanyak yang ada – bagaimana memulainya, bagaimana menggunakannya. Dan alat itu sendiri masih mentah pada saat itu: kesalahan terus-menerus hanya mengecewakan kami dan sulit mempercayai otomatisasi ajaib yang mereka janjikan.

Namun, utilitas utama yang termasuk dalam inti fastlane adalah gym и pilot, kami berhasil memulainya.

Skrip kami telah diperbaiki sedikit.

$ fastlane gym  —-workspace "Example.xcworkspace" 
                --scheme "AppName" 
                —-buildlog_path "/tmp" 
                -—clean

Mereka telah ditingkatkan, jika hanya karena tidak semua parameter diperlukan xcodebuild, Anda perlu menunjukkan - gym akan secara mandiri memahami di mana dan apa yang ada. Dan untuk penyesuaian lebih lanjut, Anda dapat menentukan kunci yang sama seperti pada xcodebuild, hanya penamaan kuncinya yang lebih jelas.

Kali ini, berkat gym dan pemformat xcpretty bawaan, log build menjadi lebih mudah dibaca. Hal ini mulai menghemat waktu dalam memperbaiki rakitan yang rusak, dan terkadang tim rilis dapat mengatasinya sendiri.

Sayangnya, pengukuran kecepatan perakitan xcodebuild и gym Kami tidak melakukannya, tapi kami percaya pada dokumentasinya - percepatan hingga 30%.

Proses tunggal untuk semua aplikasi

Tahun 2018 dan sekarang

Pada tahun 2018, proses pembuatan dan peluncuran aplikasi sepenuhnya dipindahkan ke Jenkins, pengembang berhenti merilis dari mesin mereka, dan hanya tim rilis yang berhak merilis.

Kami sudah ingin meningkatkan peluncuran pengujian dan analisis statis, dan skrip kami semakin berkembang. Tumbuh dan berubah seiring dengan aplikasi kami. Saat itu ada sekitar 10 aplikasi, mengingat kami memiliki dua platform, itu berarti sekitar 20 skrip “hidup”.

Setiap kali kami ingin menambahkan langkah baru ke skrip, kami harus menyalin-menempelkan potongan tersebut ke semua skrip shell. Mungkin kami bisa bekerja lebih hati-hati, tetapi sering kali perubahan seperti itu berakhir dengan kesalahan ketik, yang berubah menjadi malam bagi tim rilis untuk memperbaiki skrip dan mencari tahu orang pintar mana yang menambahkan perintah ini dan apa sebenarnya fungsinya. Secara umum, tidak dapat dikatakan bahwa skrip perakitan untuk satu platform setidaknya serupa. Meskipun mereka pasti melakukan hal yang sama.

Untuk memulai proses aplikasi baru, diperlukan waktu satu hari untuk memilih versi "segar" dari skrip ini, melakukan debug, dan mengatakan bahwa "ya, berhasil".

Pada musim panas 2018, kami sekali lagi melihat ke arah jalur cepat yang masih berkembang.

Tugas #1: meringkas semua langkah skrip dan menulis ulang di Fastfile

Saat kami memulai, skrip kami tampak seperti alas kaki yang terdiri dari semua langkah dan kruk dalam satu skrip shell di Jenkins. Kami belum beralih ke jalur pipa dan divisi demi tahap.

Kami melihat apa yang kami miliki dan mengidentifikasi 4 langkah yang sesuai dengan deskripsi CI/CD kami:

  • build - menginstal dependensi, merakit arsip,
  • pengujian — menjalankan pengujian unit pengembang, menghitung cakupan,
  • sonar - meluncurkan semua linter dan mengirimkan laporan ke SonarQube,
  • deploy — mengirim artefak ke alpha (TestFlight).

Dan jika Anda tidak merincinya, menghilangkan kunci yang digunakan dalam tindakan, Anda akan mendapatkan Fastfile ini:

default_platform(:ios)

platform :ios do
  before_all do
    unlock
  end

  desc "Build stage"
  lane :build do
    match
    prepare_build
    gym
  end

  desc "Prepare build stage: carthage and cocoapods"
  lane :prepare_build do
    pathCartfile = ""
    Dir.chdir("..") do
      pathCartfile = File.join(Dir.pwd, "/Cartfile")
    end
    if File.exist?(pathCartfile)
      carthage
    end
    pathPodfile = ""
    Dir.chdir("..") do
      pathPodfile = File.join(Dir.pwd, "/Podfile")
    end
    if File.exist?(pathPodfile)
      cocoapods
    end
  end

  desc "Test stage"
  lane :test do
    scan
    xcov
  end

  desc "Sonar stage (after run test!)"
  lane :run_sonar do
    slather
    lizard
    swiftlint
    sonar
  end

  desc "Deploy to testflight stage"
  lane :deploy do
    pilot
  end

  desc "Unlock keychain"
  private_lane :unlock do
    pass = ENV['KEYCHAIN_PASSWORD']
    unlock_keychain(
      password: pass
    )
  end
end

Faktanya, Fastfile pertama kami ternyata sangat buruk, mengingat beberapa kruk yang masih kami perlukan dan jumlah parameter yang kami gantikan:

lane :build do
carthage(
  command: "update",
  use_binaries: false,
  platform: "ios",
  cache_builds: true)
cocoapods(
  clean: true,
    podfile: "./Podfile",
    use_bundle_exec: false)

gym(
  workspace: "MyApp.xcworkspace",
  configuration: "Release",
  scheme: "MyApp",
  clean: true,
  output_directory: "/build",
  output_name: "my-app.ipa")
end 

lane :deploy do
 pilot(
  username: "[email protected]",
  app_identifier: "com.example.app",
  dev_portal_team_id: "TEAM_ID_NUMBER_DEV",
  team_id: "ITS_TEAM_ID")
end

Dalam contoh di atas, hanya sebagian parameter yang perlu kita tentukan: ini adalah parameter build - skema, konfigurasi, nama Profil Penyediaan, serta parameter distribusi - ID Apple dari akun pengembang, kata sandi, ID aplikasi, dan sebagainya pada. Sebagai perkiraan pertama, kami memasukkan semua kunci ini ke dalam file khusus - Gymfile, Matchfile и Appfile.

Sekarang di Jenkins Anda dapat memanggil perintah singkat yang tidak mengaburkan pandangan dan mudah dibaca oleh mata:

# fastlane ios <lane_name>

$ fastlane ios build
$ fastlane ios test
$ fastlane ios run_sonar
$ fastlane ios deploy

Hore, kami hebat

Apa yang kamu dapatkan? Hapus perintah untuk setiap langkah. Script sudah dibersihkan, tersusun rapi dalam file fastlane. Bersukacitalah, kami menemui para pengembang meminta mereka untuk menambahkan semua yang mereka butuhkan ke repositori mereka.

Namun kami menyadari pada waktunya bahwa kami akan menghadapi kesulitan yang sama - kami masih memiliki 20 skrip perakitan yang entah bagaimana akan mulai menjalani kehidupannya sendiri, akan lebih sulit untuk mengeditnya, karena skrip akan dipindahkan ke repositori, dan kami tidak memiliki akses ke sana. Dan, secara umum, tidak mungkin mengatasi rasa sakit kita dengan cara ini.

Pengalaman CICD seluler: satu standar jalur cepat untuk banyak aplikasi seluler

Tugas #2: mendapatkan satu Fastfile untuk N aplikasi

Sekarang tampaknya menyelesaikan masalah tidak terlalu sulit - atur variabelnya, dan ayo. Ya, sebenarnya, begitulah cara masalahnya diselesaikan. Tetapi pada saat kami mengacaukannya, kami tidak memiliki keahlian dalam fastlane itu sendiri, atau di Ruby, di mana fastlane ditulis, atau contoh-contoh berguna di jaringan - setiap orang yang menulis tentang fastlane kemudian dibatasi pada contoh untuk satu aplikasi untuk satu pengembang.

Fastlane dapat menangani variabel lingkungan, dan kami telah mencobanya dengan mengatur kata sandi Rantai Kunci:

ENV['KEYCHAIN_PASSWORD']

Setelah melihat skrip kami, kami mengidentifikasi bagian-bagian umum:

#for build, test and deploy
APPLICATION_SCHEME_NAME=appScheme
APPLICATION_PROJECT_NAME=app.xcodeproj
APPLICATION_WORKSPACE_NAME=app.xcworkspace
APPLICATION_NAME=appName

OUTPUT_IPA_NAME=appName.ipa

#app info
APP_BUNDLE_IDENTIFIER=com.example.appName
[email protected]
TEAM_ID=ABCD1234
FASTLANE_ITC_TEAM_ID=123456789

Sekarang, untuk mulai menggunakan kunci ini di file fastlane, kami harus memikirkan cara mengirimkannya ke sana. Fastlane punya solusi untuk ini: memuat variabel melalui dotenv. Dokumentasi mengatakan bahwa jika penting bagi Anda untuk memuat kunci untuk tujuan berbeda, buat beberapa file konfigurasi di direktori fastlane .env, .env.default, .env.development.

Dan kemudian kami memutuskan untuk menggunakan perpustakaan ini sedikit berbeda. Mari kita tempatkan di repositori pengembang bukan skrip fastlane dan informasi meta-nya, tetapi kunci unik aplikasi ini di dalam file .env.appName.

Dirinya sendiri Fastfile, Appfile, Matchfile и Gymfile, kami menyembunyikannya di repositori terpisah. File tambahan dengan kunci kata sandi dari layanan lain disembunyikan di sana - .env.
Anda dapat melihat contohnya di sini.

Pengalaman CICD seluler: satu standar jalur cepat untuk banyak aplikasi seluler

Di CI, panggilannya tidak banyak berubah; kunci konfigurasi untuk aplikasi tertentu telah ditambahkan:

# fastlane ios <lane_name> --env appName

$ fastlane ios build --env appName
$ fastlane ios test --env appName
$ fastlane ios run_sonar --env appName
$ fastlane ios deploy --env appName

Sebelum menjalankan perintah, kami memuat repositori kami dengan skrip. Tidak terlihat bagus:

git clone [email protected]/FastlaneCICD.git fastlane_temp

cp ./fastlane_temp/fastlane/* ./fastlane/
cp ./fastlane_temp/fastlane/.env fastlane/.env

Tinggalkan solusi ini untuk saat ini, meskipun Fastlane memiliki solusi untuk mengunduh Fastfile melalui tindakan import_from_git, tetapi ini hanya berfungsi untuk Fastfile, tetapi tidak untuk file lain. Jika ingin “cantik banget”, Anda bisa menulis sendiri action.

Kumpulan serupa dibuat untuk aplikasi Android dan ReactNative, file-file tersebut berada di repositori yang sama, tetapi di cabang yang berbeda iOS, android и react_native.

Ketika tim rilis ingin menambahkan beberapa langkah baru, perubahan skrip dicatat melalui MR di git, tidak perlu lagi mencari penyebab skrip rusak, dan secara umum, sekarang Anda harus mencoba memecahkannya.

Itu sudah pasti

Sebelumnya, kami menghabiskan waktu memelihara semua skrip, memperbaruinya, dan memperbaiki semua konsekuensi pembaruan. Sangat mengecewakan ketika alasan kesalahan dan downtime dalam rilis adalah kesalahan ketik sederhana yang sangat sulit untuk dilacak dalam skrip shell yang campur aduk. Sekarang kesalahan seperti itu diminimalkan. Perubahan diluncurkan ke semua aplikasi sekaligus. Dan dibutuhkan waktu 15 menit untuk memasukkan aplikasi baru ke dalam proses - menyiapkan pipeline template di CI dan menambahkan kunci ke repositori pengembang.

Nampaknya maksud Fastfile untuk Android dan tanda tangan aplikasinya masih belum jelas, jika artikelnya menarik saya akan menulis lanjutannya. Saya akan senang melihat pertanyaan atau saran Anda “bagaimana Anda mengatasi masalah ini” di komentar atau di Telegram bashkirova.

Sumber: www.habr.com

Tambah komentar