thrust 0.2.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/thrust +8 -1
- data/lib/config/android_example.yml +17 -0
- data/lib/config/ios_example.yml +39 -0
- data/lib/tasks/cedar.rake +26 -18
- data/lib/tasks/testflight.rake +3 -3
- data/lib/tasks/version.rake +12 -0
- data/lib/thrust/android/deploy.rb +0 -11
- data/lib/thrust/android/deploy_provider.rb +13 -0
- data/lib/thrust/android/tools.rb +19 -13
- data/lib/thrust/config.rb +1 -1
- data/lib/thrust/executor.rb +9 -7
- data/lib/thrust/git.rb +10 -9
- data/lib/thrust/ios/agv_tool.rb +13 -0
- data/lib/thrust/ios/cedar.rb +8 -4
- data/lib/thrust/ios/deploy.rb +3 -12
- data/lib/thrust/ios/deploy_provider.rb +15 -0
- data/lib/thrust/ios/x_code_tools.rb +46 -53
- data/lib/thrust/ios/x_code_tools_provider.rb +10 -0
- data/lib/thrust/tasks.rb +3 -3
- data/lib/thrust/testflight.rb +5 -4
- data/lib/thrust.rb +4 -0
- metadata +21 -14
- data/lib/config/example.yml +0 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 978a630b927682d5514cf9ce5b71ce2bc2c9a9ff
|
4
|
+
data.tar.gz: ca9c565b330db40e39c02a7ca6ee600ae1a1a682
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 483178b25da64bc6d343d3032fc60b4d0bf12fdf5380794564a4bec13f2dc0e97dd6424f4111ff06c83ce891d71d5ce5e30c48ae784b0ecb8824f91142edcbe8
|
7
|
+
data.tar.gz: 79ea4ddc3b9ad3879d0572a354922b7a1d2ac4450f1134ee2cdf53103a916e6c3414487d6801458165adc573924c530c0c6ceb467a38f57586a722ca35d9123d
|
data/bin/thrust
CHANGED
@@ -20,7 +20,14 @@ File.open(rakefile, 'a') do |f|
|
|
20
20
|
f.puts "require 'thrust/tasks'"
|
21
21
|
end
|
22
22
|
|
23
|
-
|
23
|
+
if File.exists?('AndroidManifest.xml')
|
24
|
+
example_file_name = 'android_example.yml'
|
25
|
+
else
|
26
|
+
example_file_name = 'ios_example.yml'
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
FileUtils.cp(File.join(thrust_root, 'lib', 'config', example_file_name), File.join(project_root, 'thrust.example.yml'))
|
24
31
|
puts ''
|
25
32
|
puts " To finish installation of " + "Thrust".green + ", rename:\n\n"
|
26
33
|
puts " #{project_root}/thrust.example.yml\n".blue
|
@@ -0,0 +1,17 @@
|
|
1
|
+
thrust_version: 0.3
|
2
|
+
project_name: My Great Project
|
3
|
+
app_name: My Great App
|
4
|
+
|
5
|
+
testflight:
|
6
|
+
api_token: 'testflight api token'
|
7
|
+
team_token: 'testflight team token'
|
8
|
+
|
9
|
+
deployment_targets:
|
10
|
+
staging:
|
11
|
+
distribution_list: Developers
|
12
|
+
notify: true
|
13
|
+
note_generation_method: autotag # If you set this value, it will auto-generate the deploy notes from the commit history. Optional.
|
14
|
+
|
15
|
+
demo:
|
16
|
+
distribution_list: Beta Testers
|
17
|
+
notify: true
|
@@ -0,0 +1,39 @@
|
|
1
|
+
thrust_version: 0.3
|
2
|
+
project_name: My Great Project # do not use if building with an xcode workspace
|
3
|
+
# workspace_name: My Workspace # use if building with an xcode workspace
|
4
|
+
app_name: My Great App
|
5
|
+
ios_distribution_certificate: 'Name of Distribution Signing Certificate'
|
6
|
+
ios_sim_binary: 'ios-sim' # or wax-sim. iOS only.
|
7
|
+
|
8
|
+
testflight:
|
9
|
+
api_token: 'testflight api token' # To find your App Token, follow the instructions at: http://help.testflightapp.com/customer/portal/articles/829956-what-does-the-api-token-do-
|
10
|
+
team_token: 'testflight team token' # To find your Team Token, follow the instructions at: http://help.testflightapp.com/customer/portal/articles/829942-how-do-i-find-my-team-token-
|
11
|
+
|
12
|
+
deployment_targets:
|
13
|
+
staging:
|
14
|
+
distribution_list: Developers # This is the name of a TestFlight distribution list
|
15
|
+
notify: true # Whether to notify people on the distribution list about this deployment
|
16
|
+
note_generation_method: autotag # If you set this value, it will auto-generate the deploy notes from the commit history. Optional.
|
17
|
+
ios_target: MyGreatAppTarget # Name of the build target. Optional, defaults to app name. iOS only.
|
18
|
+
ios_build_configuration: Release # iOS only
|
19
|
+
ios_provisioning_search_query: 'query to find Provisioning Profile' # iOS only. Optional.
|
20
|
+
|
21
|
+
demo:
|
22
|
+
distribution_list: Beta Testers
|
23
|
+
notify: true
|
24
|
+
|
25
|
+
ios_spec_targets:
|
26
|
+
specs: # This is the name of the rake task: `rake specs`
|
27
|
+
target: UISpecs # name of the build target
|
28
|
+
# scheme: Specs (My Great App) # use in addition to target when you want to use a scheme (necessary if you are building with an xcode workspace)
|
29
|
+
build_configuration: Debug # name of the build configuration
|
30
|
+
build_sdk: iphonesimulator7.0 # SDK used to build the target. Optional, defaults to latest iphonesimulator.
|
31
|
+
runtime_sdk: 7.0 # SDK used to run the target. Not optional.
|
32
|
+
device: ipad # Device to run the specs on. Optional, defaults to iPhone.
|
33
|
+
|
34
|
+
integration:
|
35
|
+
target: IntegrationSpecs
|
36
|
+
# scheme: IntegrationSpecs (My Great App) # use in addition to target when you want to use a scheme (necessary if you are building with an xcode workspace)
|
37
|
+
build_configuration: Release
|
38
|
+
build_sdk: macosx
|
39
|
+
runtime_sdk: macosx
|
data/lib/tasks/cedar.rake
CHANGED
@@ -3,6 +3,8 @@ require 'tmpdir'
|
|
3
3
|
require File.expand_path('../../thrust', __FILE__)
|
4
4
|
|
5
5
|
@thrust = Thrust::Config.make(Dir.getwd, File.join(Dir.getwd, 'thrust.yml'))
|
6
|
+
@xcode_tools_provider = Thrust::IOS::XCodeToolsProvider.new
|
7
|
+
@executor = Thrust::Executor.new
|
6
8
|
|
7
9
|
desc 'Trim whitespace'
|
8
10
|
task :trim do
|
@@ -16,51 +18,57 @@ task :trim do
|
|
16
18
|
AWK
|
17
19
|
awk_statement.gsub!(%r{\s+}, " ")
|
18
20
|
|
19
|
-
|
21
|
+
@executor.system_or_exit %Q[git status --porcelain | awk '#{awk_statement}' | grep -e '.*\.[cmh]$' | xargs sed -i '' -e 's/ / /g;s/ *$//g;']
|
20
22
|
end
|
21
23
|
|
22
|
-
desc
|
24
|
+
desc 'Remove any focus from specs'
|
23
25
|
task :nof do
|
24
26
|
substitutions = focused_methods.map do |method|
|
25
27
|
unfocused_method = method.sub(/^f/, '')
|
26
28
|
"-e 's/#{method}/#{unfocused_method}/g;'"
|
27
29
|
end
|
28
30
|
|
29
|
-
|
31
|
+
@executor.system_or_exit %Q[ rake focused_specs | xargs -I filename sed -i '' #{substitutions.join(' ')} "filename" ]
|
30
32
|
end
|
31
33
|
|
32
|
-
desc
|
34
|
+
desc 'Print out names of files containing focused specs'
|
33
35
|
task :focused_specs do
|
34
36
|
pattern = focused_methods.join("\\|")
|
35
37
|
directories = @thrust.app_config['ios_spec_targets'].values.map {|h| h['target']}.join(' ')
|
36
|
-
|
38
|
+
@executor.system_or_exit %Q[ grep -l -r -e "\\(#{pattern}\\)" #{directories} | grep -v 'Frameworks' ; exit 0 ]
|
37
39
|
end
|
38
40
|
|
39
41
|
desc 'Clean all targets'
|
40
|
-
task :
|
41
|
-
|
42
|
-
xcode_tools = Thrust::IOS::XCodeTools.new($stdout, config, @thrust.build_dir, @thrust.app_config['project_name'])
|
43
|
-
xcode_tools.clean_build
|
44
|
-
end
|
42
|
+
task :clean do
|
43
|
+
xcode_tools_instance(nil).clean_build
|
45
44
|
end
|
46
45
|
|
46
|
+
desc 'Clean all targets (deprecated, use "clean")'
|
47
|
+
task :clean_build => :clean
|
48
|
+
|
47
49
|
(@thrust.app_config['ios_spec_targets'] || []).each do |task_name, target_info|
|
48
|
-
desc "Run the #{target_info['target']} target"
|
49
|
-
task task_name do
|
50
|
+
desc target_info['scheme'] ? "Run the #{target_info['scheme'].inspect} scheme" : "Run the #{target_info['target'].inspect} target"
|
51
|
+
task task_name, :runtime_sdk do |_, args|
|
50
52
|
build_configuration = target_info['build_configuration']
|
51
53
|
target = target_info['target']
|
54
|
+
scheme = target_info['scheme']
|
52
55
|
build_sdk = target_info['build_sdk'] || 'iphonesimulator' #build sdk - version you compile the code with
|
53
|
-
runtime_sdk = target_info['runtime_sdk'] #runtime sdk
|
56
|
+
runtime_sdk = args[:runtime_sdk] || target_info['runtime_sdk'] #runtime sdk
|
54
57
|
|
55
|
-
xcode_tools =
|
56
|
-
xcode_tools.
|
58
|
+
xcode_tools = xcode_tools_instance(build_configuration)
|
59
|
+
xcode_tools.build_scheme_or_target(scheme || target, build_sdk, 'i386')
|
57
60
|
|
58
|
-
cedar_success = Thrust::IOS::Cedar.run($stdout, build_configuration, target, runtime_sdk, build_sdk, target_info['device'], @thrust.build_dir, @thrust.app_config['ios_sim_binary'])
|
61
|
+
cedar_success = Thrust::IOS::Cedar.new.run($stdout, build_configuration, target, runtime_sdk, build_sdk, target_info['device'], @thrust.build_dir, @thrust.app_config['ios_sim_binary'])
|
59
62
|
|
60
|
-
|
63
|
+
exit(1) unless cedar_success
|
61
64
|
end
|
62
65
|
end
|
63
66
|
|
64
67
|
def focused_methods
|
65
|
-
|
68
|
+
%w(fit fcontext fdescribe).map { |method| "#{method}(@" }
|
69
|
+
end
|
70
|
+
|
71
|
+
def xcode_tools_instance(build_configuration)
|
72
|
+
tools_options = { project_name: @thrust.app_config['project_name'], workspace_name: @thrust.app_config['workspace_name'] }
|
73
|
+
@xcode_tools_provider.instance($stdout, build_configuration, @thrust.build_dir, tools_options)
|
66
74
|
end
|
data/lib/tasks/testflight.rake
CHANGED
@@ -11,14 +11,14 @@ namespace :testflight do
|
|
11
11
|
if android_project
|
12
12
|
desc "Deploy Android build to #{task_name} (use NOTIFY=false to prevent team notification)"
|
13
13
|
task task_name do |_, _|
|
14
|
-
Thrust::Android::
|
14
|
+
Thrust::Android::DeployProvider.new.instance(@thrust, deployment_config, task_name).run
|
15
15
|
|
16
16
|
Rake::Task['autotag:create'].invoke(task_name)
|
17
17
|
end
|
18
18
|
else
|
19
19
|
desc "Deploy iOS build to #{task_name} (use NOTIFY=false to prevent team notification)"
|
20
20
|
task task_name do |_, _|
|
21
|
-
Thrust::IOS::
|
21
|
+
Thrust::IOS::DeployProvider.new.instance(@thrust, deployment_config, task_name).run
|
22
22
|
|
23
23
|
Rake::Task['autotag:create'].invoke(task_name)
|
24
24
|
end
|
@@ -34,7 +34,7 @@ namespace :autotag do
|
|
34
34
|
desc 'Show the commit that is currently deployed to each environment'
|
35
35
|
task :list do
|
36
36
|
@thrust.app_config['deployment_targets'].each do |deployment_target, _|
|
37
|
-
puts Thrust::Git.new($stdout).commit_summary_for_last_deploy(deployment_target)
|
37
|
+
puts Thrust::Git.new(Thrust::Executor.new, $stdout).commit_summary_for_last_deploy(deployment_target)
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require File.expand_path('../../thrust', __FILE__)
|
2
|
+
|
3
|
+
desc 'Set build number'
|
4
|
+
task :set_build_number, :build_number do |_, args|
|
5
|
+
executor = Thrust::Executor.new
|
6
|
+
|
7
|
+
if File.exists?('AndroidManifest.xml')
|
8
|
+
Thrust::Android::Tools.new(executor, $stdout).change_build_number(Time.now.utc.strftime('%y%m%d%H%M'), args[:build_number])
|
9
|
+
else
|
10
|
+
Thrust::IOS::AgvTool.new(executor, $stdout).change_build_number(args[:build_number])
|
11
|
+
end
|
12
|
+
end
|
@@ -1,15 +1,4 @@
|
|
1
1
|
class Thrust::Android::Deploy
|
2
|
-
def self.make(thrust_config, deployment_config, deployment_target)
|
3
|
-
tools = Thrust::Android::Tools.new($stdout)
|
4
|
-
git = Thrust::Git.new($stdout)
|
5
|
-
|
6
|
-
testflight_config = thrust_config.app_config['testflight']
|
7
|
-
testflight = Thrust::Testflight.new($stdout, $stdin, testflight_config['api_token'], testflight_config['team_token'])
|
8
|
-
|
9
|
-
autogenerate_notes = deployment_config['note_generation_method'] == 'autotag'
|
10
|
-
new($stdout, tools, git, testflight, deployment_config['notify'], deployment_config['distribution_list'], autogenerate_notes, deployment_target)
|
11
|
-
end
|
12
|
-
|
13
2
|
def initialize(out, tools, git, testflight, notify, distribution_list, autogenerate_notes, deployment_target)
|
14
3
|
@out = out
|
15
4
|
@tools = tools
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class Thrust::Android::DeployProvider
|
2
|
+
def instance(thrust_config, deployment_config, deployment_target)
|
3
|
+
thrust_executor = Thrust::Executor.new
|
4
|
+
tools = Thrust::Android::Tools.new(thrust_executor, $stdout)
|
5
|
+
git = Thrust::Git.new(thrust_executor, $stdout)
|
6
|
+
|
7
|
+
testflight_config = thrust_config.app_config['testflight']
|
8
|
+
testflight = Thrust::Testflight.new(thrust_executor, $stdout, $stdin, testflight_config['api_token'], testflight_config['team_token'])
|
9
|
+
|
10
|
+
autogenerate_notes = deployment_config['note_generation_method'] == 'autotag'
|
11
|
+
Thrust::Android::Deploy.new($stdout, tools, git, testflight, deployment_config['notify'], deployment_config['distribution_list'], autogenerate_notes, deployment_target)
|
12
|
+
end
|
13
|
+
end
|
data/lib/thrust/android/tools.rb
CHANGED
@@ -1,33 +1,39 @@
|
|
1
1
|
require 'colorize'
|
2
2
|
|
3
3
|
class Thrust::Android::Tools
|
4
|
-
def initialize(out)
|
4
|
+
def initialize(thrust_executor, out)
|
5
|
+
@thrust_executor = thrust_executor
|
5
6
|
@out = out
|
6
|
-
|
7
|
-
if ENV['ANDROID_HOME'].nil?
|
8
|
-
if File.directory?('/usr/local/opt/android-sdk')
|
9
|
-
@out.puts 'Setting /usr/local/opt/android-sdk as ANDROID_HOME...'.magenta
|
10
|
-
ENV['ANDROID_HOME'] = '/usr/local/opt/android-sdk'
|
11
|
-
else
|
12
|
-
raise('**********Android is not installed. Run `brew install android`.**********')
|
13
|
-
end
|
14
|
-
end
|
15
7
|
end
|
16
8
|
|
17
9
|
def change_build_number(version_code, version_name)
|
18
|
-
|
10
|
+
@thrust_executor.system_or_exit(
|
19
11
|
"sed -i ''" +
|
20
12
|
" -e 's/android:versionCode=\"[0-9]*\"/android:versionCode=\"#{version_code}\"/'" +
|
21
13
|
" -e 's/android:versionName=\"\\([^ \"]*\\)[^\"]*\"/android:versionName=\"\\1 (#{version_name})\"/'" +
|
22
14
|
" AndroidManifest.xml")
|
23
|
-
|
15
|
+
@thrust_executor.system_or_exit(
|
24
16
|
"sed -i ''" +
|
25
17
|
" '1,/<version>/s/<version>\\([^- <]*\\)[^<]*<\\/version>/<version>\\1 (#{version_name})<\\/version>/'" +
|
26
18
|
" pom.xml")
|
27
19
|
end
|
28
20
|
|
29
21
|
def build_signed_release
|
30
|
-
|
22
|
+
verify_android_installed!
|
23
|
+
@thrust_executor.system_or_exit('mvn clean package -Prelease')
|
31
24
|
Dir.glob('target/*-signed-aligned.apk').first or raise 'Signed APK was not generated'
|
32
25
|
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def verify_android_installed!
|
30
|
+
if ENV['ANDROID_HOME'].nil?
|
31
|
+
if File.directory?('/usr/local/opt/android-sdk')
|
32
|
+
@out.puts 'Setting /usr/local/opt/android-sdk as ANDROID_HOME...'.magenta
|
33
|
+
ENV['ANDROID_HOME'] = '/usr/local/opt/android-sdk'
|
34
|
+
else
|
35
|
+
raise('**********Android is not installed. Run `brew install android`.**********')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
33
39
|
end
|
data/lib/thrust/config.rb
CHANGED
data/lib/thrust/executor.rb
CHANGED
@@ -1,22 +1,24 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
class Thrust::Executor
|
2
|
+
CommandFailed = Class.new(StandardError)
|
3
|
+
|
4
|
+
def system_or_exit(cmd, output_file = nil)
|
5
|
+
system(cmd, output_file) or raise(CommandFailed, '******** Build failed ********')
|
4
6
|
end
|
5
7
|
|
6
|
-
def
|
8
|
+
def system(cmd, output_file = nil)
|
7
9
|
STDERR.puts "Executing #{cmd}"
|
8
10
|
cmd += " > #{output_file}" if output_file
|
9
11
|
Kernel::system(cmd)
|
10
12
|
end
|
11
13
|
|
12
|
-
def
|
14
|
+
def capture_output_from_system(cmd)
|
13
15
|
captured_output = `#{cmd}`
|
14
|
-
raise '******** Build failed ********' if $?.exitstatus > 0
|
16
|
+
raise(CommandFailed, '******** Build failed ********') if $?.exitstatus > 0
|
15
17
|
|
16
18
|
captured_output
|
17
19
|
end
|
18
20
|
|
19
|
-
def
|
21
|
+
def check_command_for_failure(cmd)
|
20
22
|
STDERR.puts "Executing #{cmd} and checking for FAILURE"
|
21
23
|
result = %x[#{cmd} 2>&1]
|
22
24
|
STDERR.puts "Results:"
|
data/lib/thrust/git.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'colorize'
|
2
2
|
|
3
3
|
class Thrust::Git
|
4
|
-
def initialize(out)
|
4
|
+
def initialize(thrust_executor, out)
|
5
|
+
@thrust_executor = thrust_executor
|
5
6
|
@out = out
|
6
7
|
end
|
7
8
|
|
@@ -10,20 +11,20 @@ class Thrust::Git
|
|
10
11
|
@out.puts 'WARNING NOT CHECKING FOR CLEAN WORKING DIRECTORY'.red
|
11
12
|
else
|
12
13
|
@out.puts 'Checking for clean working tree...'
|
13
|
-
|
14
|
+
@thrust_executor.system_or_exit 'git diff-index --quiet HEAD'
|
14
15
|
end
|
15
16
|
end
|
16
17
|
|
17
18
|
def current_commit
|
18
|
-
|
19
|
+
@thrust_executor.capture_output_from_system('git log --format=format:%h -1').strip
|
19
20
|
end
|
20
21
|
|
21
22
|
def reset
|
22
|
-
|
23
|
+
@thrust_executor.system_or_exit('git reset --hard')
|
23
24
|
end
|
24
25
|
|
25
26
|
def checkout_file(filename)
|
26
|
-
|
27
|
+
@thrust_executor.system_or_exit("git checkout #{filename}")
|
27
28
|
end
|
28
29
|
|
29
30
|
def commit_summary_for_last_deploy(deployment_target)
|
@@ -36,13 +37,13 @@ class Thrust::Git
|
|
36
37
|
end
|
37
38
|
|
38
39
|
def generate_notes_for_deployment(deployment_target)
|
39
|
-
sha_of_latest_commit =
|
40
|
+
sha_of_latest_commit = @thrust_executor.capture_output_from_system('git rev-parse HEAD').strip
|
40
41
|
sha_of_latest_deployed_commit = latest_deployed_commit(deployment_target)
|
41
42
|
|
42
43
|
notes = Tempfile.new('deployment_notes')
|
43
44
|
|
44
45
|
if sha_of_latest_deployed_commit
|
45
|
-
|
46
|
+
@thrust_executor.system_or_exit("git log --oneline #{sha_of_latest_deployed_commit}...#{sha_of_latest_commit}", notes.path)
|
46
47
|
else
|
47
48
|
notes.puts(summary_for_commit(sha_of_latest_commit))
|
48
49
|
notes.close
|
@@ -54,11 +55,11 @@ class Thrust::Git
|
|
54
55
|
private
|
55
56
|
|
56
57
|
def summary_for_commit(sha)
|
57
|
-
|
58
|
+
@thrust_executor.capture_output_from_system("git log --oneline -n 1 #{sha}")
|
58
59
|
end
|
59
60
|
|
60
61
|
def latest_deployed_commit(deployment_target)
|
61
|
-
list =
|
62
|
+
list = @thrust_executor.capture_output_from_system("autotag list #{deployment_target}")
|
62
63
|
unless list.strip.empty?
|
63
64
|
list.split("\n").last.split(" ").first
|
64
65
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class Thrust::IOS::AgvTool
|
2
|
+
|
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')
|
12
|
+
end
|
13
|
+
end
|
data/lib/thrust/ios/cedar.rb
CHANGED
@@ -1,17 +1,21 @@
|
|
1
1
|
class Thrust::IOS::Cedar
|
2
2
|
|
3
|
-
def
|
3
|
+
def initialize(thrust_executor = Thrust::Executor.new)
|
4
|
+
@thrust_executor = thrust_executor
|
5
|
+
end
|
6
|
+
|
7
|
+
def run(out, build_configuration, target, runtime_sdk, build_sdk, device, build_dir, simulator_binary)
|
4
8
|
if build_sdk == 'macosx'
|
5
9
|
build_path = File.join(build_dir, build_configuration)
|
6
10
|
app_dir = File.join(build_path, target)
|
7
|
-
|
11
|
+
@thrust_executor.check_command_for_failure("DYLD_FRAMEWORK_PATH=#{build_path.inspect} #{app_dir}")
|
8
12
|
else
|
9
13
|
app_executable = File.join(build_dir, "#{build_configuration}-#{build_sdk}", "#{target}.app")
|
10
14
|
|
11
15
|
if simulator_binary =~ /waxim%/
|
12
|
-
|
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}])
|
13
17
|
elsif simulator_binary =~ /ios-sim$/
|
14
|
-
|
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])
|
15
19
|
else
|
16
20
|
out.puts "Unknown binary for running specs: '#{simulator_binary}'"
|
17
21
|
false
|
data/lib/thrust/ios/deploy.rb
CHANGED
@@ -1,17 +1,8 @@
|
|
1
1
|
class Thrust::IOS::Deploy
|
2
|
-
def
|
3
|
-
build_configuration = deployment_config['ios_build_configuration']
|
4
|
-
x_code_tools = Thrust::IOS::XCodeTools.new($stdout, build_configuration, thrust_config.build_dir, thrust_config.app_config['project_name'])
|
5
|
-
git = Thrust::Git.new($stdout)
|
6
|
-
testflight_config = thrust_config.app_config['testflight']
|
7
|
-
testflight = Thrust::Testflight.new($stdout, $stdin, testflight_config['api_token'], testflight_config['team_token'])
|
8
|
-
|
9
|
-
new($stdout, x_code_tools, git, testflight, thrust_config, deployment_config, deployment_target)
|
10
|
-
end
|
11
|
-
|
12
|
-
def initialize(out, x_code_tools, git, testflight, thrust_config, deployment_config, deployment_target)
|
2
|
+
def initialize(out, x_code_tools, agv_tool, git, testflight, thrust_config, deployment_config, deployment_target)
|
13
3
|
@out = out
|
14
4
|
@x_code_tools = x_code_tools
|
5
|
+
@agv_tool = agv_tool
|
15
6
|
@git = git
|
16
7
|
@testflight = testflight
|
17
8
|
@thrust_config = thrust_config
|
@@ -21,7 +12,7 @@ class Thrust::IOS::Deploy
|
|
21
12
|
|
22
13
|
def run
|
23
14
|
@git.ensure_clean
|
24
|
-
@
|
15
|
+
@agv_tool.change_build_number(@git.current_commit)
|
25
16
|
|
26
17
|
app_name = @thrust_config.app_config['app_name']
|
27
18
|
target = @deployment_config['ios_target'] || app_name
|
@@ -0,0 +1,15 @@
|
|
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'])
|
12
|
+
|
13
|
+
Thrust::IOS::Deploy.new(stdout, x_code_tools, agv_tool, git, testflight, thrust_config, deployment_config, deployment_target)
|
14
|
+
end
|
15
|
+
end
|
@@ -1,33 +1,21 @@
|
|
1
1
|
class Thrust::IOS::XCodeTools
|
2
2
|
ProvisioningProfileNotFound = Class.new(StandardError)
|
3
3
|
|
4
|
-
def
|
5
|
-
|
6
|
-
match = /Build Configurations:(.+?)\n\n/m.match(output)
|
7
|
-
if match
|
8
|
-
match[1].strip.split("\n").map { |line| line.strip }
|
9
|
-
else
|
10
|
-
[]
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def initialize(out, build_configuration, build_directory, project_name)
|
4
|
+
def initialize(thrust_executor, out, build_configuration, build_directory, options = {})
|
5
|
+
@thrust_executor = thrust_executor
|
15
6
|
@out = out
|
16
|
-
@git = Thrust::Git.new(out)
|
7
|
+
@git = Thrust::Git.new(@thrust_executor, @out)
|
17
8
|
@build_configuration = build_configuration
|
18
9
|
@build_directory = build_directory
|
19
|
-
@project_name = project_name
|
20
|
-
|
21
|
-
|
22
|
-
def change_build_number(build_number)
|
23
|
-
Thrust::Executor.system_or_exit "agvtool new-version -all '#{build_number}'"
|
24
|
-
@git.checkout_file('*.xcodeproj')
|
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?
|
25
13
|
end
|
26
14
|
|
27
15
|
def cleanly_create_ipa(target, app_name, signing_identity, provision_search_query = nil)
|
28
16
|
clean_build
|
29
17
|
kill_simulator
|
30
|
-
|
18
|
+
build_scheme_or_target(target, 'iphoneos')
|
31
19
|
create_ipa(app_name, signing_identity, provision_search_query)
|
32
20
|
end
|
33
21
|
|
@@ -37,27 +25,21 @@ class Thrust::IOS::XCodeTools
|
|
37
25
|
|
38
26
|
def clean_build
|
39
27
|
@out.puts 'Cleaning...'
|
40
|
-
|
41
|
-
FileUtils.rm_rf(build_configuration_directory)
|
28
|
+
FileUtils.rm_rf(@build_directory)
|
42
29
|
end
|
43
30
|
|
44
|
-
def
|
45
|
-
|
46
|
-
|
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)
|
47
34
|
end
|
48
35
|
|
49
36
|
private
|
50
37
|
|
51
|
-
def build_target(target, build_sdk)
|
52
|
-
@out.puts "Building..."
|
53
|
-
run_xcode('build', build_sdk, target)
|
54
|
-
end
|
55
|
-
|
56
38
|
def kill_simulator
|
57
39
|
@out.puts('Killing simulator...')
|
58
|
-
|
59
|
-
|
60
|
-
|
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"]
|
61
43
|
end
|
62
44
|
|
63
45
|
def provision_path(provision_search_query)
|
@@ -79,30 +61,37 @@ class Thrust::IOS::XCodeTools
|
|
79
61
|
"--sign '#{signing_identity}'",
|
80
62
|
"--embed '#{provision_path(provision_search_query)}'"
|
81
63
|
].join(' ')
|
82
|
-
|
64
|
+
@thrust_executor.system_or_exit(cmd)
|
83
65
|
ipa_filename
|
84
66
|
end
|
85
67
|
|
86
|
-
|
87
|
-
|
88
|
-
target_flag =
|
89
|
-
sdk_flag = sdk ? "-sdk #{sdk}" :
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
)
|
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
|
106
95
|
end
|
107
96
|
|
108
97
|
def output_file(target)
|
@@ -114,4 +103,8 @@ class Thrust::IOS::XCodeTools
|
|
114
103
|
|
115
104
|
File.join(output_dir, "#{target}.output").tap { |file| @out.puts "Output: #{file}" }
|
116
105
|
end
|
106
|
+
|
107
|
+
def project_or_workspace_flag
|
108
|
+
@workspace_name ? "-workspace #{@workspace_name}.xcworkspace" : "-project #{@project_name}.xcodeproj"
|
109
|
+
end
|
117
110
|
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class Thrust::IOS::XCodeToolsProvider
|
2
|
+
|
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)
|
9
|
+
end
|
10
|
+
end
|
data/lib/thrust/tasks.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
load File.expand_path("../../tasks/cedar.rake", __FILE__) unless File.exists?('AndroidManifest.xml')
|
2
|
+
load File.expand_path("../../tasks/testflight.rake", __FILE__)
|
3
|
+
load File.expand_path("../../tasks/version.rake", __FILE__)
|
data/lib/thrust/testflight.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
class Thrust::Testflight
|
2
|
-
def initialize(out, input, api_token, team_token)
|
2
|
+
def initialize(thrust_executor, out, input, api_token, team_token)
|
3
|
+
@thrust_executor = thrust_executor
|
3
4
|
@out = out
|
4
5
|
@in = input
|
5
|
-
@git = Thrust::Git.new(@out)
|
6
|
+
@git = Thrust::Git.new(@thrust_executor, @out)
|
6
7
|
@api_token = api_token
|
7
8
|
@team_token = team_token
|
8
9
|
end
|
@@ -11,7 +12,7 @@ class Thrust::Testflight
|
|
11
12
|
if dsym_path
|
12
13
|
@out.puts 'Zipping dSYM...'
|
13
14
|
zipped_dsym_path = "#{dsym_path}.zip"
|
14
|
-
|
15
|
+
@thrust_executor.system_or_exit "zip -r -T -y '#{zipped_dsym_path}' '#{dsym_path}'"
|
15
16
|
@out.puts 'Done!'
|
16
17
|
end
|
17
18
|
|
@@ -22,7 +23,7 @@ class Thrust::Testflight
|
|
22
23
|
end
|
23
24
|
|
24
25
|
|
25
|
-
|
26
|
+
@thrust_executor.system_or_exit [
|
26
27
|
'curl http://testflightapp.com/api/builds.json',
|
27
28
|
"-F file=@#{package_file}",
|
28
29
|
("-F dsym=@#{zipped_dsym_path}" if dsym_path),
|
data/lib/thrust.rb
CHANGED
@@ -9,8 +9,12 @@ require 'thrust/testflight'
|
|
9
9
|
require 'thrust/user_prompt'
|
10
10
|
|
11
11
|
require 'thrust/android/deploy'
|
12
|
+
require 'thrust/android/deploy_provider'
|
12
13
|
require 'thrust/android/tools'
|
13
14
|
|
15
|
+
require 'thrust/ios/agv_tool'
|
14
16
|
require 'thrust/ios/cedar'
|
15
17
|
require 'thrust/ios/deploy'
|
18
|
+
require 'thrust/ios/deploy_provider'
|
16
19
|
require 'thrust/ios/x_code_tools'
|
20
|
+
require 'thrust/ios/x_code_tools_provider'
|
metadata
CHANGED
@@ -1,25 +1,26 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thrust
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
8
|
-
-
|
9
|
-
-
|
7
|
+
- Aaron Levine
|
8
|
+
- Aaron VonderHaar
|
9
|
+
- Andrew Bruce
|
10
10
|
- Andrew Kitchen
|
11
|
-
- Tyler Schultz
|
12
|
-
- Wiley Kestner
|
13
11
|
- Brandon Liu
|
12
|
+
- Can Berk Güder
|
13
|
+
- Eugenia Dellapenna
|
14
14
|
- Jeff Hui
|
15
|
+
- Johnathon Britz
|
16
|
+
- Jonathan Barnes
|
17
|
+
- Michael McCormick
|
18
|
+
- Molly Trombley-McCann
|
15
19
|
- Philip Kuryloski
|
16
|
-
- Andrew Bruce
|
17
|
-
- Aaron Levine
|
18
|
-
- Eugenia Dellapenna
|
19
|
-
- Aaron VonderHaar
|
20
|
-
- Sheel Choksi
|
21
20
|
- Rachel Bobbins
|
22
|
-
-
|
21
|
+
- Sheel Choksi
|
22
|
+
- Tyler Schultz
|
23
|
+
- Wiley Kestner
|
23
24
|
autorequire:
|
24
25
|
bindir: bin
|
25
26
|
cert_chain: []
|
@@ -119,18 +120,24 @@ extensions: []
|
|
119
120
|
extra_rdoc_files: []
|
120
121
|
files:
|
121
122
|
- bin/thrust
|
122
|
-
- lib/config/
|
123
|
+
- lib/config/android_example.yml
|
124
|
+
- lib/config/ios_example.yml
|
123
125
|
- lib/tasks/cedar.rake
|
124
126
|
- lib/tasks/testflight.rake
|
127
|
+
- lib/tasks/version.rake
|
125
128
|
- lib/thrust.rb
|
126
129
|
- lib/thrust/android/deploy.rb
|
130
|
+
- lib/thrust/android/deploy_provider.rb
|
127
131
|
- lib/thrust/android/tools.rb
|
128
132
|
- lib/thrust/config.rb
|
129
133
|
- lib/thrust/executor.rb
|
130
134
|
- lib/thrust/git.rb
|
135
|
+
- lib/thrust/ios/agv_tool.rb
|
131
136
|
- lib/thrust/ios/cedar.rb
|
132
137
|
- lib/thrust/ios/deploy.rb
|
138
|
+
- lib/thrust/ios/deploy_provider.rb
|
133
139
|
- lib/thrust/ios/x_code_tools.rb
|
140
|
+
- lib/thrust/ios/x_code_tools_provider.rb
|
134
141
|
- lib/thrust/tasks.rb
|
135
142
|
- lib/thrust/testflight.rb
|
136
143
|
- lib/thrust/user_prompt.rb
|
@@ -154,7 +161,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
154
161
|
version: '0'
|
155
162
|
requirements: []
|
156
163
|
rubyforge_project:
|
157
|
-
rubygems_version: 2.2.
|
164
|
+
rubygems_version: 2.2.2
|
158
165
|
signing_key:
|
159
166
|
specification_version: 4
|
160
167
|
summary: Thrust is a collection of rake tasks for iOS/Android development and deployment
|
data/lib/config/example.yml
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
thrust_version: 0.2
|
2
|
-
project_name: My Great Project
|
3
|
-
app_name: My Great App
|
4
|
-
ios_distribution_certificate: 'Name of Distribution Signing Certificate'
|
5
|
-
ios_sim_binary: 'ios-sim' # or wax-sim. iOS only.
|
6
|
-
|
7
|
-
testflight:
|
8
|
-
api_token: 'testflight api token'
|
9
|
-
team_token: 'testflight team token'
|
10
|
-
|
11
|
-
deployment_targets:
|
12
|
-
staging:
|
13
|
-
distribution_list: Developers
|
14
|
-
notify: true
|
15
|
-
note_generation_method: autotag # If you set this value, it will auto-generate the deploy notes from the commit history. Optional.
|
16
|
-
ios_target: MyGreatAppTarget # Name of the build target. Optional, defaults to app name. iOS only.
|
17
|
-
ios_build_configuration: Release # iOS only
|
18
|
-
ios_provisioning_search_query: 'query to find Provisioning Profile' # iOS only. Optional.
|
19
|
-
|
20
|
-
demo:
|
21
|
-
distribution_list: Beta Testers
|
22
|
-
notify: true
|
23
|
-
|
24
|
-
ios_spec_targets:
|
25
|
-
specs:
|
26
|
-
target: UISpecs # name of the build target
|
27
|
-
build_configuration: Debug # name of the build configuration
|
28
|
-
build_sdk: 6.1 # SDK used to build the target. Optional, defaults to iphonesimulator.
|
29
|
-
runtime_sdk: 7.0 # SDK used to run the target. Not optional.
|
30
|
-
device: ipad # Device to run the specs on. Optional, defaults to iPhone.
|
31
|
-
|
32
|
-
integration:
|
33
|
-
target: IntegrationSpecs
|
34
|
-
build_configuration: Release
|
35
|
-
build_sdk: macosx
|
36
|
-
runtime_sdk: macosx
|