thrust 0.3.1 → 0.4.0

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.
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