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

How we use fastlane at Wantedly

How we use fastlane at Wantedly

2015.06.26 #fastlane_jp

Jiro Nagashima

June 26, 2015
Tweet

More Decks by Jiro Nagashima

Other Decks in Technology

Transcript

  1. How we use fastlane
    at Wantedly
    JIRO NAGASHIMAʗ@hedjirog

    View Slide

  2. Jiro Nagashima
    @hedjirog
    wantedly.com/users/3153

    View Slide

  3. γΰτͰίίϩΦυϧ

    View Slide

  4. γΰτͰίίϩΦυϧ

    View Slide

  5. γΰτͰίίϩΦυϧ

    View Slide

  6. γΰτͰίίϩΦυϧ
    2 Apps

    View Slide

  7. γΰτͰίίϩΦυϧ
    2 Apps
    1 Project
    (Targets)

    View Slide

  8. γΰτͰίίϩΦυϧ
    • It's a lot of trouble…
    • Beta Distribution
    • Submitting to the App Store
    • Integration Tests
    2 Apps
    (Targets)

    View Slide

  9. γΰτͰίίϩΦυϧ

    View Slide

  10. γΰτͰίίϩΦυϧ
    • Use fastlane to
    1. Distribute beta buils
    2. Submit apps to the App Store
    3. Take screenshots
    fastlane

    View Slide

  11. γΰτͰίίϩΦυϧ
    1. Beta Distribution

    View Slide

  12. Build
    Distribution
    Download
    Import

    View Slide

  13. Build
    Distribution
    Download
    Import

    View Slide

  14. Workflow

    View Slide

  15. Workflow
    Push

    View Slide

  16. γΰτͰίίϩΦυϧ
    • Tools
    • Fabric (Crashlytics Beta)
    • fastlane
    • CircleCI
    Beta Distribution

    View Slide

  17. γΰτͰίίϩΦυϧ
    • Tools
    • Fabric (Crashlytics Beta)
    • fastlane
    • CircleCI
    Beta Distribution

    View Slide

  18. γΰτͰίίϩΦυϧ
    Beta Distribution
    fastlane / Fastfile
    lane :beta do
    # Import certificates
    cert_dir = "./fastlane/certificates"
    import_certificates(
    cert_paths: [
    File.join(cert_dir, "apple.cer")
    ],
    key_paths: [
    File.join(cert_dir, "development.p12"),
    File.join(cert_dir, "distribution.p12")
    ]
    )
    # Download provisioning profiles
    sigh(
    app_identifier: "com.wantedly.app-qa",
    adhoc: true
    )
    # Build
    ipa(
    scheme: "app",
    configuration: "QA"
    )
    # Push to Crashlytics
    crashlytics(
    crashlytics_path: "./Pods/Fabric/Crashlytics.framework",
    groups: "Developers"
    )
    end
    Build
    Distribution
    Download
    Import

    View Slide

  19. γΰτͰίίϩΦυϧ
    Beta Distribution
    fastlane / Fastfile
    lane :beta do
    # Import certificates
    cert_dir = "./fastlane/certificates"
    import_certificates(
    cert_paths: [
    File.join(cert_dir, "apple.cer")
    ],
    key_paths: [
    File.join(cert_dir, "development.p12"),
    File.join(cert_dir, "distribution.p12")
    ]
    )
    # Download provisioning profiles
    sigh(
    app_identifier: "com.wantedly.app-qa",
    adhoc: true
    )
    # Build
    ipa(
    scheme: "app",
    configuration: "QA"
    )
    # Push to Crashlytics
    crashlytics(
    crashlytics_path: "./Pods/Fabric/Crashlytics.framework",
    groups: "Developers"
    )
    end
    Build
    Distribution
    Download
    Import

    View Slide

  20. γΰτͰίίϩΦυϧ
    Beta Distribution
    fastlane / Fastfile
    lane :beta do
    # Import certificates
    cert_dir = "./fastlane/certificates"
    import_certificates(
    cert_paths: [
    File.join(cert_dir, "apple.cer")
    ],
    key_paths: [
    File.join(cert_dir, "development.p12"),
    File.join(cert_dir, "distribution.p12")
    ]
    )
    # Download provisioning profiles
    sigh(
    app_identifier: "com.wantedly.app-qa",
    adhoc: true
    )
    # Build
    ipa(
    scheme: "app",
    configuration: "QA"
    )
    # Push to Crashlytics
    crashlytics(
    crashlytics_path: "./Pods/Fabric/Crashlytics.framework",
    groups: "Developers"
    )
    end
    Build
    Distribution
    Download
    Import

    View Slide

  21. γΰτͰίίϩΦυϧ
    Beta Distribution
    fastlane / Fastfile
    lane :beta do
    # Import certificates
    cert_dir = "./fastlane/certificates"
    import_certificates(
    cert_paths: [
    File.join(cert_dir, "apple.cer")
    ],
    key_paths: [
    File.join(cert_dir, "development.p12"),
    File.join(cert_dir, "distribution.p12")
    ]
    )
    # Download provisioning profiles
    sigh(
    app_identifier: "com.wantedly.app-qa",
    adhoc: true
    )
    # Build
    ipa(
    scheme: "app",
    configuration: "QA"
    )
    # Push to Crashlytics
    crashlytics(
    crashlytics_path: "./Pods/Fabric/Crashlytics.framework",
    groups: "Developers"
    )
    end
    Build
    Distribution
    Download
    Import

    View Slide

  22. γΰτͰίίϩΦυϧ
    Beta Distribution
    fastlane / Fastfile
    lane :beta do
    # Import certificates
    cert_dir = "./fastlane/certificates"
    import_certificates(
    cert_paths: [
    File.join(cert_dir, "apple.cer")
    ],
    key_paths: [
    File.join(cert_dir, "development.p12"),
    File.join(cert_dir, "distribution.p12")
    ]
    )
    # Download provisioning profiles
    sigh(
    app_identifier: "com.wantedly.app-qa",
    adhoc: true
    )
    # Build
    ipa(
    scheme: "app",
    configuration: "QA"
    )
    # Push to Crashlytics
    crashlytics(
    crashlytics_path: "./Pods/Fabric/Crashlytics.framework",
    groups: "Developers"
    )
    end
    Build
    Distribution
    Download
    Import

    View Slide

  23. γΰτͰίίϩΦυϧ
    Beta Distribution
    fastlane / Fastfile - Built-in Action
    lane :beta do
    # Import certificates
    cert_dir = "./fastlane/certificates"
    import_certificates(
    cert_paths: [
    File.join(cert_dir, "apple.cer")
    ],
    key_paths: [
    File.join(cert_dir, "development.p12"),
    File.join(cert_dir, "distribution.p12")
    ]
    )
    # Download provisioning profiles
    sigh(
    app_identifier: "com.wantedly.app-qa",
    adhoc: true
    )
    # Build
    ipa(
    scheme: "app",
    configuration: "QA"
    )
    # Push to Crashlytics
    crashlytics(
    crashlytics_path: "./Pods/Fabric/Crashlytics.framework",
    groups: "Developers"
    )
    end
    Build
    Distribution
    Download
    Import
    Action
    Action
    Action

    View Slide

  24. γΰτͰίίϩΦυϧ
    Beta Distribution
    fastlane / Fastfile - Custom Action
    lane :beta do
    # Import certificates
    cert_dir = "./fastlane/certificates"
    import_certificates(
    cert_paths: [
    File.join(cert_dir, "apple.cer")
    ],
    key_paths: [
    File.join(cert_dir, "development.p12"),
    File.join(cert_dir, "distribution.p12")
    ]
    )
    # Download provisioning profiles
    sigh(
    app_identifier: "com.wantedly.app-qa",
    adhoc: true
    )
    # Build
    ipa(
    scheme: "app",
    configuration: "QA"
    )
    # Push to Crashlytics
    crashlytics(
    crashlytics_path: "./Pods/Fabric/Crashlytics.framework",
    groups: "Developers"
    )
    end
    Build
    Distribution
    Download
    Import
    Custom Action

    View Slide

  25. γΰτͰίίϩΦυϧ
    Beta Distribution
    fastlane / Fastfile - Custom Action
    class ImportCertificatesAction < Action
    def self.run(params)
    cert_paths = params[:cert_paths]
    key_paths = params[:key_paths]
    keychain = "ios-build.keychain"
    password = "ios-build"
    timeout_seconds = 3600
    begin
    sh "security create-keychain -p #{password} #{keychain}"
    sh "security default-keychain -s #{keychain}"
    sh "security list-keychains -s #{keychain}"
    sh "security unlock-keychain -p #{password} #{keychain}"
    sh "security set-keychain-settings -t #{timeout_seconds} -l #{keychain}"
    cert_paths.each do |cert_path|
    sh "security import #{cert_path} -k #{keychain} -T /usr/bin/codesign"
    end
    key_paths.each do |key_path|
    # Don't use `sh` so as not to output a password.
    `security import #{key_path} -k #{keychain} -P #{ENV['P12_PASSWORD']} -T /usr/bin/codesign`
    raise "Password is not correct" unless $?.to_i == 0
    end
    Helper.log.info 'Successfully import certificates .'.green
    rescue => ex
    Helper.log.error 'Failed to import certificates'.red
    raise ex
    end
    end

    View Slide

  26. γΰτͰίίϩΦυϧ
    • Tools
    • Fabric (Crashlytics Beta)
    • fastlane
    • CircleCI
    Beta Distribution

    View Slide

  27. γΰτͰίίϩΦυϧ
    Beta Distribution
    CircleCI / circle.yml
    deployment:
    beta:
    branch: master
    commands:
    - bundle exec fastlane beta_app1
    - bundle exec fastlane beta_app2
    • Execute workflows with fastlane

    View Slide

  28. γΰτͰίίϩΦυϧ
    Beta Distribution
    CircleCI / circle.yml
    deployment:
    beta:
    branch: master
    commands:
    - bundle exec fastlane beta_app1
    - bundle exec fastlane beta_app2
    • Execute workflows with fastlane

    View Slide

  29. γΰτͰίίϩΦυϧ
    2. Submitting Apps

    View Slide

  30. γΰτͰίίϩΦυϧ
    Submitting Apps
    Fastfile
    lane :deploy do
    ensure_git_status_clean
    increment_build_number
    commit_version_bump
    schemes = ["app1", "app2"]
    schemes.each do |scheme|
    ipa(
    scheme: scheme,
    configuration: "Release"
    )
    deliver(
    deliver_file_path: "./fastlane/#{scheme}"
    )
    end
    end

    View Slide

  31. γΰτͰίίϩΦυϧ
    Submitting Apps
    Fastfile
    lane :deploy do
    ensure_git_status_clean
    increment_build_number
    commit_version_bump
    schemes = ["app1", "app2"]
    schemes.each do |scheme|
    ipa(
    scheme: scheme,
    configuration: "Release"
    )
    deliver(
    deliver_file_path: "./fastlane/#{scheme}"
    )
    end
    end
    • Specify Deliverfile for each app

    View Slide

  32. γΰτͰίίϩΦυϧ
    Submitting Apps
    Contents of Directories
    $ tree fastlane
    fastlane
    ├── Fastfile
    ├── app1
    │ ├── Deliverfile
    │ …
    └── app2
    ├── Deliverfile

    View Slide

  33. γΰτͰίίϩΦυϧ
    Submitting Apps
    Contents of Directories
    $ tree fastlane
    fastlane
    ├── Fastfile
    ├── app1
    │ ├── Deliverfile
    │ …
    └── app2
    ├── Deliverfile

    Multiple Deliverfiles

    View Slide

  34. γΰτͰίίϩΦυϧ
    Submitting Apps
    Contents of Directories
    $ tree fastlane
    fastlane
    ├── Fastfile
    └── app1
    ├── Deliverfile
    └── metadata
    └── ja-JP
    ├── description.txt
    ├── keywords.txt
    ├── privacy_url.txt
    ├── software_url.txt
    ├── support_url.txt
    ├── title.txt
    └── version_whats_new.txt

    View Slide

  35. γΰτͰίίϩΦυϧ
    Submitting Apps
    Commands
    $ bundle exec fastlane deploy
    • That’s all!

    View Slide

  36. γΰτͰίίϩΦυϧ
    3. Taking Screenshots

    View Slide

  37. View Slide

  38. View Slide

  39. γΰτͰίίϩΦυϧ
    Taking Screenshots
    iPhone 5
    iPhone 6
    iPhone 6 Plus
    iPad Air
    2 Apps

    View Slide

  40. γΰτͰίίϩΦυϧ
    Taking Screenshots
    Fastfile
    lane :snapshot do
    schemes = ["app1", "app2"]
    schemes.each do |scheme|
    snapshot(
    snapshot_file_path: "./fastlane/#{scheme}"
    )
    end
    end

    View Slide

  41. γΰτͰίίϩΦυϧ
    Taking Screenshots
    Fastfile
    lane :snapshot do
    schemes = ["app1", "app2"]
    schemes.each do |scheme|
    snapshot(
    snapshot_file_path: "./fastlane/#{scheme}"
    )
    end
    end
    • Specify Snapfile for each app

    View Slide

  42. γΰτͰίίϩΦυϧ
    Taking Screenshots
    Contents of Directories
    $ tree fastlane
    fastlane
    ├── Fastfile
    ├── app1
    │ ├── Snapfile
    │ …
    └── app2
    ├── Snapfile

    View Slide

  43. γΰτͰίίϩΦυϧ
    Taking Screenshots
    Contents of Directories
    $ tree fastlane
    fastlane
    ├── Fastfile
    ├── app1
    │ ├── Snapfile
    │ …
    └── app2
    ├── Snapfile

    Multiple Snapfile

    View Slide

  44. γΰτͰίίϩΦυϧ
    Taking Screenshots
    Contents of Directories
    $ tree fastlane
    fastlane
    ├── Fastfile
    └── app1
    ├── Snapfile
    └── js
    ├── helpers
    │ └── capture.js
    ├── screens
    │ ├── activitiesScreen.js
    │ ├── featureScreen.js
    │ ├── messagesScreen.js
    │ ├── profileScreen.js
    │ ├── projectScreen.js
    │ ├── projectsScreen.js
    │ ├── screen.js
    │ ├── settingsScreen.js
    │ └── welcomeScreen.js
    ├── screens.js
    └── snapshot.js

    View Slide

  45. γΰτͰίίϩΦυϧ
    Taking Screenshots
    Commands
    $ bundle exec fastlane snapshot
    • That’s all!

    View Slide

  46. γΰτͰίίϩΦυϧ
    • Use fastlane to
    1. Distribute beta buils
    2. Submit apps to the App Store
    3. Take screenshots

    View Slide

  47. View Slide

  48. View Slide

  49. iOS, Android, Rails Engineer
    WE’RE HIRING!!!

    View Slide