Class: Fastlane::Actions::BuildAppAction

Inherits:
Fastlane::Action show all
Defined in:
fastlane/lib/fastlane/actions/build_app.rb

Direct Known Subclasses

BuildIosAppAction, BuildMacAppAction, GymAction

Constant Summary

Constants inherited from Fastlane::Action

Fastlane::Action::AVAILABLE_CATEGORIES, Fastlane::Action::RETURN_TYPES

Class Method Summary collapse

Methods inherited from Fastlane::Action

action_name, authors, deprecated_notes, lane_context, method_missing, other_action, return_type, sample_return_value, shell_out_should_use_bundle_exec?, step_text

Class Method Details

.authorObject



123
124
125
# File 'fastlane/lib/fastlane/actions/build_app.rb', line 123

def self.author
  "KrauseFx"
end

.available_optionsObject



127
128
129
130
# File 'fastlane/lib/fastlane/actions/build_app.rb', line 127

def self.available_options
  require 'gym'
  Gym::Options.available_options
end

.categoryObject



155
156
157
# File 'fastlane/lib/fastlane/actions/build_app.rb', line 155

def self.category
  :building
end

.descriptionObject

rubocop:enable Metrics/PerceivedComplexity



102
103
104
# File 'fastlane/lib/fastlane/actions/build_app.rb', line 102

def self.description
  "Easily build and sign your app (via _gym_)"
end

.detailsObject



106
107
108
# File 'fastlane/lib/fastlane/actions/build_app.rb', line 106

def self.details
  "More information: https://fastlane.tools/gym"
end

.example_codeObject



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'fastlane/lib/fastlane/actions/build_app.rb', line 136

def self.example_code
  [
    'build_app(scheme: "MyApp", workspace: "MyApp.xcworkspace")',
    'build_app(
      workspace: "MyApp.xcworkspace",
      configuration: "Debug",
      scheme: "MyApp",
      silent: true,
      clean: true,
      output_directory: "path/to/dir", # Destination directory. Defaults to current directory.
      output_name: "my-app.ipa",       # specify the name of the .ipa file to generate (including file extension)
      sdk: "iOS 11.1"                  # use SDK as the name or path of the base SDK when building the project.
    )',
    'gym              # alias for "build_app"',
    'build_ios_app    # alias for "build_app (only iOS options)"',
    'build_mac_app    # alias for "build_app (only macOS options)"'
  ]
end

.is_supported?(platform) ⇒ Boolean

Returns:



132
133
134
# File 'fastlane/lib/fastlane/actions/build_app.rb', line 132

def self.is_supported?(platform)
  [:ios, :mac].include?(platform)
end

.outputObject



110
111
112
113
114
115
116
117
# File 'fastlane/lib/fastlane/actions/build_app.rb', line 110

def self.output
  [
    ['IPA_OUTPUT_PATH', 'The path to the newly generated ipa file'],
    ['PKG_OUTPUT_PATH', 'The path to the newly generated pkg file'],
    ['DSYM_OUTPUT_PATH', 'The path to the dSYM files'],
    ['XCODEBUILD_ARCHIVE', 'The path to the xcodebuild archive']
  ]
end

.return_valueObject



119
120
121
# File 'fastlane/lib/fastlane/actions/build_app.rb', line 119

def self.return_value
  "The absolute path to the generated ipa file"
end

.run(values) ⇒ Object

rubocop:disable Metrics/PerceivedComplexity



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'fastlane/lib/fastlane/actions/build_app.rb', line 12

def self.run(values)
  require 'gym'

  unless Actions.lane_context[SharedValues::SIGH_PROFILE_TYPE].to_s == "development"
    values[:export_method] ||= Actions.lane_context[SharedValues::SIGH_PROFILE_TYPE]
  end

  if Actions.lane_context[SharedValues::MATCH_PROVISIONING_PROFILE_MAPPING]
    # Since Xcode 9 you need to explicitly provide the provisioning profile per app target
    # If the user is smart and uses match and gym together with fastlane, we can do all
    # the heavy lifting for them
    values[:export_options] ||= {}
    # It's not always a hash, because the user might have passed a string path to a ready plist file
    # If that's the case, we won't set the provisioning profiles
    # see https://github.com/fastlane/fastlane/issues/9490
    if values[:export_options].kind_of?(Hash)
      match_mapping = (Actions.lane_context[SharedValues::MATCH_PROVISIONING_PROFILE_MAPPING] || {}).dup
      existing_mapping = (values[:export_options][:provisioningProfiles] || {}).dup

      # Be smart about how we merge those mappings in case there are conflicts
      mapping_object = Gym::CodeSigningMapping.new
      hash_to_use = mapping_object.merge_profile_mapping(primary_mapping: existing_mapping,
                                                       secondary_mapping: match_mapping,
                                                          export_method: values[:export_method])

      values[:export_options][:provisioningProfiles] = hash_to_use
    else
      self.show_xcode_9_warning
    end
  elsif Actions.lane_context[SharedValues::SIGH_PROFILE_PATHS]
    # Since Xcode 9 you need to explicitly provide the provisioning profile per app target
    # If the user used sigh we can match the profiles from sigh
    values[:export_options] ||= {}
    if values[:export_options].kind_of?(Hash)
      # It's not always a hash, because the user might have passed a string path to a ready plist file
      # If that's the case, we won't set the provisioning profiles
      # see https://github.com/fastlane/fastlane/issues/9684
      values[:export_options][:provisioningProfiles] ||= {}
      Actions.lane_context[SharedValues::SIGH_PROFILE_PATHS].each do |profile_path|
        begin
          profile = FastlaneCore::ProvisioningProfile.parse(profile_path)
          app_id_prefix = profile["ApplicationIdentifierPrefix"].first
          entitlements = profile["Entitlements"]
          bundle_id = (entitlements["application-identifier"] || entitlements["com.apple.application-identifier"]).gsub("#{app_id_prefix}.", "")
          values[:export_options][:provisioningProfiles][bundle_id] = profile["Name"]
        rescue => ex
          UI.error("Couldn't load profile at path: #{profile_path}")
          UI.error(ex)
          UI.verbose(ex.backtrace.join("\n"))
        end
      end
    else
      self.show_xcode_9_warning
    end
  end

  gym_output_path = Gym::Manager.new.work(values)
  if gym_output_path.nil?
    UI.important("No output path received from gym")
    return nil
  end

  absolute_output_path = File.expand_path(gym_output_path)

  # Binary path
  if File.extname(absolute_output_path) == ".ipa"
    absolute_dsym_path = absolute_output_path.gsub(/.ipa$/, ".app.dSYM.zip")

    Actions.lane_context[SharedValues::IPA_OUTPUT_PATH] = absolute_output_path
    ENV[SharedValues::IPA_OUTPUT_PATH.to_s] = absolute_output_path # for deliver
  elsif File.extname(absolute_output_path) == ".pkg"
    absolute_dsym_path = absolute_output_path.gsub(/.pkg$/, ".dSYM.zip")

    Actions.lane_context[SharedValues::PKG_OUTPUT_PATH] = absolute_output_path
    ENV[SharedValues::PKG_OUTPUT_PATH.to_s] = absolute_output_path # for deliver
  end

  # xcarchive path
  Actions.lane_context[SharedValues::XCODEBUILD_ARCHIVE] = Gym::BuildCommandGenerator.archive_path

  # dSYM path
  if absolute_dsym_path && File.exist?(absolute_dsym_path)
    Actions.lane_context[SharedValues::DSYM_OUTPUT_PATH] = absolute_dsym_path
    ENV[SharedValues::DSYM_OUTPUT_PATH.to_s] = absolute_dsym_path
  end

  return absolute_output_path
end

.show_xcode_9_warningObject



159
160
161
162
163
164
# File 'fastlane/lib/fastlane/actions/build_app.rb', line 159

def self.show_xcode_9_warning
  return unless Helper.xcode_at_least?("9.0")
  UI.message("You passed a path to a custom plist file for exporting the binary.")
  UI.message("Make sure to include information about what provisioning profiles to use with Xcode 9")
  UI.message("More information: https://docs.fastlane.tools/codesigning/xcode-project/#xcode-9-and-up")
end