Εμπειρία CICD για φορητές συσκευές: ένα πρότυπο fastlane για πολλές εφαρμογές για κινητές συσκευές

Εμπειρία CICD για φορητές συσκευές: ένα πρότυπο fastlane για πολλές εφαρμογές για κινητές συσκευές
Θα ήθελα να μιλήσω για τη συνεχή ενσωμάτωση και παράδοση για εφαρμογές για κινητά χρησιμοποιώντας το fastlane. Πώς υλοποιούμε το CI/CD σε όλες τις εφαρμογές για κινητά, πώς φτάσαμε εκεί και τι έγινε τελικά.

Υπάρχει ήδη αρκετό υλικό στο δίκτυο για το εργαλείο, το οποίο μας έλειπε τόσο πολύ στην αρχή, οπότε σκόπιμα δεν θα περιγράψω το εργαλείο λεπτομερώς, αλλά θα αναφερθώ μόνο σε αυτό που είχαμε τότε:

Το άρθρο αποτελείται από δύο μέρη:

  • Ιστορικό για την εμφάνιση κινητών CI/CD στην εταιρεία
  • Τεχνική λύση για την ανάπτυξη CI/CD για N-εφαρμογές

Το πρώτο μέρος είναι περισσότερο νοσταλγία για τα παλιά και το δεύτερο είναι μια εμπειρία που μπορείτε να εφαρμόσετε στον εαυτό σας.

Έτσι έγινε ιστορικά

Έτος 2015

Μόλις ξεκινήσαμε να αναπτύσσουμε εφαρμογές για κινητά, τότε δεν γνωρίζαμε τίποτα για τη συνεχή ενοποίηση, για τα DevOps και άλλα μοντέρνα πράγματα. Κάθε ενημέρωση εφαρμογής κυκλοφόρησε από τον ίδιο τον προγραμματιστή από το μηχάνημά του. Και αν για το Android είναι αρκετά απλό - συναρμολογημένο, υπογεγραμμένο .apk και το ανέβασε στην Κονσόλα προγραμματιστή Google, στη συνέχεια για το iOS το τότε εργαλείο διανομής μέσω Xcode μας άφησε υπέροχες βραδιές - οι προσπάθειες λήψης του αρχείου συχνά κατέληγαν σε σφάλματα και έπρεπε να προσπαθήσουμε ξανά. Αποδείχθηκε ότι ο πιο προηγμένος προγραμματιστής δεν γράφει κώδικα πολλές φορές το μήνα, αλλά απελευθερώνει την εφαρμογή.

Έτος 2016

Μεγαλώσαμε, είχαμε ήδη σκέψεις για το πώς να ελευθερώσουμε προγραμματιστές από μια ολόκληρη μέρα για κυκλοφορία και εμφανίστηκε επίσης μια δεύτερη εφαρμογή, η οποία μας ώθησε περισσότερο προς την αυτοματοποίηση. Την ίδια χρονιά, εγκαταστήσαμε το Jenkins για πρώτη φορά και γράψαμε ένα σωρό τρομακτικά σενάρια, πολύ παρόμοια με αυτά που δείχνει το fastlane στην τεκμηρίωσή του.

$ 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"

Δυστυχώς, μέχρι τώρα μόνο οι προγραμματιστές μας γνώριζαν πώς λειτουργούν αυτά τα σενάρια και γιατί χρειάζεται αυτή η ατελείωτη στοίβα πλήκτρων, και όταν κάτι έσπασε ξανά, πήραν τα «υπέροχα βράδια» για την ανάλυση των αρχείων καταγραφής.

Έτος 2017

Φέτος μάθαμε ότι υπάρχει τέτοιο πράγμα όπως fastlane. Δεν υπήρχαν τόσες πολλές πληροφορίες όσες υπάρχουν τώρα - πώς να ξεκινήσετε, πώς να το χρησιμοποιήσετε. Και το ίδιο το εργαλείο ήταν ακόμα ακατέργαστο εκείνη την εποχή: τα συνεχή λάθη μόνο μας απογοήτευαν και ήταν δύσκολο να πιστέψουμε στον μαγικό αυτοματισμό που υποσχέθηκαν.

Ωστόσο, τα κύρια βοηθητικά προγράμματα που περιλαμβάνονται στον πυρήνα fastlane είναι gym и pilot, καταφέραμε να το ξεκινήσουμε.

Τα σενάρια μας έχουν βελτιωθεί λίγο.

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

Έχουν βελτιωθεί, έστω και μόνο επειδή δεν είναι όλες οι απαραίτητες παράμετροι xcodebuild, πρέπει να υποδείξετε - gym θα καταλάβει ανεξάρτητα πού και τι βρίσκεται. Και για περισσότερη λεπτομέρεια, μπορείτε να καθορίσετε τα ίδια πλήκτρα όπως στο xcodebuild, μόνο η ονομασία των κλειδιών είναι πιο ξεκάθαρη.

Αυτή τη φορά, χάρη στο γυμναστήριο και τον ενσωματωμένο μορφοποιητή xcpretty, τα αρχεία καταγραφής έχουν γίνει πολύ πιο ευανάγνωστα. Αυτό άρχισε να εξοικονομεί χρόνο για τη διόρθωση σπασμένων συγκροτημάτων και μερικές φορές η ομάδα απελευθέρωσης μπορούσε να το καταλάβει μόνη της.

Δυστυχώς, μετρήσεις ταχύτητας συναρμολόγησης xcodebuild и gym Δεν το κάναμε, αλλά θα εμπιστευόμαστε την τεκμηρίωση - επιτάχυνση έως και 30%.

Ενιαία διαδικασία για όλες τις εφαρμογές

Έτος 2018 και σήμερα

Μέχρι το 2018, η διαδικασία δημιουργίας και διάθεσης εφαρμογών μεταφέρθηκε πλήρως στο Jenkins, οι προγραμματιστές σταμάτησαν να κυκλοφορούν από τα μηχανήματα τους και μόνο η ομάδα κυκλοφορίας είχε το δικαίωμα να κυκλοφορήσει.

Θέλαμε ήδη να βελτιώσουμε την έναρξη των δοκιμών και τη στατική ανάλυση και τα σενάρια μας μεγάλωναν και μεγάλωναν. Αναπτύχθηκε και άλλαξε μαζί με τις εφαρμογές μας. Εκείνη την εποχή, υπήρχαν περίπου 10 εφαρμογές. Λαμβάνοντας υπόψη ότι έχουμε δύο πλατφόρμες, είναι περίπου 20 «ζωντανά» σενάρια.

Κάθε φορά που θέλαμε να προσθέσουμε ένα νέο βήμα στο σενάριο, έπρεπε να κάνουμε copy-paste τα κομμάτια σε όλα τα σενάρια του κελύφους. Ίσως θα μπορούσαμε να είχαμε δουλέψει πιο προσεκτικά, αλλά συχνά τέτοιες αλλαγές κατέληγαν σε τυπογραφικά λάθη, τα οποία μετατράπηκαν σε βραδιές για την ομάδα έκδοσης για να διορθώσει τα σενάρια και να ανακαλύψει ποιος έξυπνος τύπος πρόσθεσε αυτήν την εντολή και τι κάνει στην πραγματικότητα. Σε γενικές γραμμές, δεν μπορεί να ειπωθεί ότι τα σενάρια για τη συναρμολόγηση για μία πλατφόρμα ήταν τουλάχιστον κάπως παρόμοια. Αν και σίγουρα έκαναν το ίδιο πράγμα.

Για να ξεκινήσετε μια διαδικασία για μια νέα εφαρμογή, ήταν απαραίτητο να αφιερώσετε μια μέρα για να επιλέξετε μια «φρέσκια» έκδοση αυτών των σεναρίων, να την διορθώσετε και να πείτε ότι «ναι, λειτουργεί».

Το καλοκαίρι του 2018, κοιτάξαμε για άλλη μια φορά προς το αναπτυσσόμενο fastlane.

Εργασία #1: συνοψίστε όλα τα βήματα του σεναρίου και ξαναγράψτε τα στο Fastfile

Όταν ξεκινήσαμε, τα σενάρια μας έμοιαζαν με ένα ποδόπανο που αποτελείται από όλα τα βήματα και τα δεκανίκια σε ένα σενάριο με κέλυφος στο Jenkins. Δεν έχουμε ακόμη μεταβεί σε αγωγό και διαίρεση κατά στάδιο.

Εξετάσαμε τι έχουμε και εντοπίσαμε 4 βήματα που ταιριάζουν στην περιγραφή του CI/CD μας:

  • κατασκευή - εγκατάσταση εξαρτήσεων, συναρμολόγηση του αρχείου,
  • δοκιμή — εκτέλεση δοκιμών μονάδων προγραμματιστή, υπολογισμός κάλυψης,
  • βυθόμετρο - εκκινεί όλα τα linters και στέλνει αναφορές στο SonarQube,
  • ανάπτυξη — αποστολή ενός τεχνουργήματος στο alpha (TestFlight).

Και αν δεν μπείτε σε λεπτομέρειες, παραλείποντας τα κλειδιά που χρησιμοποιούνται στις ενέργειες, θα λάβετε αυτό το Fastfile:

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

Στην πραγματικότητα, το πρώτο μας Fastfile αποδείχθηκε τερατώδες, λαμβάνοντας υπόψη μερικά από τα δεκανίκια που χρειαζόμασταν ακόμα και τον αριθμό των παραμέτρων που αντικαταστήσαμε:

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

Στο παραπάνω παράδειγμα, μόνο μέρος των παραμέτρων που πρέπει να καθορίσουμε: αυτές είναι οι παράμετροι κατασκευής - σχήμα, διαμόρφωση, ονόματα προφίλ παροχής, καθώς και παράμετροι διανομής - Apple ID του λογαριασμού προγραμματιστή, κωδικός πρόσβασης, αναγνωριστικό εφαρμογής κ.λπ. επί. Ως πρώτη προσέγγιση, βάζουμε όλα αυτά τα κλειδιά σε ειδικά αρχεία - Gymfile, Matchfile и Appfile.

Τώρα στο Jenkins μπορείτε να καλέσετε σύντομες εντολές που δεν θολώνουν την προβολή και είναι εύκολα αναγνώσιμες από το μάτι:

# fastlane ios <lane_name>

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

Ούρα, είμαστε υπέροχοι

Τι πήρες? Εκκαθάριση εντολών για κάθε βήμα. Καθαρισμένα σενάρια, τακτοποιημένα σε αρχεία fastlane. Χαρούμενοι, τρέξαμε στους προγραμματιστές ζητώντας τους να προσθέσουν όλα όσα χρειάζονταν στα αποθετήρια τους.

Αλλά καταλάβαμε εγκαίρως ότι θα συναντούσαμε τις ίδιες δυσκολίες - θα είχαμε ακόμα 20 σενάρια συναρμολόγησης που με τον ένα ή τον άλλο τρόπο θα άρχιζαν να ζουν τη δική τους ζωή, θα ήταν πιο δύσκολο να τα επεξεργαστούμε, αφού τα σενάρια θα μετακινούνταν σε αποθετήρια, και δεν είχαμε πρόσβαση εκεί. Και, γενικά, δεν θα μπορέσει να λυθεί έτσι ο πόνος μας.

Εμπειρία CICD για φορητές συσκευές: ένα πρότυπο fastlane για πολλές εφαρμογές για κινητές συσκευές

Εργασία #2: λάβετε ένα μόνο Fastfile για N εφαρμογές

Τώρα φαίνεται ότι η επίλυση του προβλήματος δεν είναι τόσο δύσκολη - ορίστε τις μεταβλητές και πάμε. Ναι, στην πραγματικότητα, έτσι λύθηκε το πρόβλημα. Αλλά τη στιγμή που το βιδώναμε, δεν είχαμε ούτε εξειδίκευση στο ίδιο το fastlane, ούτε στο Ruby, στο οποίο είναι γραμμένο το fastlane, ούτε χρήσιμα παραδείγματα στο δίκτυο - όλοι όσοι έγραφαν για το fastlane τότε περιορίστηκαν σε ένα παράδειγμα για μία εφαρμογή για έναν προγραμματιστή.

Το Fastlane μπορεί να χειριστεί μεταβλητές περιβάλλοντος και το έχουμε ήδη δοκιμάσει ορίζοντας τον κωδικό πρόσβασης Keychain:

ENV['KEYCHAIN_PASSWORD']

Αφού εξετάσαμε τα σενάρια μας, εντοπίσαμε τα κοινά μέρη:

#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

Τώρα, για να αρχίσουμε να χρησιμοποιούμε αυτά τα κλειδιά σε αρχεία fastlane, έπρεπε να καταλάβουμε πώς να τα παραδώσουμε εκεί. Το Fastlane έχει μια λύση για αυτό: φόρτωση μεταβλητών μέσω dotenv. Η τεκμηρίωση λέει ότι εάν είναι σημαντικό για εσάς να φορτώσετε κλειδιά για διαφορετικούς σκοπούς, δημιουργήστε πολλά αρχεία διαμόρφωσης στον κατάλογο fastlane .env, .env.default, .env.development.

Και μετά αποφασίσαμε να χρησιμοποιήσουμε αυτή τη βιβλιοθήκη λίγο διαφορετικά. Ας τοποθετήσουμε στο αποθετήριο προγραμματιστών όχι τα σενάρια fastlane και τις μετα-πληροφορίες του, αλλά τα μοναδικά κλειδιά αυτής της εφαρμογής στο αρχείο .env.appName.

Οι ίδιοι Fastfile, Appfile, Matchfile и Gymfile, το κρύψαμε σε ξεχωριστό αποθετήριο. Ένα επιπλέον αρχείο με κλειδιά κωδικού πρόσβασης από άλλες υπηρεσίες ήταν κρυμμένο εκεί - .env.
Μπορείτε να δείτε ένα παράδειγμα εδώ.

Εμπειρία CICD για φορητές συσκευές: ένα πρότυπο fastlane για πολλές εφαρμογές για κινητές συσκευές

Στο CI, η κλήση δεν έχει αλλάξει πολύ· έχει προστεθεί ένα κλειδί διαμόρφωσης για μια συγκεκριμένη εφαρμογή:

# 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

Πριν εκτελέσουμε τις εντολές, φορτώνουμε το αποθετήριο μας με σενάρια. Δεν φαίνεται τόσο ωραίο:

git clone [email protected]/FastlaneCICD.git fastlane_temp

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

Άφησε αυτήν τη λύση προς το παρόν, αν και το Fastlane έχει μια λύση για τη λήψη του Fastfile μέσω δράση import_from_git, αλλά λειτουργεί μόνο για το Fastfile, αλλά όχι για άλλα αρχεία. Αν θέλετε «πραγματικά όμορφο», μπορείτε να γράψετε το δικό σας action.

Ένα παρόμοιο σετ έγινε για εφαρμογές Android και ReactNative, τα αρχεία βρίσκονται στο ίδιο αποθετήριο, αλλά σε διαφορετικούς κλάδους iOS, android и react_native.

Όταν η ομάδα έκδοσης θέλει να προσθέσει κάποιο νέο βήμα, οι αλλαγές στο σενάριο καταγράφονται μέσω MR στο git, δεν χρειάζεται πλέον να αναζητάτε τους ένοχους των σπασμένων σεναρίων και γενικά, τώρα πρέπει να προσπαθήσετε να το σπάσετε.

Τώρα αυτό είναι σίγουρα

Προηγουμένως, ξοδεύαμε χρόνο για να διατηρήσουμε όλα τα σενάρια, να τα ενημερώσουμε και να διορθώσουμε όλες τις συνέπειες των ενημερώσεων. Ήταν πολύ απογοητευτικό όταν οι λόγοι για τα λάθη και το χρόνο διακοπής στις εκδόσεις ήταν απλά τυπογραφικά λάθη που ήταν τόσο δύσκολο να παρακολουθούνται στο συνονθύλευμα των σεναρίων του κελύφους. Τώρα τέτοια σφάλματα μειώνονται στο ελάχιστο. Οι αλλαγές γίνονται σε όλες τις εφαρμογές ταυτόχρονα. Και χρειάζονται 15 λεπτά για να τεθεί σε διαδικασία μια νέα εφαρμογή - ρυθμίστε μια διοχέτευση προτύπων στο CI και προσθέστε τα κλειδιά στο αποθετήριο του προγραμματιστή.

Φαίνεται ότι το θέμα με το Fastfile για Android και την υπογραφή εφαρμογής παραμένει ανεξήγητο· αν το άρθρο είναι ενδιαφέρον, θα γράψω μια συνέχεια. Θα χαρώ να δω τις ερωτήσεις ή τις προτάσεις σας "πώς θα λύνατε αυτό το πρόβλημα" στα σχόλια ή στο Telegram bashkirova.

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο