$30 off During Our Annual Pro Sale. View Details »

詳解Fastfile

giginet
PRO
September 01, 2018

 詳解Fastfile

giginet
PRO

September 01, 2018
Tweet

More Decks by giginet

Other Decks in Technology

Transcript

  1. ৄղFastfile
    iOSDC 2018 @giginet

    View Slide


  2. • @giginet
    • Cookpad Inc. ٕज़෦ϞόΠϧج൫άϧʔϓ
    • Core contributor of fastlane

    View Slide

  3. View Slide

  4. ର৅
    • ͢ͰʹfastlaneΛಋೖ͍ͯ͠Δਓ
    • ಋೖํ๏ͳͲʹ͍ͭͯ͸͋·Γ৮Ε·ͤΜ
    • RubyͰͷ։ൃʹ׳Ε͍ͯͳ͍ਓ

    View Slide

  5. Agenda
    • fastlane׆༻ࣄྫ঺հ
    • ࠷ڧͷFastfileͷॻ͖ํ
    • ໌೔͔Β࢖͑Δศརػೳ
    • Ξϯνύλʔϯू
    • ޮ཰తσόοάख๏ͷ঺հ

    View Slide

  6. fastlane׆༻ࣄྫू

    View Slide

  7. ίʔυϨϏϡʔ

    View Slide

  8. ϦϦʔεϑϩʔ؅ཧ

    View Slide

  9. αϒϛοτ
    • CIͰϦϦʔεϏϧυͯ͠AppStore Connectʹαϒ
    ϛοτ
    • ΞϓϦ͝ͱʹҟͳͬͨϦϦʔεϑϩʔ
    • Slack͔ΒλάΛࢦఆͯ͠δϣϒΛىಈ
    • ຖिࣗಈతʹϦϦʔε

    View Slide

  10. View Slide

  11. View Slide

  12. ࣾ಺޲͚Ϗϧυ
    • masterΛࣗಈͰEnterpriseϥΠηϯεͰϏϧυͯ͠
    ഑৴αʔϏεͰࣾ಺഑৴
    • ಛఆͷϥϕϧ͕͍ͭͨPR΋ಈ࡞֬ೝ༻ʹ഑৴

    View Slide

  13. ࣾ಺޲͚Ϗϧυ

    View Slide

  14. ࣾ಺޲͚Ϗϧυ

    View Slide

  15. View Slide

  16. એ఻
    • ಈ࡞֬ೝͷͨΊͷࣾ಺ΞϓϦ഑৴αʔϏεΛ৽ͨʹ࡞ͬ
    ͨ࿩

    View Slide

  17. ϝτϦΫεऩू

    View Slide

  18. ͋Γ͕ͪͳ͜ͱ
    • ͳΜͰ΋Fastfileʹॻ͖͕ͪ
    • ͳΜͰ΋Ͱ͖ΔͷͰϩδοΫ૿͕͑ͪ
    • ஌Βͳ͍͏ͪʹյΕ͍ͯΔ
    • fastlane͓͡͞Μ͕͍Δ

    View Slide

  19. ࠷ߴͷFastfileͷॻ͖ํ

    View Slide

  20. Fastfileͷॻ͖ํʢجຊฤʣ

    View Slide

  21. Fastfile
    • جຊతʹ͸Ruby
    • FastlaneͷଞͷΞΫγϣϯ͕؆୯ʹݺ΂Δ
    • ศརͳಠࣗػೳ͕͍͔ͭ͋͘Δ

    View Slide

  22. private_lane
    • ಺෦తʹ͔࣮͠ߦͰ͖ͳ͍lane
    • ڞ௨ॲཧͳͲΛ·ͱΊΔͷʹศར
    • ΄͔ͷlane͔Βݺ΂Δ

    View Slide

  23. private_lane :build_for_appstore do |params|
    scheme = params[:scheme]
    build_ios_app(scheme: scheme)
    end
    lane :release do
    build_for_appstore(scheme: 'MyApp')
    end
    Ҿ਺
    ผͷMBOF͔Βݺ΂Δ

    View Slide

  24. private_lane VS def
    • private_lane͸಺෦తʹ͸ProcʹͳΔͷͰॻ͖ํ͕
    ҟͳΔ
    • Rubyͷdef͸ؔ਺ΦϒδΣΫτͰ͸ͳ͍

    View Slide

  25. private_lane :build_for_appstore do |params|
    next unless params[:scheme]
    build_ios_app
    end
    SFUVSOͰ͸ͳ͍

    View Slide

  26. import
    • ڊେͳFastfileΛ෼ׂͰ͖Δ

    View Slide

  27. # vim: syntax=ruby
    lane :release do
    build_for_appstore
    end
    import 'ReleaseFastfile'
    fastlane/ReleaseFastfile
    fastlane/Fastfile

    View Slide

  28. View Slide

  29. GitHubͰͷγϯλοΫεϋΠϥΠτ
    • Fastfile΍ओཁͳ~file͸ࣗಈతʹRubyͱͯ͠ѻΘΕΔ
    • ϑΝΠϧ໊Λม͑ͨͱ͖ʹਖ਼ৗʹϋΠϥΠτ͞Εͳ͍໰୊
    • ϑΝΠϧͷ1ߦ໨ʹϚδοΫίϝϯτΛهड़͢Δ
    # vim: syntax=ruby

    View Slide

  30. View Slide

  31. Advanced Feature
    • ެࣜυΩϡϝϯτͷAdvanced͕ৄ͍͠
    • https://docs.fastlane.tools/advanced/

    View Slide

  32. Fastfile
    • ͳΜͰ΋ॻ͚͕ͪ
    • = Ruby
    • ͳΜͰ΋ॻ͖͕ͪ
    • ʹFastfile͕ͲΜͲΜංେԽ͍ͯ͘͠

    View Slide

  33. ಡΈ΍͍͢Fastfile΁

    View Slide

  34. Q. ࠷ߴͷFastfileͱ͸

    View Slide

  35. A. ແ

    View Slide

  36. ͦ΋ͦ΋FastfileΛॻ͔ͳ͍
    • Fastfile͸ίʔυΛॻ͘৔ॴͰ͸ͳ͍
    • Fastfile΁ͷهड़ྔΛݮΒ͍ͯ͘͠Ξϓϩʔν

    View Slide

  37. ൿಗ஋΍ઃఆ஋͸؀ڥม਺΁
    • fastlaneͷଟ͘ͷύϥϝʔλ͸؀ڥม਺͔Β౉
    ͢͜ͱ͕Ͱ͖Δ
    • ϋʔυίʔυΛ͢ΔΑΓ؀ڥม਺Ͱ஫ೖͨ͠
    ํ͕σόοάɺϝϯς͠΍͍͢

    View Slide

  38. slack(message: 'Building...',
    slack_url: 'https://hooks.slack.com/
    services/XXXXXXXX/YYYYYYY/ZZZZZZZ',
    channel: '#myapp-dev')
    slack(message: 'Building...')


    export SLACK_URL=https://hooks.slack.com/
    services/XXXXXXXX/YYYYYYY/ZZZZZZZ
    export FL_SLACK_CHANNEL=#myapp-dev

    View Slide

  39. ઃఆͱϩδοΫ͸෼཭͢Δ
    • ~fileΛར༻͢Δ
    • Appfile, Gymfile, Scanfile, Matchfile,
    Deliverfile etc…
    • for_laneͰlane͝ͱͷઃఆ஋΋ར༻Մೳ

    View Slide

  40. lane :buiid_for_appstore do
    gym(xcodeproj: 'MyApp.xcodeproj',
    scheme: 'MyApp',
    configuration: 'Release',
    export_method: 'app-store',
    include_bitcode: true,
    clean: true)
    end

    View Slide

  41. scheme 'MyApp'
    include_bitcode false
    claen true
    for_lane :build_for_inhouse do
    configuration 'Beta'
    export_method 'enterprise'
    end
    for_lane :build_for_release do
    configuration 'Release'
    export_method 'app-store'
    include_bitcode true
    end
    fastlane/Gymfile
    σϑΥϧτ஋Λઃఆ
    MBOF͝ͱʹPWFSSJEF

    View Slide

  42. ActionΛ෼཭͢Δ
    $ bundle exec fastlane new_action

    View Slide

  43. View Slide

  44. module Fastlane
    module Actions
    class GetAnswer < Action
    def self.run(params)
    42
    end
    def self.description
    "Answer to the Ultimate Question of Life, the
    Universe, and Everything"
    end
    end
    end
    end
    get_answer_action.rb
    ΞΫγϣϯ࣮ߦ࣌ͷ
    ॲཧ

    View Slide

  45. actions_path '../actions/'
    lane :show_answer do
    UI.message(get_answer)
    end
    Fastfile
    ࠷্෦Ͱϩʔυ͢Δ

    View Slide

  46. Actionͷ෼཭
    • ύϥϝʔλͷόϦσʔγϣϯ͕͠΍͍͢(ConfigItem)
    • ܕνΣοΫɺόϦσʔλɺNullable
    • ςετ͕ॻ͖΍͍͢(rspec)

    View Slide

  47. $ fastlane generate_certificate \
    app_identifiers:com.example.myapp,com.example.mya
    pp.NotificationService \
    type:production
    ΧϯϚ۠੾Γͷจࣈྻ
    ಛఆͷจࣈྻ͚ͩड͚෇͚͍ͨ

    View Slide

  48. lane generate_certificate |params| do
    # Split app_identifier
    app_identifiers = params[:app_identifiers]
    UI.user_error!("app_identifier must be String") unless
    app_identifier.is_a?(String)
    app_identifiers = app_identifiers.split(',')
    # Validate type
    type = params[:type]
    UI.user_error!("Type must be development or production") unless
    %w(development production).include?(type)
    # Do something...
    end
    ܕνΣοΫ͢Δ
    TQMJU͢Δ
    UZQF͕ਖ਼͍͔͠ΈΔ

    View Slide

  49. def self.available_options
    [
    FastlaneCore::ConfigItem.new(
    key: :type,
    description: "Certificate type to generate. (development or
    production)",
    optional: false,
    verify_block: proc do |value|
    is_valid = %w(development production).include?(value.downcase)
    UI.user_error!(“type is invalid") unless is_valid
    end,
    type: String),
    FastlaneCore::ConfigItem.new(
    ɹɹɹɹkey: :app_identifier,
    ɹɹɹɹshort_option: "-a",
    ɹɹɹɹdescription: "The bundle identifier(s) of your app (comma-
    separated)",
    ɹɹɹɹis_string: false,
    ɹɹɹɹtype: Array),
    ]
    end
    ΦʔόʔϥΠυ

    View Slide

  50. def self.available_options
    [
    FastlaneCore::ConfigItem.new(
    key: :type,
    description: "Certificate type to generate. (development or
    production)",
    optional: false,
    verify_block: proc do |value|
    is_valid = %w(development production).include?(value.downcase)
    UI.user_error!(“type is invalid") unless is_valid
    end,
    type: String),
    FastlaneCore::ConfigItem.new(
    ɹɹɹɹkey: :app_identifiers,
    ɹɹɹɹshort_option: "-a",
    ɹɹɹɹdescription: "The bundle identifier(s) of your app (comma-
    separated)",
    ɹɹɹɹis_string: false,
    ɹɹɹɹtype: Array),
    ]
    end
    ΦʔόʔϥΠυ

    View Slide

  51. ίʔυαΠϯ

    View Slide

  52. XcodeͷઃఆΛ׆༻͢Δ
    • ྫ͑͹഑෍༻ͱࣾ಺Ϗϧυ༻ͳͲͰϏϧυ؀ڥΛෳ਺؅
    ཧ͍ͨ͠
    #VJME
    $POpHVSBUJPO
    %FWFMPQFS
    5FBN
    "QQ*EFOUJpFS
    $PEF4JHOJOH
    4UZMF
    %FCVH 0SHBOJ[BUJPO
    DPNDPPLQBEOFX
    BQQ
    "VUPNBUJD
    3FMFBTF 0SHBOJ[BUJPO
    DPNDPPLQBEOFX
    BQQ
    .BOVBM
    #FUB &OUFSQSJTF
    DPNDPPLQBEOF
    XBQQJOIPVTF
    .BOVBM

    View Slide

  53. View Slide

  54. XcodeͷઃఆΛ׆༻͢Δ
    • FastfileͰApp Identifier΍Code Signing StyleΛॻ͖
    ׵͑
    • update_app_identifier
    • update_project_team
    • automatic_code_signing
    • update_project_provisioning

    View Slide

  55. # Provisioning Profileͷऔಘ
    match(git_branch: "enterprise",
    type: 'enterprise',
    readonly: true,
    app_identifier: 'com.cookpad.myapp-beta')
    provisioning_profile_specifier =
    ENV["sigh_com.cookpad.myapp-beta_appstore_profile-name"]
    provisioning_profile_path = ENV["sigh_com.cookpad.myapp-
    beta_appstore_profile-path"]
    team_id = ENV["sigh_com.cookpad.myapp-beta_appstore_team-
    id"]
    NBUDIͰ1SPWJTJPOJOH1SPpMFΛऔಘ
    1SPWJTJPOJOH1SPpMFͷ1BUI΍໊લΛऔಘ

    View Slide

  56. match
    • Provisioning ProfileΛgitϦϙδτϦͰಉظͰ
    ͖Δ࢓૊Έ

    View Slide

  57. View Slide

  58. View Slide

  59. # Team IDͷߋ৽
    update_project_team(
    teamid: team_id,
    )
    # Automatic Code SigningͷແޮԽ
    disable_automatic_code_signing(
    team_id: team_id,
    profile_name: provisioning_profile_specifier,
    code_sign_identity: 'iPhone Distribution',
    targets: %w(MyApp),
    )
    # Provisioning Profileͷઃఆ
    update_project_provisioning(
    profile: provisioning_profile_path,
    target_filter: 'MyApp',
    )

    View Slide

  60. # App Identifierͷߋ৽
    update_app_identifier(
    app_identifier: 'com.cookpad.myapp-inhouse',
    )
    gym(scheme: 'MyApp-Beta', export_method:
    ‘enterprise')

    View Slide

  61. lane :build_for_inhouse
    # Provisioning Profileͷऔಘ
    match(git_branch: "enterprise",
    type: 'enterprise',
    readonly: true,
    app_identifier: 'com.cookpad.myapp-beta')
    provisioning_profile_specifier = ENV["sigh_com.cookpad.myapp-beta_appstore_profile-name"]
    provisioning_profile_path = ENV["sigh_com.cookpad.myapp-beta_appstore_profile-path"]
    team_id = ENV["sigh_com.cookpad.myapp-beta_appstore_team-id"]
    # Team IDͷߋ৽
    update_project_team(
    teamid: team_id,
    )
    # Automatic Code SigningͷແޮԽ
    disable_automatic_code_signing(
    team_id: team_id,
    profile_name: provisioning_profile_specifier,
    code_sign_identity: 'iPhone Distribution',
    targets: %w(MyApp),
    )
    # Provisioning Profileͷઃఆ
    update_project_provisioning(
    profile: provisioning_profile_path,
    target_filter: 'MyApp',
    )
    # App Identifierͷߋ৽
    update_app_identifier(
    app_identifier: 'com.cookpad.myapp-beta',
    )
    build_ios_app(scheme: 'MyApp-Beta', export_method: 'enterprise')
    end

    View Slide

  62. lane :build_for_inhouse
    # Provisioning Profileͷऔಘ
    match(git_branch: "enterprise",
    type: 'enterprise',
    readonly: true,
    app_identifier: 'com.cookpad.myapp-beta')
    provisioning_profile_specifier = ENV["sigh_com.cookpad.myapp-beta_appstore_profile-name"]
    provisioning_profile_path = ENV["sigh_com.cookpad.myapp-beta_appstore_profile-path"]
    team_id = ENV["sigh_com.cookpad.myapp-beta_appstore_team-id"]
    # Team IDͷߋ৽
    update_project_team(
    teamid: team_id,
    )
    # Automatic Code SigningͷແޮԽ
    disable_automatic_code_signing(
    team_id: team_id,
    profile_name: provisioning_profile_specifier,
    code_sign_identity: 'iPhone Distribution',
    targets: %w(MyApp),
    )
    # Provisioning Profileͷઃఆ
    update_project_provisioning(
    profile: provisioning_profile_path,
    target_filter: 'MyApp',
    )
    # App Identifierͷߋ৽
    update_app_identifier(
    app_identifier: 'com.cookpad.myapp-beta',
    )
    build_ios_app(scheme: 'MyApp-Beta', export_method: 'enterprise')
    end

    View Slide

  63. XcodeͷઃఆΛ׆༻͢Δ
    • ίʔυͰϏϧυઃఆΛॻ͖׵͑ͳ͍
    • XcodeͷBuild ConfigurationΛ׆༻͢Δ

    View Slide

  64. View Slide

  65. View Slide

  66. #VJME
    $POpHVSBU
    JPO
    %FWFMPQF
    S5FBN
    1SPEVDU
    #VOEMF
    *EFOUJpFS
    $PEF
    4JHOJOH
    4UZMF
    1SPEVDU
    #VOEMF
    *EFOUJUZ
    1SPWJTJPOJOH
    1SPpMF
    %FCVH
    0SHBOJ[BUJ
    PO
    DPNDPPLQBE
    OFXBQQ
    "VUPNBUJD
    J04
    %FWFMPQFS
    "VUPNBUJD
    3FMFBTF
    0SHBOJ[BUJ
    PO
    DPNDPPLQBE
    OFXBQQ
    .BOVBM
    J04
    %JTUSJCVUJPO
    NBUDI
    "QQ4UPSF
    DPNDPPLQBE
    OFXBQQ
    #FUB &OUFSQSJTF
    DPNDPPLQBE
    OFXBQQ
    JOIPVTF
    .BOVBM
    J04
    %JTUSJCVJUJPO
    NBUDI
    *O)PVTF
    DPNDPPLQBE
    OFXBQQCFUB

    View Slide

  67. $PEF4JHO*EFOUJUZ
    $PEF4JHOJOH4UZMF
    %FWFMPQFS5FBN
    1SPWJTJPOJOH1SPpMF4QFDJpFS

    View Slide

  68. lane :build_for_appstore do
    # Provisioning Profileͷऔಘ(match)
    app_identifiers = %w(com.cookpad.myapp
    com.cookpad.myapp.NotificationService)
    match(type: 'appstore',
    readonly: true,
    app_identifier: app_identifiers)
    # Ϗϧυ
    gym(scheme: 'MyApp',
    configuration: 'Release',
    export_method: 'app-store')
    end

    View Slide

  69. XcodeͷઃఆΛ׆༻͢Δ
    • ͜Ε͸͜ΕͰಈ͘
    • ͕ɺXcode͕ෆ҆ఆʹͳΓ͕ͪͳͷͰίʔυ
    αΠϯ͸Կ΍ͬͯ΋ਏ͍

    View Slide

  70. ࠷ߴͷFastfileͷͨΊʹ
    • ઃఆ஋͸؀ڥม਺Λ࢖͏
    • ઃఆͱϩδοΫͷ෼཭ɻ~FileΛ׆༻͢Δ
    • ڊେͳϩδοΫ͸Actionʹ͢Δ
    • XcodeͷϏϧυઃఆΛ࢖͏

    View Slide

  71. σόοάख๏

    View Slide

  72. fastlane͋Δ͋Δ
    • खݩͰͷಈ࡞֬ೝ͕μϧ͍
    • ಈ͔ͳͯ͘CIʹpushΛ܁Γฦ͢

    View Slide

  73. σόοάख๏
    • جຊతʹRubyͳͷͰσόοΨʔ͕࢖͑Δ
    • irb, pry, byebug
    • ൿಗ஋͸؀ڥม਺Λ࢖͏
    • envchain
    • ઃఆ஋΋؀ڥม਺Λ࢖͏
    • direnv

    View Slide

  74. pry, pry-nav
    • RubyͷσόοΨ
    • ϒϨΠΫϙΠϯτΛுͬͯREPL͕ىಈͰ͖Δ
    • εςοϓ࣮ߦ΋Ͱ͖Δ(pry-byebug)
    gem 'pry'
    gem 'pry-byebug'

    View Slide

  75. View Slide

  76. # vim: syntax=ruby
    require_fastlane 'pry'
    lane :release do |params|
    binding.pry
    scheme = params[:scheme]
    build_for_appstore
    end
    SFRVJSFͱಉ͡
    #SFBLQPJOU

    View Slide

  77. direnv
    • σόοά༻ʹൿಗ஋Ͱ͸ͳ͍஋͸ϋʔυίʔ
    υ͢ΔΑΓ؀ڥม਺Ͱ༩͑ͨํ͕ศར
    • σΟϨΫτϦ಺ͷ؀ڥม਺Λઃఆͯ͘͠ΕΔ

    • .envrcΛಡΜͰ͘ΕΔ

    View Slide

  78. export [email protected]
    export FL_SLACK_CHANNEL=#ios-dev
    .envrc

    View Slide

  79. envchain
    • ΩʔνΣΠϯʹൿಗ஋Λอଘͯ͠؀ڥม਺͔
    ΒಡΊΔ΍ͭ
    • σόοά༻ʹΑ͘࢖͏஋͸ొ࿥͓ͯ͘͠ͱศ

    View Slide

  80. envchain

    View Slide

  81. ·ͱΊ
    • ࠷ߴͷFastfileͷॻ͖ํ͸FastfileΛॻ͔ͳ͍͜ͱ
    • σʔλ͸ผʹ؅ཧ͢Δ
    • XcodeͷػೳΛར༻͢Δ
    • ϓϥάΠϯɺΞΫγϣϯʹͰ͖Δ΋ͷ͸੾Γग़͢
    • ϩδοΫʹ͸specΛॻ͘

    View Slide

  82. એ఻

    View Slide

  83. એ఻1
    • ಈ࡞֬ೝͷͨΊͷࣾ಺ΞϓϦ഑৴αʔϏεΛ৽ͨʹ࡞ͬ
    ͨ࿩

    View Slide

  84. એ఻2

    ୀ۶ͳ͜ͱ͸App Store Connect APIʹ΍ΒͤΑ͏
    • 9/20(Tue) iOSDC Reject Conference Day 2

    View Slide

  85. એ఻3


    View Slide

  86. ͝ਗ਼ௌ
    ͋Γ͕ͱ͏͍͟͝·ͨ͠

    View Slide