Closed source is best source

Closed source is best source

Releasing a private Swift framework using Cocoapods, Fastlane and some command line tools.

B4f9306896b6eaa56a9a6b9048285f53?s=128

Romain Pouclet

November 19, 2016
Tweet

Transcript

  1. Closed source is best source Cocoaheads Montreal - 11/2016

  2. Hi, I'm Romain · @Palleas on Github, Twitter... · iOS

    developer at Mirego · I love Continuous Integration (it's a disease)
  3. Context · Currently working on a project for a super

    secret client I can't tell you about but OMG it's cool · Working on reusable components for other teams in the company · Unable to give them access to the sources (for now)
  4. Creating the framework

  5. Creating the framework let emojis = ["!", """, "#", "$"]

    public func nicify(_ string: String) -> String { let emoji = emojis[Int(arc4random_uniform(UInt32(emojis.count)))] return "\(string) \(emoji)" }
  6. Building the framework (⌘ + B)

  7. Using the framework in a "sandbox"

  8. Using the framework in a "sandbox"

  9. Using the framework in a "sandbox"

  10. Thank You! Questions ?

  11. (Kidding)

  12. Running the app on a device (iPhone 7+) Framework is

    not working on device !
  13. That's not how you release a framework

  14. Solutions ? · Cocoapods-packager · Carthage · Sweat, tears and

    command line
  15. Cocoapods-packager · Does not seem to play well with Swi!

    · Not actively maintained by the community https://github.com/CocoaPods/cocoapods- packager
  16. Carthage · Carthage is cool · Carthage is slow ·

    Carthage mostly-only works with Github https://github.com/Carthage/Carthage
  17. Sweat, tears and command line · Customize the whole process

    · Learn a lot about frameworks · Still rely on cocoapods
  18. Disclaimer I have never done anything like that before

  19. The goal · Build a framework · Put it on

    a server somewhere · Make it available via Cocoapods over HTTPS
  20. And CI the shit out of it

  21. Let's go back to the framework we built

  22. Digging into the framework

  23. Switching to the command line with lipo Lipo is a

    command line tool to interact with The lipo command creates or operates on universal files.
  24. Switching to the command line with lipo lipo -info BeingNiceIsNice.framework/BeingNiceIsNice

    Architectures are: i386 x86_64 Architectures are: * i386 * x86_64
  25. Devices architectures iPhone architectures are: * armv7 * armv7s *

    armv64
  26. We need to build for the devices and the simulator...

  27. ... and merge the products into one framework

  28. Building the framework (simulator) xcodebuild -scheme BeingNiceIsNice -arch i386 -arch

    x86_64 -sdk iphonesimulator only_active_arch=no
  29. Building the framework (iphone) xcodebuild -scheme BeingNiceIsNice -arch armv7 -arch

    armv7s -arch armv64 -sdk iphoneos only_active_arch=no
  30. Merging the frameworks? Lipo is a command line tool to

    interact with universal files. So let's interact. lipo -create -output "BeingNiceIsNice.framework/BeingNiceIsNice" \ "build/Release-iphoneos/BeingNiceIsNice.framework/BeingNiceIsNice" \ "build/Release-iphonesimulator/BeingNiceIsNice.framework/BeingNiceIsNice"
  31. Add the missing slices · Copy the *.swiftmodule file from

    the simulator framework to the new one cp -r "BeingNiceIsNice.framework/Modules/BeingNiceIsNice.swiftmodule/" "BeingNiceIsNice.framework/Modules/BeingNiceIsNice.swiftmodule"
  32. Checking $ lipo -info BeingNiceIsNice.framework/BeingNiceIsNice Architectures are: i386 x86_64 arvv7

    armv7s arm64
  33. What did we do? · Built the framework for the

    simulator architectures · Built the framework for the devices architectures · Merged two frameworks into a single one
  34. Now for the fun part: Fastlane

  35. Fastlane · Fastlane is the easiest way to automate building

    and releasing apps (seriously) · Written in ruby · 500+ contributors · Great documentation · Great community
  36. Fastfile platform :ios do # ... desc "Deploy a new

    version to the App Store" lane :release do # release the framework end end
  37. Packaging with fastlane · Bump the version number · Build

    the project · Zip the framework · Make it available via cocoapods
  38. Bump the version number new_version = version_bump_podspec('BeingNiceIsNice.podspec') set_info_plist_value( path: 'BeingNiceIsNice/Info.plist',

    key: "CFBundleShortVersionString", value: new_version )
  39. Build the project sh('build-script-from-earlier.sh')

  40. Zip the framework zip( path: "BeingNiceIsNice.framework", output_path: "BeingNiceIsNice-#{new_version}.zip" )

  41. Upload the framework somewhere scp( host: 'some-server.com', username: 'somebody', upload:

    { src: "BeingNiceIsNice-#{new_version}.zip" } )
  42. Cocoapods trivia · Podfile · podspec · Specs repository

  43. Make it available via cocoapods Pod::Spec.new do |s| s.name =

    "BeingNiceIsNice" s.version = "0.4.6" # ... s.source = { :http => "http://some-server.com/BeingNiceIsNice-#{s.version}.zip" } s.vendored_frameworks = "BeingNiceIsNice.framework" end
  44. Make it available via cocoapods pod_push( path: "BeingNiceIsNice.podspec", repo: 'secret-podspecs'

    )
  45. Using the framework source 'secret-podspecs' # ⚠ target 'BeingNiceIsHard' do

    # Comment the next line if you're not using Swift and don't want to use dynamic frameworks use_frameworks! pod 'BeingNiceIsNice' end
  46. Bonus · Run the test with scan · Generate the

    documentation: jazzy · ...
  47. Thank you! Questions ?