thrust 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/thrust/git.rb CHANGED
@@ -1,67 +1,74 @@
1
1
  require 'colorize'
2
+ require 'tempfile'
2
3
 
3
- class Thrust::Git
4
- def initialize(thrust_executor, out)
5
- @thrust_executor = thrust_executor
6
- @out = out
7
- end
4
+ module Thrust
5
+ class Git
6
+ def initialize(out = $stdout, thrust_executor = Thrust::Executor.new)
7
+ @thrust_executor = thrust_executor
8
+ @out = out
9
+ end
8
10
 
9
- def ensure_clean
10
- if ENV['IGNORE_GIT']
11
- @out.puts 'WARNING NOT CHECKING FOR CLEAN WORKING DIRECTORY'.red
12
- else
13
- @out.puts 'Checking for clean working tree...'
14
- @thrust_executor.system_or_exit 'git diff-index --quiet HEAD'
11
+ def ensure_clean
12
+ if ENV['IGNORE_GIT']
13
+ @out.puts 'WARNING NOT CHECKING FOR CLEAN WORKING DIRECTORY'.red
14
+ else
15
+ @out.puts 'Checking for clean working tree...'
16
+ @thrust_executor.system_or_exit 'git diff-index --quiet HEAD'
17
+ end
15
18
  end
16
- end
17
19
 
18
- def current_commit
19
- @thrust_executor.capture_output_from_system('git log --format=format:%h -1').strip
20
- end
20
+ def current_commit
21
+ @thrust_executor.capture_output_from_system('git log --format=format:%h -1').strip
22
+ end
21
23
 
22
- def reset
23
- @thrust_executor.system_or_exit('git reset --hard')
24
- end
24
+ def reset
25
+ @thrust_executor.system_or_exit('git reset --hard')
26
+ end
25
27
 
26
- def checkout_file(filename)
27
- @thrust_executor.system_or_exit("git checkout #{filename}")
28
- end
28
+ def checkout_file(filename)
29
+ @thrust_executor.system_or_exit("git checkout #{filename}")
30
+ end
29
31
 
30
- def commit_summary_for_last_deploy(deployment_target)
31
- sha_of_latest_deployed_commit = latest_deployed_commit(deployment_target)
32
- if sha_of_latest_deployed_commit
33
- "#{deployment_target}:".blue + " #{summary_for_commit(sha_of_latest_deployed_commit)}"
34
- else
35
- "#{deployment_target}:".blue + ' Never deployed'
32
+ def commit_summary_for_last_deploy(deployment_target)
33
+ sha_of_latest_deployed_commit = latest_deployed_commit(deployment_target)
34
+ if sha_of_latest_deployed_commit
35
+ "#{deployment_target}:".blue + " #{summary_for_commit(sha_of_latest_deployed_commit)}"
36
+ else
37
+ "#{deployment_target}:".blue + ' Never deployed'
38
+ end
36
39
  end
37
- end
38
40
 
39
- def generate_notes_for_deployment(deployment_target)
40
- sha_of_latest_commit = @thrust_executor.capture_output_from_system('git rev-parse HEAD').strip
41
- sha_of_latest_deployed_commit = latest_deployed_commit(deployment_target)
41
+ def generate_notes_for_deployment(deployment_target)
42
+ sha_of_latest_commit = @thrust_executor.capture_output_from_system('git rev-parse HEAD').strip
43
+ sha_of_latest_deployed_commit = latest_deployed_commit(deployment_target)
42
44
 
43
- notes = Tempfile.new('deployment_notes')
45
+ notes = Tempfile.new('deployment_notes')
44
46
 
45
- if sha_of_latest_deployed_commit
46
- @thrust_executor.system_or_exit("git log --oneline #{sha_of_latest_deployed_commit}...#{sha_of_latest_commit}", notes.path)
47
- else
48
- notes.puts(summary_for_commit(sha_of_latest_commit))
49
- notes.close
47
+ if sha_of_latest_deployed_commit
48
+ @thrust_executor.system_or_exit("git log --oneline #{sha_of_latest_deployed_commit}...#{sha_of_latest_commit}", notes.path)
49
+ else
50
+ notes.puts(summary_for_commit(sha_of_latest_commit))
51
+ notes.close
52
+ end
53
+
54
+ notes.path
50
55
  end
51
56
 
52
- notes.path
53
- end
57
+ def commit_count
58
+ @thrust_executor.capture_output_from_system("git rev-list HEAD | wc -l").strip
59
+ end
54
60
 
55
- private
61
+ private
56
62
 
57
- def summary_for_commit(sha)
58
- @thrust_executor.capture_output_from_system("git log --oneline -n 1 #{sha}")
59
- end
63
+ def summary_for_commit(sha)
64
+ @thrust_executor.capture_output_from_system("git log --oneline -n 1 #{sha}")
65
+ end
60
66
 
61
- def latest_deployed_commit(deployment_target)
62
- list = @thrust_executor.capture_output_from_system("autotag list #{deployment_target}")
63
- unless list.strip.empty?
64
- list.split("\n").last.split(" ").first
67
+ def latest_deployed_commit(deployment_target)
68
+ list = @thrust_executor.capture_output_from_system("autotag list #{deployment_target}")
69
+ unless list.strip.empty?
70
+ list.split("\n").last.split(" ").first
71
+ end
65
72
  end
66
73
  end
67
74
  end
@@ -1,13 +1,16 @@
1
- class Thrust::IOS::AgvTool
1
+ module Thrust
2
+ module IOS
3
+ class AgvTool
4
+ def initialize(thrust_executor = Thrust::Executor.new, git = Thrust::Git.new)
5
+ @thrust_executor = thrust_executor
6
+ @git = git
7
+ end
2
8
 
3
- def initialize(thrust_executor, out)
4
- @thrust_executor = thrust_executor
5
- @out = out
6
- @git = Thrust::Git.new(@thrust_executor, @out)
7
- end
8
-
9
- def change_build_number(build_number)
10
- @thrust_executor.system_or_exit "agvtool new-version -all '#{build_number}'"
11
- @git.checkout_file('*.xcodeproj')
9
+ def change_build_number(build_number, path_to_xcodeproj)
10
+ path_to_xcodeproj = path_to_xcodeproj ? File.dirname(path_to_xcodeproj) : '.'
11
+ @thrust_executor.system_or_exit "cd #{path_to_xcodeproj} && agvtool new-version -all '#{build_number}'"
12
+ @git.checkout_file("#{path_to_xcodeproj}/*.xcodeproj")
13
+ end
14
+ end
12
15
  end
13
16
  end
@@ -1,24 +1,39 @@
1
- class Thrust::IOS::Cedar
1
+ require 'tmpdir'
2
2
 
3
- def initialize(thrust_executor = Thrust::Executor.new)
4
- @thrust_executor = thrust_executor
5
- end
3
+ module Thrust
4
+ module IOS
5
+ class Cedar
6
+ def initialize(out = $stdout, thrust_executor = Thrust::Executor.new)
7
+ @thrust_executor = thrust_executor
8
+ @out = out
9
+ end
10
+
11
+ def run(build_configuration, target, runtime_sdk, build_sdk, device, device_type_id, build_dir, simulator_binary)
12
+ if build_sdk == 'macosx'
13
+ build_path = File.join(build_dir, build_configuration)
14
+ app_dir = File.join(build_path, target)
15
+ @thrust_executor.check_command_for_failure(app_dir.inspect, {'DYLD_FRAMEWORK_PATH' => build_path.inspect})
16
+ else
17
+ app_executable = File.join(build_dir, "#{build_configuration}-#{build_sdk}", "#{target}.app")
6
18
 
7
- def run(out, build_configuration, target, runtime_sdk, build_sdk, device, build_dir, simulator_binary)
8
- if build_sdk == 'macosx'
9
- build_path = File.join(build_dir, build_configuration)
10
- app_dir = File.join(build_path, target)
11
- @thrust_executor.check_command_for_failure("DYLD_FRAMEWORK_PATH=#{build_path.inspect} #{app_dir}")
12
- else
13
- app_executable = File.join(build_dir, "#{build_configuration}-#{build_sdk}", "#{target}.app")
19
+ if simulator_binary =~ /waxim%/
20
+ @thrust_executor.check_command_for_failure(%Q[#{simulator_binary} -s #{runtime_sdk} -f #{device} -e CFFIXED_USER_HOME=#{Dir.tmpdir} -e CEDAR_HEADLESS_SPECS=1 -e CEDAR_REPORTER_CLASS=CDRDefaultReporter #{app_executable}])
21
+ elsif simulator_binary =~ /ios-sim$/
22
+ if (device_type_id.nil?)
23
+ if device == "ipad"
24
+ @thrust_executor.check_command_for_failure(%Q[#{simulator_binary} launch #{app_executable} --sdk #{runtime_sdk} --family #{device} --setenv CFFIXED_USER_HOME=#{Dir.tmpdir} --setenv CEDAR_HEADLESS_SPECS=1 --setenv CEDAR_REPORTER_CLASS=CDRDefaultReporter])
25
+ else
26
+ @thrust_executor.check_command_for_failure(%Q[#{simulator_binary} launch #{app_executable} --sdk #{runtime_sdk} --family #{device} --retina --tall --setenv CFFIXED_USER_HOME=#{Dir.tmpdir} --setenv CEDAR_HEADLESS_SPECS=1 --setenv CEDAR_REPORTER_CLASS=CDRDefaultReporter])
27
+ end
28
+ else
29
+ @thrust_executor.check_command_for_failure(%Q[#{simulator_binary} launch #{app_executable} --devicetypeid '#{device_type_id}' --setenv CFFIXED_USER_HOME=#{Dir.tmpdir} --setenv CEDAR_HEADLESS_SPECS=1 --setenv CEDAR_REPORTER_CLASS=CDRDefaultReporter])
30
+ end
14
31
 
15
- if simulator_binary =~ /waxim%/
16
- @thrust_executor.check_command_for_failure(%Q[#{simulator_binary} -s #{runtime_sdk} -f #{device} -e CFFIXED_USER_HOME=#{Dir.tmpdir} -e CEDAR_HEADLESS_SPECS=1 -e CEDAR_REPORTER_CLASS=CDRDefaultReporter #{app_executable}])
17
- elsif simulator_binary =~ /ios-sim$/
18
- @thrust_executor.check_command_for_failure(%Q[#{simulator_binary} launch #{app_executable} --sdk #{runtime_sdk} --family #{device} --retina --tall --setenv CFFIXED_USER_HOME=#{Dir.tmpdir} --setenv CEDAR_HEADLESS_SPECS=1 --setenv CEDAR_REPORTER_CLASS=CDRDefaultReporter])
19
- else
20
- out.puts "Unknown binary for running specs: '#{simulator_binary}'"
21
- false
32
+ else
33
+ @out.puts "Unknown binary for running specs: '#{simulator_binary}'"
34
+ false
35
+ end
36
+ end
22
37
  end
23
38
  end
24
39
  end
@@ -1,27 +1,40 @@
1
- class Thrust::IOS::Deploy
2
- def initialize(out, x_code_tools, agv_tool, git, testflight, thrust_config, deployment_config, deployment_target)
3
- @out = out
4
- @x_code_tools = x_code_tools
5
- @agv_tool = agv_tool
6
- @git = git
7
- @testflight = testflight
8
- @thrust_config = thrust_config
9
- @deployment_config = deployment_config
10
- @deployment_target = deployment_target
11
- end
1
+ module Thrust
2
+ module IOS
3
+ class Deploy
4
+ def initialize(out, x_code_tools, agv_tool, git, testflight, thrust_config, deployment_config, deployment_target)
5
+ @out = out
6
+ @x_code_tools = x_code_tools
7
+ @agv_tool = agv_tool
8
+ @git = git
9
+ @testflight = testflight
10
+ @thrust_config = thrust_config
11
+ @deployment_config = deployment_config
12
+ @deployment_target = deployment_target
13
+ end
14
+
15
+ def run
16
+ @git.ensure_clean
17
+
18
+ if @deployment_config.versioning_method != 'none'
19
+ if (@deployment_config.versioning_method == 'commits')
20
+ @agv_tool.change_build_number(@git.commit_count, @thrust_config.app_config.path_to_xcodeproj)
21
+ else
22
+ @agv_tool.change_build_number(@git.current_commit, @thrust_config.app_config.path_to_xcodeproj)
23
+ end
24
+ end
25
+
12
26
 
13
- def run
14
- @git.ensure_clean
15
- @agv_tool.change_build_number(@git.current_commit)
27
+ app_name = @thrust_config.app_config.app_name
28
+ target = @deployment_config.ios_target || app_name
16
29
 
17
- app_name = @thrust_config.app_config['app_name']
18
- target = @deployment_config['ios_target'] || app_name
19
- ipa_file = @x_code_tools.cleanly_create_ipa(target, app_name, @thrust_config.app_config['ios_distribution_certificate'], @deployment_config['ios_provisioning_search_query'])
30
+ ipa_file = @x_code_tools.cleanly_create_ipa(target, app_name, @thrust_config.app_config.ios_distribution_certificate, @deployment_config.ios_provisioning_search_query)
20
31
 
21
- dsym_path = "#{@x_code_tools.build_configuration_directory}/#{app_name}.app.dSYM"
32
+ dsym_path = "#{@x_code_tools.build_configuration_directory}/#{app_name}.app.dSYM"
22
33
 
23
- autogenerate_notes = @deployment_config['note_generation_method'] == 'autotag'
24
- @testflight.upload(ipa_file, @deployment_config['notify'], @deployment_config['distribution_list'], autogenerate_notes, @deployment_target, dsym_path)
25
- @git.reset
34
+ autogenerate_notes = @deployment_config.note_generation_method == 'autotag'
35
+ @testflight.upload(ipa_file, @deployment_config.notify, @deployment_config.distribution_list, autogenerate_notes, @deployment_target, dsym_path)
36
+ @git.reset
37
+ end
38
+ end
26
39
  end
27
40
  end
@@ -1,15 +1,19 @@
1
- class Thrust::IOS::DeployProvider
2
- def instance(thrust_config, deployment_config, deployment_target)
3
- stdout = $stdout
4
- thrust_executor = Thrust::Executor.new
5
- build_configuration = deployment_config['ios_build_configuration']
6
- tools_options = { project_name: thrust_config.app_config['project_name'], workspace_name: thrust_config.app_config['workspace_name'] }
7
- x_code_tools = Thrust::IOS::XCodeToolsProvider.new.instance(stdout, build_configuration, thrust_config.build_dir, tools_options)
8
- agv_tool = Thrust::IOS::AgvTool.new(thrust_executor, stdout)
9
- git = Thrust::Git.new(thrust_executor, stdout)
10
- testflight_config = thrust_config.app_config['testflight']
11
- testflight = Thrust::Testflight.new(thrust_executor, stdout, $stdin, testflight_config['api_token'], testflight_config['team_token'])
1
+ module Thrust
2
+ module IOS
3
+ class DeployProvider
4
+ def instance(thrust_config, deployment_config, deployment_target)
5
+ stdout = $stdout
6
+ thrust_executor = Thrust::Executor.new
7
+ build_configuration = deployment_config.ios_build_configuration
8
+ tools_options = {project_name: thrust_config.app_config.project_name, workspace_name: thrust_config.app_config.workspace_name}
9
+ x_code_tools = Thrust::IOS::XCodeToolsProvider.new.instance(stdout, build_configuration, thrust_config.build_dir, tools_options)
10
+ git = Thrust::Git.new(stdout, thrust_executor)
11
+ agv_tool = Thrust::IOS::AgvTool.new(thrust_executor, git)
12
+ testflight_config = thrust_config.app_config.testflight
13
+ testflight = Thrust::Testflight.new(thrust_executor, stdout, $stdin, testflight_config.api_token, testflight_config.team_token)
12
14
 
13
- Thrust::IOS::Deploy.new(stdout, x_code_tools, agv_tool, git, testflight, thrust_config, deployment_config, deployment_target)
15
+ Thrust::IOS::Deploy.new(stdout, x_code_tools, agv_tool, git, testflight, thrust_config, deployment_config, deployment_target)
16
+ end
17
+ end
14
18
  end
15
19
  end
@@ -1,110 +1,145 @@
1
- class Thrust::IOS::XCodeTools
2
- ProvisioningProfileNotFound = Class.new(StandardError)
3
-
4
- def initialize(thrust_executor, out, build_configuration, build_directory, options = {})
5
- @thrust_executor = thrust_executor
6
- @out = out
7
- @git = Thrust::Git.new(@thrust_executor, @out)
8
- @build_configuration = build_configuration
9
- @build_directory = build_directory
10
- @project_name = options[:project_name]
11
- @workspace_name = options[:workspace_name]
12
- raise "project_name OR workspace_name required" unless @project_name.nil? ^ @workspace_name.nil?
13
- end
1
+ module Thrust
2
+ module IOS
3
+ class XCodeTools
4
+ ProvisioningProfileNotFound = Class.new(StandardError)
5
+ ProvisioningProfileNotEmbedded = Class.new(StandardError)
14
6
 
15
- def cleanly_create_ipa(target, app_name, signing_identity, provision_search_query = nil)
16
- clean_build
17
- kill_simulator
18
- build_scheme_or_target(target, 'iphoneos')
19
- create_ipa(app_name, signing_identity, provision_search_query)
20
- end
7
+ def initialize(thrust_executor, out, build_configuration, build_directory, options = {})
8
+ @thrust_executor = thrust_executor
9
+ @out = out
10
+ @git = Thrust::Git.new(@out, @thrust_executor)
11
+ @build_configuration = build_configuration
12
+ @build_directory = build_directory
13
+ @project_name = options[:project_name]
14
+ @workspace_name = options[:workspace_name]
15
+ raise "project_name OR workspace_name required" unless @project_name.nil? ^ @workspace_name.nil?
16
+ end
21
17
 
22
- def build_configuration_directory
23
- "#{@build_directory}/#{@build_configuration}-iphoneos"
24
- end
18
+ def cleanly_create_ipa(target, app_name, signing_identity, provision_search_query = nil)
19
+ clean_build
20
+ kill_simulator
21
+ build_scheme_or_target(target, 'iphoneos')
22
+ ipa_name = create_ipa(app_name, signing_identity, provision_search_query)
23
+ verify_provision(app_name, provision_search_query)
25
24
 
26
- def clean_build
27
- @out.puts 'Cleaning...'
28
- FileUtils.rm_rf(@build_directory)
29
- end
25
+ return ipa_name
26
+ end
30
27
 
31
- def build_scheme_or_target(scheme_or_target, build_sdk, architecture=nil)
32
- @out.puts "Building..."
33
- run_xcode('build', build_sdk, scheme_or_target, architecture)
34
- end
28
+ def build_configuration_directory
29
+ "#{@build_directory}/#{@build_configuration}-iphoneos"
30
+ end
35
31
 
36
- private
32
+ def clean_build
33
+ @out.puts 'Cleaning...'
34
+ FileUtils.rm_rf(@build_directory)
35
+ end
37
36
 
38
- def kill_simulator
39
- @out.puts('Killing simulator...')
40
- @thrust_executor.system %q[killall -m -KILL "gdb"]
41
- @thrust_executor.system %q[killall -m -KILL "otest"]
42
- @thrust_executor.system %q[killall -m -KILL "iPhone Simulator"]
43
- end
37
+ def build_scheme_or_target(scheme_or_target, build_sdk, architecture=nil)
38
+ @out.puts "Building..."
39
+ run_xcode('build', build_sdk, scheme_or_target, architecture)
40
+ end
44
41
 
45
- def provision_path(provision_search_query)
46
- provision_search_path = File.expand_path("~/Library/MobileDevice/Provisioning Profiles/")
47
- command = %Q(grep -rl "#{provision_search_query}" "#{provision_search_path}")
48
- paths = `#{command}`.split("\n")
49
- paths.first or raise(ProvisioningProfileNotFound, "\nCouldn't find provisioning profiles matching #{provision_search_query}.\n\nThe command used was:\n\n#{command}")
50
- end
42
+ def test(scheme, build_configuration, runtime_sdk, build_dir)
43
+ destination = "OS=#{runtime_sdk},name=iPhone Retina (3.5-inch)"
51
44
 
52
- def create_ipa(app_name, signing_identity, provision_search_query)
53
- @out.puts 'Packaging...'
54
- ipa_filename = "#{build_configuration_directory}/#{app_name}.ipa"
55
- cmd = [
56
- "xcrun",
57
- "-sdk iphoneos",
58
- "-v PackageApplication",
59
- "'#{build_configuration_directory}/#{app_name}.app'",
60
- "-o '#{ipa_filename}'",
61
- "--sign '#{signing_identity}'",
62
- "--embed '#{provision_path(provision_search_query)}'"
63
- ].join(' ')
64
- @thrust_executor.system_or_exit(cmd)
65
- ipa_filename
66
- end
45
+ cmd = [
46
+ "xcodebuild",
47
+ "test",
48
+ "-scheme #{scheme}",
49
+ "-configuration #{build_configuration}",
50
+ "-destination '#{destination}'",
51
+ "ARCHS=i386",
52
+ "SYMROOT='#{build_dir}'"
53
+ ].join(' ')
67
54
 
68
- def run_xcode(build_command, sdk = nil, scheme_or_target = nil, architecture=nil)
69
- architecture_flag = architecture ? "-arch #{architecture}" : nil
70
- target_flag = @workspace_name ? "-scheme \"#{scheme_or_target}\"" : "-target \"#{scheme_or_target}\""
71
- sdk_flag = sdk ? "-sdk #{sdk}" : nil
72
- configuration_build_dir = File.join(@build_directory, "#{@build_configuration}-#{sdk}")
73
-
74
- command = [
75
- 'set -o pipefail &&',
76
- 'xcodebuild',
77
- project_or_workspace_flag,
78
- architecture_flag,
79
- target_flag,
80
- "-configuration #{@build_configuration}",
81
- sdk_flag,
82
- "#{build_command}",
83
- "SYMROOT=#{@build_directory.inspect}",
84
- "CONFIGURATION_BUILD_DIR=#{configuration_build_dir.inspect}",
85
- '2>&1',
86
- "| grep -v 'backing file'"
87
- ].compact.join(' ')
88
- output_file = output_file("#{@build_configuration}-#{build_command}")
89
- begin
90
- @thrust_executor.system_or_exit(command, output_file)
91
- rescue Thrust::Executor::CommandFailed => e
92
- @out.write File.read(output_file)
93
- raise e
94
- end
95
- end
55
+ @thrust_executor.check_command_for_failure(cmd)
56
+ end
96
57
 
97
- def output_file(target)
98
- output_dir = if ENV['IS_CI_BOX']
99
- ENV['CC_BUILD_ARTIFACTS']
100
- else
101
- File.exists?(@build_directory) ? @build_directory : FileUtils.mkdir_p(@build_directory)
102
- end
58
+ def kill_simulator
59
+ @out.puts('Killing simulator...')
60
+ @thrust_executor.system %q[killall -m -KILL "gdb"]
61
+ @thrust_executor.system %q[killall -m -KILL "otest"]
62
+ @thrust_executor.system %q[killall -m -KILL "iPhone Simulator"]
63
+ end
103
64
 
104
- File.join(output_dir, "#{target}.output").tap { |file| @out.puts "Output: #{file}" }
105
- end
65
+ private
66
+
67
+ def provision_path(provision_search_query)
68
+ provision_search_path = File.expand_path("~/Library/MobileDevice/Provisioning Profiles/")
69
+ command = %Q(grep -rl "#{provision_search_query}" "#{provision_search_path}")
70
+ paths = `#{command}`.split("\n")
71
+ paths.first or raise(ProvisioningProfileNotFound, "\nCouldn't find provisioning profiles matching #{provision_search_query}.\n\nThe command used was:\n\n#{command}")
72
+ end
73
+
74
+ def create_ipa(app_name, signing_identity, provision_search_query)
75
+ @out.puts 'Packaging...'
76
+ ipa_filename = "#{build_configuration_directory}/#{app_name}.ipa"
77
+ cmd = [
78
+ "xcrun",
79
+ "-sdk iphoneos",
80
+ "-v PackageApplication",
81
+ "'#{build_configuration_directory}/#{app_name}.app'",
82
+ "-o '#{ipa_filename}'",
83
+ "--sign '#{signing_identity}'",
84
+ "--embed '#{provision_path(provision_search_query)}'"
85
+ ].join(' ')
86
+ @thrust_executor.system_or_exit(cmd)
87
+ ipa_filename
88
+ end
89
+
90
+ def verify_provision(app_name, provision_search_query)
91
+ @out.puts 'Verifying provisioning profile...'
92
+ embedded_filename = "#{build_configuration_directory}/#{app_name}.app/embedded.mobileprovision"
93
+ correct_provision_filename = provision_path(provision_search_query)
94
+
95
+ if !FileUtils.cmp(embedded_filename, correct_provision_filename)
96
+ raise(ProvisioningProfileNotEmbedded, "Wrong mobile provision embedded by xcrun. Check your xcode provisioning profile settings.")
97
+ end
98
+ end
106
99
 
107
- def project_or_workspace_flag
108
- @workspace_name ? "-workspace #{@workspace_name}.xcworkspace" : "-project #{@project_name}.xcodeproj"
100
+ def run_xcode(build_command, sdk = nil, scheme_or_target = nil, architecture = nil)
101
+ architecture_flag = architecture ? "-arch #{architecture}" : nil
102
+ target_flag = @workspace_name ? "-scheme \"#{scheme_or_target}\"" : "-target \"#{scheme_or_target}\""
103
+ sdk_flag = sdk ? "-sdk #{sdk}" : nil
104
+ configuration_build_dir = File.join(@build_directory, "#{@build_configuration}-#{sdk}").inspect
105
+ configuration_build_dir_option = sdk != 'macosx' ? "CONFIGURATION_BUILD_DIR=#{configuration_build_dir}" : nil
106
+
107
+ command = [
108
+ 'set -o pipefail &&',
109
+ 'xcodebuild',
110
+ project_or_workspace_flag,
111
+ architecture_flag,
112
+ target_flag,
113
+ "-configuration #{@build_configuration}",
114
+ sdk_flag,
115
+ "#{build_command}",
116
+ "SYMROOT=#{@build_directory.inspect}",
117
+ configuration_build_dir_option,
118
+ '2>&1',
119
+ "| grep -v 'backing file'"
120
+ ].compact.join(' ')
121
+ output_file = output_file("#{@build_configuration}-#{build_command}")
122
+ begin
123
+ @thrust_executor.system_or_exit(command, output_file)
124
+ rescue Thrust::Executor::CommandFailed => e
125
+ @out.write File.read(output_file)
126
+ raise e
127
+ end
128
+ end
129
+
130
+ def output_file(target)
131
+ output_dir = if ENV['IS_CI_BOX']
132
+ ENV['CC_BUILD_ARTIFACTS']
133
+ else
134
+ File.exists?(@build_directory) ? @build_directory : FileUtils.mkdir_p(@build_directory)
135
+ end
136
+
137
+ File.join(output_dir, "#{target}.output").tap { |file| @out.puts "Output: #{file}" }
138
+ end
139
+
140
+ def project_or_workspace_flag
141
+ @workspace_name ? "-workspace #{@workspace_name}.xcworkspace" : "-project #{@project_name}.xcodeproj"
142
+ end
143
+ end
109
144
  end
110
145
  end
@@ -1,10 +1,13 @@
1
- class Thrust::IOS::XCodeToolsProvider
1
+ module Thrust
2
+ module IOS
3
+ class XCodeToolsProvider
4
+ def initialize(thrust_executor = Thrust::Executor.new)
5
+ @thrust_executor = thrust_executor
6
+ end
2
7
 
3
- def initialize(thrust_executor = Thrust::Executor.new)
4
- @thrust_executor = thrust_executor
5
- end
6
-
7
- def instance(out, build_configuration, build_directory, options)
8
- Thrust::IOS::XCodeTools.new(@thrust_executor, out, build_configuration, build_directory, options)
8
+ def instance(out, build_configuration, build_directory, options)
9
+ Thrust::IOS::XCodeTools.new(@thrust_executor, out, build_configuration, build_directory, options)
10
+ end
11
+ end
9
12
  end
10
13
  end
@@ -0,0 +1,23 @@
1
+ module Thrust
2
+ class IOSSpecTarget
3
+ attr_reader :build_configuration,
4
+ :build_sdk,
5
+ :device,
6
+ :device_type_id,
7
+ :runtime_sdk,
8
+ :scheme,
9
+ :target,
10
+ :type
11
+
12
+ def initialize(attributes)
13
+ @build_configuration = attributes['build_configuration']
14
+ @build_sdk = attributes['build_sdk'] || 'iphonesimulator'
15
+ @device = attributes['device'] || 'iphone'
16
+ @device_type_id = attributes['device_type_id']
17
+ @runtime_sdk = attributes['runtime_sdk']
18
+ @scheme = attributes['scheme']
19
+ @target = attributes['target']
20
+ @type = attributes['type'] || 'app'
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,15 @@
1
+ module Thrust
2
+ module Tasks
3
+ module Autotag
4
+ class Create
5
+ def initialize(executor = Thrust::Executor.new)
6
+ @executor = executor
7
+ end
8
+
9
+ def run(stage)
10
+ @executor.capture_output_from_system("autotag create #{stage}")
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ module Thrust
2
+ module Tasks
3
+ module Autotag
4
+ class List
5
+ def initialize(git = Thrust::Git.new)
6
+ @git = git
7
+ end
8
+
9
+ def run(thrust)
10
+ thrust.app_config.deployment_targets.each do |deployment_target, _|
11
+ puts @git.commit_summary_for_last_deploy(deployment_target)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ module Thrust
2
+ module Tasks
3
+ class Clean
4
+ def initialize(out = $stdout, xcode_tools_provider = Thrust::IOS::XCodeToolsProvider.new)
5
+ @xcode_tools_provider = xcode_tools_provider
6
+ @out = out
7
+ end
8
+
9
+ def run(thrust)
10
+ tools_options = {
11
+ project_name: thrust.app_config.project_name,
12
+ workspace_name: thrust.app_config.workspace_name
13
+ }
14
+
15
+ xcode_tools = @xcode_tools_provider.instance(@out, nil, thrust.build_dir, tools_options)
16
+ xcode_tools.clean_build
17
+ end
18
+ end
19
+ end
20
+ end