nx-react-native-cli 2.5.4 → 2.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.cjs +41 -41
- package/package.json +1 -1
- package/templates/19.7.0/apps/mobile/project.json +1 -1
- package/templates/21.2.2/apps/mobile/project.json +1 -1
- package/templates/shared/apps/mobile/fastlane/.env.template +4 -4
- package/templates/shared/apps/mobile/scripts/setup-ios-dev-scheme.rb +356 -0
package/package.json
CHANGED
|
@@ -3,12 +3,12 @@ IS_CI=false
|
|
|
3
3
|
|
|
4
4
|
# Match
|
|
5
5
|
GIT_URL=
|
|
6
|
-
GIT_BRANCH=
|
|
7
|
-
GIT_API_TOKEN=
|
|
6
|
+
GIT_BRANCH=main
|
|
8
7
|
|
|
9
8
|
# Firebase
|
|
10
9
|
FIREBASE_SERVICE_ACCOUNT=
|
|
11
|
-
|
|
10
|
+
FASTLANE_FIREBASE_APP_ID_ANDROID=
|
|
11
|
+
FASTLANE_FIREBASE_APP_ID_IOS=
|
|
12
12
|
FASTLANE_FIREBASE_GROUP_TESTERS=
|
|
13
13
|
|
|
14
14
|
# AppStore
|
|
@@ -26,4 +26,4 @@ FASTLANE_CHANGELOGS="Performance and Feature updates"
|
|
|
26
26
|
# Android (Production ONLY, Dev is already handled in build.gradle)
|
|
27
27
|
STORE_PASSWORD=
|
|
28
28
|
KEY_PASSWORD=
|
|
29
|
-
KEY_ALIAS=
|
|
29
|
+
KEY_ALIAS=production
|
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
require 'pathname'
|
|
5
|
+
require 'rexml/document'
|
|
6
|
+
require 'rexml/formatters/pretty'
|
|
7
|
+
require 'rexml/xpath'
|
|
8
|
+
require 'xcodeproj'
|
|
9
|
+
|
|
10
|
+
def ensure_build_configuration(container, config_name, base_config_name)
|
|
11
|
+
existing = container.build_configurations.find { |config| config.name == config_name }
|
|
12
|
+
return :existing if existing
|
|
13
|
+
|
|
14
|
+
base = container.build_configurations.find { |config| config.name == base_config_name }
|
|
15
|
+
raise "Base configuration '#{base_config_name}' was not found." unless base
|
|
16
|
+
|
|
17
|
+
duplicated = container.add_build_configuration(config_name, base.type)
|
|
18
|
+
duplicated.base_configuration_reference = base.base_configuration_reference
|
|
19
|
+
duplicated.build_settings = base.build_settings.dup
|
|
20
|
+
:created
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def upsert_scheme_user_defined_setting(container)
|
|
24
|
+
updated = []
|
|
25
|
+
scheme_by_config = {
|
|
26
|
+
'Dev.Debug' => 'Dev',
|
|
27
|
+
'Dev.Release' => 'Dev',
|
|
28
|
+
'Debug' => 'Prod',
|
|
29
|
+
'Release' => 'Prod'
|
|
30
|
+
}
|
|
31
|
+
bundle_id_suffix_by_config = {
|
|
32
|
+
'Dev.Debug' => '.dev',
|
|
33
|
+
'Dev.Release' => '.dev',
|
|
34
|
+
'Debug' => '',
|
|
35
|
+
'Release' => ''
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
container.build_configurations.each do |config|
|
|
39
|
+
desired_scheme = scheme_by_config[config.name]
|
|
40
|
+
desired_suffix = bundle_id_suffix_by_config[config.name]
|
|
41
|
+
next unless desired_scheme
|
|
42
|
+
|
|
43
|
+
if config.build_settings['SCHEME'] != desired_scheme
|
|
44
|
+
config.build_settings['SCHEME'] = desired_scheme
|
|
45
|
+
updated << "#{container.respond_to?(:name) ? container.name : 'Project'} #{config.name} SCHEME=#{desired_scheme}"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
current_suffix = config.build_settings['BUNDLE_ID_SUFFIX'].to_s
|
|
49
|
+
if current_suffix != desired_suffix
|
|
50
|
+
if desired_suffix.empty?
|
|
51
|
+
config.build_settings.delete('BUNDLE_ID_SUFFIX')
|
|
52
|
+
updated << "#{container.respond_to?(:name) ? container.name : 'Project'} #{config.name} BUNDLE_ID_SUFFIX=<removed>"
|
|
53
|
+
else
|
|
54
|
+
config.build_settings['BUNDLE_ID_SUFFIX'] = desired_suffix
|
|
55
|
+
updated << "#{container.respond_to?(:name) ? container.name : 'Project'} #{config.name} BUNDLE_ID_SUFFIX=#{desired_suffix}"
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
updated
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def extract_base_bundle_identifier(app_target)
|
|
64
|
+
candidate = app_target.build_configurations.map { |config| config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'].to_s.strip }
|
|
65
|
+
.find { |value| !value.empty? && !value.include?('$(PRODUCT_NAME') }
|
|
66
|
+
|
|
67
|
+
return nil if candidate.nil? || candidate.empty?
|
|
68
|
+
|
|
69
|
+
candidate
|
|
70
|
+
.gsub('$(BUNDLE_ID_SUFFIX)', '')
|
|
71
|
+
.gsub(/\.dev\z/, '')
|
|
72
|
+
.strip
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def upsert_product_bundle_identifier(app_target, base_bundle_identifier)
|
|
76
|
+
updated = []
|
|
77
|
+
desired_by_config = {
|
|
78
|
+
'Dev.Debug' => "#{base_bundle_identifier}$(BUNDLE_ID_SUFFIX)",
|
|
79
|
+
'Dev.Release' => "#{base_bundle_identifier}$(BUNDLE_ID_SUFFIX)",
|
|
80
|
+
'Debug' => "#{base_bundle_identifier}$(BUNDLE_ID_SUFFIX)",
|
|
81
|
+
'Release' => "#{base_bundle_identifier}$(BUNDLE_ID_SUFFIX)"
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
app_target.build_configurations.each do |config|
|
|
85
|
+
desired = desired_by_config[config.name]
|
|
86
|
+
next unless desired
|
|
87
|
+
next if config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] == desired
|
|
88
|
+
|
|
89
|
+
config.build_settings['PRODUCT_BUNDLE_IDENTIFIER'] = desired
|
|
90
|
+
updated << "#{app_target.name} #{config.name} PRODUCT_BUNDLE_IDENTIFIER=#{desired}"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
updated
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def extract_base_product_name(app_target)
|
|
97
|
+
candidate = app_target.build_configurations
|
|
98
|
+
.map { |config| config.build_settings['PRODUCT_NAME'].to_s.strip }
|
|
99
|
+
.find { |value| !value.empty? && value != '$(TARGET_NAME)' }
|
|
100
|
+
|
|
101
|
+
return app_target.name if candidate.nil? || candidate.empty?
|
|
102
|
+
|
|
103
|
+
candidate.gsub(/\s*-\s*Dev\z/, '').strip
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def upsert_product_name(app_target, base_product_name)
|
|
107
|
+
updated = []
|
|
108
|
+
desired_by_config = {
|
|
109
|
+
'Dev.Debug' => "#{base_product_name} - Dev",
|
|
110
|
+
'Dev.Release' => "#{base_product_name} - Dev",
|
|
111
|
+
'Debug' => base_product_name,
|
|
112
|
+
'Release' => base_product_name
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
app_target.build_configurations.each do |config|
|
|
116
|
+
desired = desired_by_config[config.name]
|
|
117
|
+
next unless desired
|
|
118
|
+
next if config.build_settings['PRODUCT_NAME'] == desired
|
|
119
|
+
|
|
120
|
+
config.build_settings['PRODUCT_NAME'] = desired
|
|
121
|
+
updated << "#{app_target.name} #{config.name} PRODUCT_NAME=#{desired}"
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
updated
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def resolve_info_plist_paths(app_target, ios_dir, project_name)
|
|
128
|
+
app_target.build_configurations.map { |config| config.build_settings['INFOPLIST_FILE'].to_s.strip }
|
|
129
|
+
.reject(&:empty?)
|
|
130
|
+
.map do |value|
|
|
131
|
+
normalized = value.gsub('$(SRCROOT)', ios_dir).gsub('${SRCROOT}', ios_dir)
|
|
132
|
+
normalized = normalized.gsub('$(PROJECT_NAME)', project_name).gsub('${PROJECT_NAME}', project_name)
|
|
133
|
+
if Pathname.new(normalized).absolute?
|
|
134
|
+
normalized
|
|
135
|
+
else
|
|
136
|
+
File.expand_path(normalized, ios_dir)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
.uniq
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def upsert_info_plist_display_name(app_target, ios_dir, project_name)
|
|
143
|
+
paths = resolve_info_plist_paths(app_target, ios_dir, project_name)
|
|
144
|
+
updated = []
|
|
145
|
+
|
|
146
|
+
paths.each do |path|
|
|
147
|
+
next unless File.exist?(path)
|
|
148
|
+
|
|
149
|
+
plist = Xcodeproj::Plist.read_from_path(path) || {}
|
|
150
|
+
next if plist['CFBundleDisplayName'] == '$(PRODUCT_NAME)'
|
|
151
|
+
|
|
152
|
+
plist['CFBundleDisplayName'] = '$(PRODUCT_NAME)'
|
|
153
|
+
Xcodeproj::Plist.write_to_path(plist, path)
|
|
154
|
+
updated << "Info.plist CFBundleDisplayName=$(PRODUCT_NAME) at #{path}"
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
updated
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def update_scheme_configuration(doc, action_name, build_configuration)
|
|
161
|
+
action = REXML::XPath.first(doc, "//#{action_name}")
|
|
162
|
+
raise "Missing #{action_name} in source scheme." unless action
|
|
163
|
+
|
|
164
|
+
action.attributes['buildConfiguration'] = build_configuration
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def upsert_podfile_project_mapping(podfile_path, project_name)
|
|
168
|
+
return :missing unless File.exist?(podfile_path)
|
|
169
|
+
|
|
170
|
+
desired_block = <<~RUBY.chomp
|
|
171
|
+
project '#{project_name}',
|
|
172
|
+
'Dev.Debug' => :debug,
|
|
173
|
+
'Dev.Release' => :release,
|
|
174
|
+
'Debug' => :debug,
|
|
175
|
+
'Release' => :release
|
|
176
|
+
RUBY
|
|
177
|
+
|
|
178
|
+
content = File.read(podfile_path)
|
|
179
|
+
return :unchanged if content.include?(desired_block)
|
|
180
|
+
|
|
181
|
+
updated = content.dup
|
|
182
|
+
project_block_pattern = /project\s+'[^']+'\s*,\s*(?:\n\s*'[^']+'\s*=>\s*:\w+\s*,?)+/m
|
|
183
|
+
|
|
184
|
+
if updated.match?(project_block_pattern)
|
|
185
|
+
updated.sub!(project_block_pattern, desired_block)
|
|
186
|
+
elsif updated.include?('prepare_react_native_project!')
|
|
187
|
+
updated.sub!(/prepare_react_native_project!\s*\n+/) do
|
|
188
|
+
"prepare_react_native_project!\n\n#{desired_block}\n\n"
|
|
189
|
+
end
|
|
190
|
+
else
|
|
191
|
+
updated = "#{desired_block}\n\n#{updated}"
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
return :unchanged if updated == content
|
|
195
|
+
|
|
196
|
+
File.write(podfile_path, updated)
|
|
197
|
+
:updated
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def upsert_firebase_environment_script_phase(app_target)
|
|
201
|
+
phase_name = 'Setup Firebase Environment GoogleService-Info.plist'
|
|
202
|
+
script_body = <<~'SCRIPT'.strip
|
|
203
|
+
# Name of the resource we're selectively copying
|
|
204
|
+
GOOGLESERVICE_INFO_PLIST=GoogleService-Info.plist
|
|
205
|
+
# Get references to dev and prod versions of the GoogleService-Info.plist
|
|
206
|
+
# NOTE: These should only live on the file system and should NOT be part of the target (since we'll be adding them to the target manually)
|
|
207
|
+
GOOGLESERVICE_INFO_DEV=${PROJECT_DIR}/Firebase/Dev/${GOOGLESERVICE_INFO_PLIST}
|
|
208
|
+
#GOOGLESERVICE_INFO_STAGING=${PROJECT_DIR}/Firebase/Staging/${GOOGLESERVICE_INFO_PLIST}
|
|
209
|
+
GOOGLESERVICE_INFO_PROD=${PROJECT_DIR}/Firebase/Prod/${GOOGLESERVICE_INFO_PLIST}
|
|
210
|
+
# Make sure the dev version of GoogleService-Info.plist exists
|
|
211
|
+
echo "Looking for ${GOOGLESERVICE_INFO_PLIST} in ${GOOGLESERVICE_INFO_DEV}"
|
|
212
|
+
if [ ! -f "${GOOGLESERVICE_INFO_DEV}" ]
|
|
213
|
+
then
|
|
214
|
+
echo "No Dev GoogleService-Info.plist found. Skipping Firebase plist setup."
|
|
215
|
+
exit 0
|
|
216
|
+
fi
|
|
217
|
+
# Make sure the staging version of GoogleService-Info.plist exists
|
|
218
|
+
# echo "Looking for ${GOOGLESERVICE_INFO_PLIST} in ${GOOGLESERVICE_INFO_STAGING}"
|
|
219
|
+
# if [ ! -f $GOOGLESERVICE_INFO_STAGING ]
|
|
220
|
+
# then
|
|
221
|
+
# echo "No Staging GoogleService-Info.plist found. Please ensure it's in the proper directory."
|
|
222
|
+
# exit 1
|
|
223
|
+
# fi
|
|
224
|
+
# Make sure the prod version of GoogleService-Info.plist exists
|
|
225
|
+
echo "Looking for ${GOOGLESERVICE_INFO_PLIST} in ${GOOGLESERVICE_INFO_PROD}"
|
|
226
|
+
if [ ! -f "${GOOGLESERVICE_INFO_PROD}" ]
|
|
227
|
+
then
|
|
228
|
+
echo "No Prod GoogleService-Info.plist found. Skipping Firebase plist setup."
|
|
229
|
+
exit 0
|
|
230
|
+
fi
|
|
231
|
+
|
|
232
|
+
# Log current user-defined configurations
|
|
233
|
+
#echo "CURRENT CONFIGURATION: ${CONFIGURATION}"
|
|
234
|
+
#echo "CURRENT SCHEME: ${SCHEME}"
|
|
235
|
+
#echo "CURRENT PRODUCT_BUNDLE_IDENTIFIER: ${PRODUCT_BUNDLE_IDENTIFIER}"
|
|
236
|
+
#echo "CURRENT BUNDLE_ID_SUFFIX: ${BUNDLE_ID_SUFFIX}"
|
|
237
|
+
#echo "CURRENT FACEBOOK_APP_ID: ${FACEBOOK_APP_ID}"
|
|
238
|
+
#echo "CURRENT FACEBOOK_CLIENT_TOKEN: ${FACEBOOK_CLIENT_TOKEN}"
|
|
239
|
+
|
|
240
|
+
# Get a reference to the destination location for the GoogleService-Info.plist
|
|
241
|
+
PLIST_DESTINATION=${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app
|
|
242
|
+
echo "Will copy ${GOOGLESERVICE_INFO_PLIST} to final destination: ${PLIST_DESTINATION}"
|
|
243
|
+
|
|
244
|
+
# Copy over the prod GoogleService-Info.plist for Release builds
|
|
245
|
+
if [ "${SCHEME}" == "Dev" ]
|
|
246
|
+
then
|
|
247
|
+
echo "Using DEV ${GOOGLESERVICE_INFO_DEV}"
|
|
248
|
+
cp "${GOOGLESERVICE_INFO_DEV}" "${PLIST_DESTINATION}"
|
|
249
|
+
# elif [ "${SCHEME}" == "Staging" ]
|
|
250
|
+
# then
|
|
251
|
+
# echo "Using STAGING ${GOOGLESERVICE_INFO_STAGING}"
|
|
252
|
+
# cp "${GOOGLESERVICE_INFO_STAGING}" "${PLIST_DESTINATION}"
|
|
253
|
+
else
|
|
254
|
+
echo "Using PROD ${GOOGLESERVICE_INFO_PROD}"
|
|
255
|
+
cp "${GOOGLESERVICE_INFO_PROD}" "${PLIST_DESTINATION}"
|
|
256
|
+
fi
|
|
257
|
+
SCRIPT
|
|
258
|
+
|
|
259
|
+
existing_phase = app_target.build_phases.find do |phase|
|
|
260
|
+
phase.isa == 'PBXShellScriptBuildPhase' && phase.name == phase_name
|
|
261
|
+
end
|
|
262
|
+
phase_status = 'existing'
|
|
263
|
+
if existing_phase.nil?
|
|
264
|
+
existing_phase = app_target.new_shell_script_build_phase(phase_name)
|
|
265
|
+
phase_status = 'created'
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
if existing_phase.shell_script != script_body
|
|
269
|
+
existing_phase.shell_script = script_body
|
|
270
|
+
phase_status = phase_status == 'created' ? 'created' : 'updated'
|
|
271
|
+
end
|
|
272
|
+
existing_phase.shell_path = '/bin/bash'
|
|
273
|
+
|
|
274
|
+
resources_phase = app_target.build_phases.find do |phase|
|
|
275
|
+
phase.isa == 'PBXResourcesBuildPhase' ||
|
|
276
|
+
(phase.respond_to?(:display_name) && phase.display_name == 'Copy Bundle Resources') ||
|
|
277
|
+
(phase.respond_to?(:name) && phase.name == 'Copy Bundle Resources')
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
if resources_phase
|
|
281
|
+
app_target.build_phases.delete(existing_phase)
|
|
282
|
+
insert_index = app_target.build_phases.index(resources_phase) || app_target.build_phases.length
|
|
283
|
+
app_target.build_phases.insert(insert_index, existing_phase)
|
|
284
|
+
phase_status = phase_status == 'existing' ? 'reordered' : phase_status
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
phase_status
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
ios_dir = File.join(Dir.pwd, 'ios')
|
|
291
|
+
project_path = Dir.glob(File.join(ios_dir, '*.xcodeproj')).first
|
|
292
|
+
raise 'Could not find an .xcodeproj under ios/.' unless project_path
|
|
293
|
+
|
|
294
|
+
project = Xcodeproj::Project.open(project_path)
|
|
295
|
+
project_name = File.basename(project_path, '.xcodeproj')
|
|
296
|
+
app_target = project.targets.find do |target|
|
|
297
|
+
target.respond_to?(:product_type) && target.product_type == 'com.apple.product-type.application'
|
|
298
|
+
end
|
|
299
|
+
raise 'Could not find an iOS application target in the project.' unless app_target
|
|
300
|
+
|
|
301
|
+
changes = []
|
|
302
|
+
|
|
303
|
+
changes << 'project Dev.Debug' if ensure_build_configuration(project, 'Dev.Debug', 'Debug') == :created
|
|
304
|
+
changes << 'project Dev.Release' if ensure_build_configuration(project, 'Dev.Release', 'Release') == :created
|
|
305
|
+
changes.concat(upsert_scheme_user_defined_setting(project))
|
|
306
|
+
|
|
307
|
+
project.targets.each do |target|
|
|
308
|
+
changes << "#{target.name} Dev.Debug" if ensure_build_configuration(target, 'Dev.Debug', 'Debug') == :created
|
|
309
|
+
changes << "#{target.name} Dev.Release" if ensure_build_configuration(target, 'Dev.Release', 'Release') == :created
|
|
310
|
+
changes.concat(upsert_scheme_user_defined_setting(target))
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
base_bundle_identifier = extract_base_bundle_identifier(app_target)
|
|
314
|
+
raise 'Could not infer base PRODUCT_BUNDLE_IDENTIFIER from app target.' if base_bundle_identifier.nil? || base_bundle_identifier.empty?
|
|
315
|
+
changes.concat(upsert_product_bundle_identifier(app_target, base_bundle_identifier))
|
|
316
|
+
base_product_name = extract_base_product_name(app_target)
|
|
317
|
+
changes.concat(upsert_product_name(app_target, base_product_name))
|
|
318
|
+
changes.concat(upsert_info_plist_display_name(app_target, ios_dir, project_name))
|
|
319
|
+
firebase_phase_status = upsert_firebase_environment_script_phase(app_target)
|
|
320
|
+
changes << "Firebase plist run script #{firebase_phase_status}" unless firebase_phase_status == 'existing'
|
|
321
|
+
|
|
322
|
+
project.save
|
|
323
|
+
|
|
324
|
+
xcschemes_dir = File.join(project_path, 'xcshareddata', 'xcschemes')
|
|
325
|
+
FileUtils.mkdir_p(xcschemes_dir)
|
|
326
|
+
|
|
327
|
+
source_scheme_path = Dir.glob(File.join(xcschemes_dir, '*.xcscheme'))
|
|
328
|
+
.reject { |path| File.basename(path) == 'Dev.xcscheme' }
|
|
329
|
+
.first
|
|
330
|
+
raise 'Could not find a shared scheme to clone in ios/*.xcodeproj/xcshareddata/xcschemes.' unless source_scheme_path
|
|
331
|
+
|
|
332
|
+
scheme_doc = REXML::Document.new(File.read(source_scheme_path))
|
|
333
|
+
update_scheme_configuration(scheme_doc, 'LaunchAction', 'Dev.Debug')
|
|
334
|
+
update_scheme_configuration(scheme_doc, 'TestAction', 'Dev.Debug')
|
|
335
|
+
update_scheme_configuration(scheme_doc, 'AnalyzeAction', 'Dev.Debug')
|
|
336
|
+
update_scheme_configuration(scheme_doc, 'ProfileAction', 'Dev.Release')
|
|
337
|
+
update_scheme_configuration(scheme_doc, 'ArchiveAction', 'Dev.Release')
|
|
338
|
+
|
|
339
|
+
dev_scheme_path = File.join(xcschemes_dir, 'Dev.xcscheme')
|
|
340
|
+
output = +''
|
|
341
|
+
output << %(<?xml version="1.0" encoding="UTF-8"?>\n)
|
|
342
|
+
formatter = REXML::Formatters::Pretty.new(2)
|
|
343
|
+
formatter.compact = true
|
|
344
|
+
formatter.write(scheme_doc.root, output)
|
|
345
|
+
output << "\n"
|
|
346
|
+
File.write(dev_scheme_path, output)
|
|
347
|
+
|
|
348
|
+
podfile_status = upsert_podfile_project_mapping(File.join(ios_dir, 'Podfile'), project_name)
|
|
349
|
+
changes << 'Podfile project mapping' if podfile_status == :updated
|
|
350
|
+
|
|
351
|
+
puts 'Configured iOS build configurations and Dev scheme.'
|
|
352
|
+
if changes.empty?
|
|
353
|
+
puts 'No new build configurations were created (already configured).'
|
|
354
|
+
else
|
|
355
|
+
puts "Created: #{changes.join(', ')}"
|
|
356
|
+
end
|