Upgrade to Pro — share decks privately, control downloads, hide ads and more …

[Mobile Devops Summit] Getting ahead of the gam...

[Mobile Devops Summit] Getting ahead of the game: Avoid release day drama!

Pol Piella Abadia

November 10, 2022
Tweet

More Decks by Pol Piella Abadia

Other Decks in Programming

Transcript

  1. Pol Piella Abadia - 📍Mobile Devops Summit - 10/11/2022 Getting

    ahead of the game: Avoid Release day drama! @polpielladev
  2. • 🧑💻 Senior iOS Engineer @ BBC iPlayer • 📍

    From Barcelona • 🇬🇧 Based in Manchester • ❤ Swift and developer tooling • 👕 Random fact: I collect football shirts! Hi, I’m Pol 👋
  3. Let’s paint a picture Many new features since previous release

    Built with UIKit. New release includes first SwiftUI views CI is all set up using fastlane Modular ( SPM & Xcode Projects) codebase
  4. What does the CI look like? 🧪 • Triggered when

    a push to a PR occurs • Runs Unit Tests • Runs UI Tests • Uses the Debug con fi guration of the App • Performs code style checks PR pipeline 🚀 • Manually triggered • Bumps version • Archives the app • Uploads to the App Store Release pipeline 👨💻 • Triggered by every push to main • Runs Unit Tests • Runs UI Tests • Uses the Debug con fi guration of the App Main pipeline
  5. What does the CI look like? 🚀 • Manually triggered

    • Bumps version • Archives the app • Uploads to the App Store Release pipeline
  6. An unusual archive error 🛑 There is an error with

    the new SwiftUI View No SwiftUI symbols are found The solution is not obvious Need to investigate further
  7. But… App target’s minimum deployment version is 15 Xcode doesn’t

    build for armv7 when targeting iOS > 11 TodayView is imported by the App Target
  8. // swift-tools-version: 5.6 import PackageDescription let package = Package( name:

    "TodayFeature", targets: [ .target( name: "TodayFeature" ), .testTarget( name: "TodayFeatureTests", dependencies: ["TodayFeature"] ) ] ) It was the package all along…
  9. // swift-tools-version: 5.6 import PackageDescription let package = Package( name:

    "TodayFeature", platforms: [ .iOS(.v15) ], targets: [ .target( name: "TodayFeature" ), .testTarget( name: "TodayFeatureTests", dependencies: ["TodayFeature"] ) ] ) It was the package all along…
  10. Upload to ASC 􀀳 Binary contains duplicated bundles. This is

    related to a new framework called Schedule. It is depended on by multiple other frameworks. The error is due to the way Schedule is being imported.
  11. What now?! 😠 It looks like the version of Xcode

    in the CI is not supported App was archived with Xcode 14 beta 2 A stable version of Xcode needs to be installed The beta version was in the CI for testing.
  12. Let’s recap our release SwiftUI symbols could not be found

    on archive Invalid version of Xcode Same binary embedded multiple times Source: https://giphy.com/gifs/this-is- fi ne-QMHoU66sBXqqLqYvGO
  13. 🌅 Could we have caught this early? We should periodically

    check processes that don’t happen often. Scheduled workflows can be very helpful Triggered at specific times using cron expressions A good example are nightly CI runs Certain workflows are time consuming and can cause disruption Source: https://crontab.guru/#0_0_*_*_*
  14. Adding a new CI pipeline 🧪 🚀 PR pipeline 👨💻

    Main pipeline Release pipeline 🌝 Nightly pipeline • Scheduled to run every night • Can be achieved with most CI providers • Archives the app • Validates the binary with App Store Connect.
  15. 🧑💻 Show me the code! 􀇿 The code in the

    following slides uses fastlane but the same result can be achieved using other means, such as with a simple bash script.
  16. lane :nightly do # Let's make some magic happen 🪄

    gym( project: "./NutriFit.xcodeproj", clean: true, derived_data_path: "./derived-data", output_directory: "./build", output_name: "NutriFit.ipa", scheme: "NutriFit", export_options: { provisioningProfiles: { "dev.polpiella.NutriFit" => "NutriFit App Store", } } ) end 🧑💻 Show me the code!
  17. lane :nightly do # Let's make some magic happen 🪄

    gym( project: "./NutriFit.xcodeproj", clean: true, derived_data_path: "./derived-data", output_directory: "./build", output_name: "NutriFit.ipa", scheme: "NutriFit", export_options: { provisioningProfiles: { "dev.polpiella.NutriFit" => "NutriFit App Store", } } ) deliver( ipa: "build/Nutrifit.ipa" ) end 🧑💻 Show me the code!
  18. lane :nightly do # Let's make some magic happen 🪄

    gym( project: "./NutriFit.xcodeproj", clean: true, derived_data_path: "./derived-data", output_directory: "./build", output_name: "NutriFit.ipa", scheme: "NutriFit", export_options: { provisioningProfiles: { "dev.polpiella.NutriFit" => "NutriFit App Store", } } ) deliver( ipa: "build/Nutrifit.ipa", verify_only: true ) end 🧑💻 Show me the code!
  19. 🧐 What else could we do? 📈 • List the

    number of modules in the app. • Show the amount of legacy vs new code (swift vs obj-c?) Collect metrics 🧪 • End 2 End tests • Accessibility testing • Any other ‘specialised’ long-running test plans. Run expensive tests 🧽 • Track the size of the IPA • Vulnerability checks • Unused code analysis - Feature Flags? • Create dependency reports Sanity checks
  20. When to use scheduled workflows… 1⃣ Gaining con fi dence

    in processes which are very important but don’t get run very often (e.g. release pipeline). 2⃣ Performing useful tasks that are time consuming with minimal disruption. 3⃣ Automating repetitive tasks which always happen at a certain time (once a week, twice a month, once a day, etc.)