xcodebuild-rb 0.1.0 → 0.2.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/CHANGES.md +11 -0
- data/README.md +4 -2
- data/bin/rbxcb +7 -1
- data/lib/xcode_build.rb +8 -5
- data/lib/xcode_build/build_action.rb +10 -2
- data/lib/xcode_build/build_step.rb +8 -0
- data/lib/xcode_build/formatters.rb +1 -1
- data/lib/xcode_build/formatters/progress_formatter.rb +14 -10
- data/lib/xcode_build/output_translator.rb +4 -3
- data/lib/xcode_build/reporter.rb +10 -2
- data/lib/xcode_build/reporting/build_reporting.rb +43 -14
- data/lib/xcode_build/reporting/clean_reporting.rb +5 -1
- data/lib/xcode_build/tasks.rb +6 -0
- data/lib/xcode_build/tasks/build_task.rb +66 -16
- data/lib/xcode_build/translations.rb +2 -2
- data/lib/xcode_build/translations/building.rb +30 -18
- data/lib/xcode_build/translations/cleaning.rb +11 -11
- data/lib/xcodebuild.rb +1 -1
- data/spec/build_task_spec.rb +147 -39
- data/spec/output_translator_spec.rb +1 -1
- data/spec/reporting/build_reporting_spec.rb +61 -8
- data/spec/translations/building_translations_spec.rb +48 -32
- data/spec/translations/cleaning_translations_spec.rb +18 -18
- metadata +22 -19
data/CHANGES.md
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
# xcodebuild-rb changes
|
2
|
+
|
3
|
+
## 0.2.0
|
4
|
+
* Added archive task
|
5
|
+
* Support Ruby 1.8.7
|
6
|
+
* Added after_(build|clean|archive) hooks for rake tasks
|
7
|
+
* Support capturing environment variables when a Run Script Phase with 'Show Environment Variables' is added.
|
8
|
+
* Ensure rake tasks exit with an appropriate exit code when the builds fail.
|
9
|
+
|
10
|
+
## 0.1.0
|
11
|
+
* Initial release.
|
data/README.md
CHANGED
@@ -15,7 +15,7 @@ After installing the gem, you need to create a `Rakefile` in the root of your pr
|
|
15
15
|
A simple Rakefile will look like this:
|
16
16
|
|
17
17
|
require 'rubygems'
|
18
|
-
require 'xcodebuild
|
18
|
+
require 'xcodebuild'
|
19
19
|
|
20
20
|
XcodeBuild::Tasks::BuildTask.new
|
21
21
|
|
@@ -35,6 +35,8 @@ When you run `rake xcode:build`, `xcodebuild` will be invoked without any argume
|
|
35
35
|
t.configuration = "Release"
|
36
36
|
end
|
37
37
|
|
38
|
+
_Note that in order to be able to use the `xcode:archive` task, a scheme **has** to be provided_
|
39
|
+
|
38
40
|
When you run the rake tasks provided, the default behaviour is to simply output the exact output from `xcodebuild`. However, `xcodebuild-rb` can go one better and allow you to configure custom formatters that change the way the build output is displayed. Some formatters are built-in, or you can write your own.
|
39
41
|
|
40
42
|
For instance, we could use the "progress" formatter that ships with `xcodebuild-rb`. Anybody who is used to the output of Ruby's Test::Unit library or RSpec library will be familiar with this.
|
@@ -56,4 +58,4 @@ Now when you run your build, your output will look something like this:
|
|
56
58
|
|
57
59
|
## License
|
58
60
|
|
59
|
-
This library is licensed under the [MIT license](http://en.wikipedia.org/wiki/MIT_License).
|
61
|
+
This library is licensed under the [MIT license](http://en.wikipedia.org/wiki/MIT_License).
|
data/bin/rbxcb
CHANGED
data/lib/xcode_build.rb
CHANGED
@@ -13,14 +13,17 @@ module XcodeBuild
|
|
13
13
|
rescue EOFError
|
14
14
|
end
|
15
15
|
end
|
16
|
+
|
17
|
+
$?.exitstatus
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
require 'xcode_build/build_action'
|
22
|
+
require 'xcode_build/build_step'
|
23
|
+
require 'xcode_build/output_translator'
|
24
|
+
require 'xcode_build/reporter'
|
25
|
+
require 'xcode_build/formatters'
|
26
|
+
require 'xcode_build/tasks'
|
24
27
|
|
25
28
|
# configure the default translations for general use
|
26
29
|
XcodeBuild::OutputTranslator.use_translation(:building)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'state_machine'
|
2
2
|
|
3
|
-
|
3
|
+
require "xcode_build/build_step"
|
4
4
|
|
5
5
|
module XcodeBuild
|
6
6
|
class BuildAction
|
@@ -47,11 +47,19 @@ module XcodeBuild
|
|
47
47
|
def finished?
|
48
48
|
successful? || failed?
|
49
49
|
end
|
50
|
+
|
51
|
+
def has_errors?
|
52
|
+
failed_steps.any?
|
53
|
+
end
|
50
54
|
|
51
55
|
def duration
|
52
56
|
return nil unless finished?
|
53
57
|
@finished_at - @started_at
|
54
58
|
end
|
59
|
+
|
60
|
+
def label
|
61
|
+
@label.downcase.capitalize
|
62
|
+
end
|
55
63
|
|
56
64
|
def project_name
|
57
65
|
@metadata[:project]
|
@@ -69,4 +77,4 @@ module XcodeBuild
|
|
69
77
|
@metadata[:default]
|
70
78
|
end
|
71
79
|
end
|
72
|
-
end
|
80
|
+
end
|
@@ -11,6 +11,7 @@ module XcodeBuild
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def add_error(params)
|
14
|
+
@failed = true
|
14
15
|
@errors << Error.new(params)
|
15
16
|
end
|
16
17
|
|
@@ -42,6 +43,13 @@ module XcodeBuild
|
|
42
43
|
private
|
43
44
|
|
44
45
|
class Error < OpenStruct
|
46
|
+
def error_detail
|
47
|
+
if self.file
|
48
|
+
"in #{err.file}:#{err.line.to_s}"
|
49
|
+
elsif self.command
|
50
|
+
"#{self.command} failed with exit code #{self.exit_code}"
|
51
|
+
end
|
52
|
+
end
|
45
53
|
end
|
46
54
|
end
|
47
55
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# encoding: UTF-8
|
2
|
-
|
2
|
+
require 'xcode_build/utilities/colorize'
|
3
3
|
|
4
4
|
module XcodeBuild
|
5
5
|
module Formatters
|
@@ -19,7 +19,7 @@ module XcodeBuild
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def clean_finished(clean)
|
22
|
-
report_finished(
|
22
|
+
report_finished(clean)
|
23
23
|
end
|
24
24
|
|
25
25
|
def build_started(build)
|
@@ -31,30 +31,34 @@ module XcodeBuild
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def build_finished(build)
|
34
|
-
report_finished(
|
34
|
+
report_finished(build)
|
35
35
|
end
|
36
36
|
|
37
|
-
def report_finished(
|
37
|
+
def report_finished(object)
|
38
38
|
puts
|
39
39
|
puts
|
40
40
|
puts "Finished in #{object.duration} seconds."
|
41
41
|
|
42
42
|
if object.successful?
|
43
|
-
puts green("#{
|
43
|
+
puts green("#{object.label} succeeded.")
|
44
44
|
else
|
45
|
-
puts red("#{
|
45
|
+
puts red("#{object.label} failed.")
|
46
46
|
puts
|
47
|
-
puts "Failed #{
|
47
|
+
puts "Failed #{object.label.downcase} steps:"
|
48
48
|
puts
|
49
49
|
error_counter = 1
|
50
50
|
object.steps_completed.each do |step|
|
51
51
|
next unless step.has_errors?
|
52
|
-
|
52
|
+
|
53
53
|
puts indent("#{error_counter}) #{step.type} #{step.arguments.join(" ")}")
|
54
54
|
|
55
55
|
step.errors.each do |err|
|
56
|
-
|
57
|
-
|
56
|
+
print indent(" #{red(err.message)}")
|
57
|
+
if err.error_detail
|
58
|
+
puts indent(cyan(err.error_detail))
|
59
|
+
else
|
60
|
+
puts
|
61
|
+
end
|
58
62
|
puts
|
59
63
|
end
|
60
64
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# encoding: UTF-8
|
2
|
-
|
2
|
+
require 'xcode_build/translations'
|
3
3
|
|
4
4
|
module XcodeBuild
|
5
5
|
class OutputTranslator
|
@@ -13,7 +13,7 @@ module XcodeBuild
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def <<(line)
|
16
|
-
notify_delegate(:beginning_translation_of_line, args
|
16
|
+
notify_delegate(:beginning_translation_of_line, :args => line)
|
17
17
|
translations.each { |translation| translation.attempt_to_translate(line) }
|
18
18
|
end
|
19
19
|
|
@@ -56,7 +56,8 @@ module XcodeBuild
|
|
56
56
|
private
|
57
57
|
|
58
58
|
module TranslationHelpers
|
59
|
-
def notify_delegate(message, options = {
|
59
|
+
def notify_delegate(message, options = {})
|
60
|
+
options[:args] ||= []
|
60
61
|
if @delegate.respond_to?(message)
|
61
62
|
@delegate.send(message, *options[:args])
|
62
63
|
else
|
data/lib/xcode_build/reporter.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require "xcode_build/reporting/build_reporting"
|
2
|
+
require "xcode_build/reporting/clean_reporting"
|
3
3
|
|
4
4
|
module XcodeBuild
|
5
5
|
class Reporter
|
@@ -11,6 +11,14 @@ module XcodeBuild
|
|
11
11
|
def initialize(delegate = nil)
|
12
12
|
@delegate = delegate
|
13
13
|
end
|
14
|
+
|
15
|
+
def direct_raw_output_to=(stream)
|
16
|
+
@output_stream = stream
|
17
|
+
end
|
18
|
+
|
19
|
+
def beginning_translation_of_line(line)
|
20
|
+
(@output_stream << line) if @output_stream
|
21
|
+
end
|
14
22
|
|
15
23
|
private
|
16
24
|
|
@@ -11,35 +11,48 @@ module XcodeBuild
|
|
11
11
|
|
12
12
|
def build_started(params)
|
13
13
|
@build = Build.new(params)
|
14
|
-
notify :build_started,
|
14
|
+
notify :build_started, build
|
15
15
|
end
|
16
16
|
|
17
17
|
def build_step(params)
|
18
|
-
if
|
19
|
-
notify :build_step_finished,
|
18
|
+
if build.last_step
|
19
|
+
notify :build_step_finished, build.last_step
|
20
20
|
end
|
21
21
|
|
22
|
-
|
22
|
+
build.add_step(params)
|
23
23
|
|
24
|
-
notify :build_step_started,
|
24
|
+
notify :build_step_started, build.last_step
|
25
25
|
end
|
26
26
|
|
27
27
|
def build_error_detected(params)
|
28
|
-
|
28
|
+
build.last_step.add_error(params)
|
29
|
+
end
|
30
|
+
|
31
|
+
def build_env_variable_detected(key, value)
|
32
|
+
build.set_environment_variable(key, value)
|
29
33
|
end
|
30
34
|
|
31
|
-
def build_succeeded
|
32
|
-
|
35
|
+
def build_succeeded(archive_or_build)
|
36
|
+
build.label = archive_or_build
|
37
|
+
|
38
|
+
# for some reason, archive reports a success even if there was an error
|
39
|
+
if build.has_errors?
|
40
|
+
build.failure!
|
41
|
+
else
|
42
|
+
build.success!
|
43
|
+
end
|
44
|
+
|
33
45
|
build_finished
|
34
46
|
end
|
35
47
|
|
36
|
-
def build_failed
|
37
|
-
|
48
|
+
def build_failed(archive_or_build)
|
49
|
+
build.label = archive_or_build
|
50
|
+
build.failure!
|
38
51
|
build_finished
|
39
52
|
end
|
40
53
|
|
41
54
|
def build_step_failed(params)
|
42
|
-
if step =
|
55
|
+
if step = build.step_with_params(params)
|
43
56
|
step.failed = true
|
44
57
|
end
|
45
58
|
end
|
@@ -47,14 +60,30 @@ module XcodeBuild
|
|
47
60
|
private
|
48
61
|
|
49
62
|
def build_finished
|
50
|
-
if
|
51
|
-
notify :build_step_finished,
|
63
|
+
if build.last_step
|
64
|
+
notify :build_step_finished, build.last_step
|
52
65
|
end
|
53
66
|
|
54
|
-
notify :build_finished,
|
67
|
+
notify :build_finished, build
|
55
68
|
end
|
56
69
|
|
57
70
|
class Build < BuildAction
|
71
|
+
attr_reader :environment
|
72
|
+
attr_writer :label
|
73
|
+
|
74
|
+
def initialize(metadata)
|
75
|
+
super(metadata)
|
76
|
+
@environment = {}
|
77
|
+
@label = "Build"
|
78
|
+
end
|
79
|
+
|
80
|
+
def set_environment_variable(key, value)
|
81
|
+
@environment[key] = value
|
82
|
+
end
|
83
|
+
|
84
|
+
def target_build_directory
|
85
|
+
@environment["TARGET_BUILD_DIR"]
|
86
|
+
end
|
58
87
|
end
|
59
88
|
end
|
60
89
|
end
|
@@ -9,7 +9,7 @@ module XcodeBuild
|
|
9
9
|
|
10
10
|
def clean_started(params)
|
11
11
|
@clean = Clean.new(params)
|
12
|
-
notify :clean_started,
|
12
|
+
notify :clean_started, clean
|
13
13
|
end
|
14
14
|
|
15
15
|
def clean_step(params)
|
@@ -53,6 +53,10 @@ module XcodeBuild
|
|
53
53
|
end
|
54
54
|
|
55
55
|
class Clean < BuildAction
|
56
|
+
def initialize(metadata)
|
57
|
+
super(metadata)
|
58
|
+
@label = "Clean"
|
59
|
+
end
|
56
60
|
end
|
57
61
|
end
|
58
62
|
end
|
@@ -3,6 +3,8 @@ require 'rake/tasklib'
|
|
3
3
|
module XcodeBuild
|
4
4
|
module Tasks
|
5
5
|
class BuildTask < ::Rake::TaskLib
|
6
|
+
include Rake::DSL if defined?(Rake::DSL)
|
7
|
+
|
6
8
|
attr_accessor :project_name
|
7
9
|
attr_accessor :target
|
8
10
|
attr_accessor :workspace
|
@@ -14,16 +16,36 @@ module XcodeBuild
|
|
14
16
|
attr_accessor :output_to
|
15
17
|
attr_accessor :formatter
|
16
18
|
attr_accessor :invoke_from_within
|
17
|
-
attr_accessor :
|
19
|
+
attr_accessor :reporter_klass
|
18
20
|
|
19
21
|
def initialize(namespace = :xcode, &block)
|
20
22
|
@namespace = namespace
|
21
23
|
@output_to = STDOUT
|
22
24
|
@invoke_from_within = "."
|
25
|
+
@reporter_klass = XcodeBuild::Reporter
|
26
|
+
@hooks = {}
|
23
27
|
|
24
28
|
yield self if block_given?
|
25
29
|
define
|
26
30
|
end
|
31
|
+
|
32
|
+
def after_build(&block)
|
33
|
+
@hooks[:after_build] = block
|
34
|
+
end
|
35
|
+
|
36
|
+
def after_clean(&block)
|
37
|
+
@hooks[:after_clean] = block
|
38
|
+
end
|
39
|
+
|
40
|
+
def after_archive(&block)
|
41
|
+
@hooks[:after_archive] = block
|
42
|
+
end
|
43
|
+
|
44
|
+
def execute_hook(name, *args)
|
45
|
+
if hook = @hooks[name.to_sym]
|
46
|
+
hook.call(*args)
|
47
|
+
end
|
48
|
+
end
|
27
49
|
|
28
50
|
def run(task)
|
29
51
|
Rake::Task["#{@namespace}:#{task}"].invoke
|
@@ -41,44 +63,72 @@ module XcodeBuild
|
|
41
63
|
opts << "-xcconfig #{xcconfig}" if xcconfig
|
42
64
|
end
|
43
65
|
end
|
66
|
+
|
67
|
+
def reporter
|
68
|
+
@reporter ||= @reporter_klass.new(formatter)
|
69
|
+
end
|
44
70
|
|
45
71
|
private
|
46
72
|
|
47
73
|
def output_buffer
|
48
|
-
|
49
|
-
XcodeBuild::OutputTranslator.new(reporter)
|
50
|
-
elsif formatter
|
51
|
-
default_reporter = XcodeBuild::Reporter.new(formatter)
|
52
|
-
XcodeBuild::OutputTranslator.new(default_reporter)
|
53
|
-
else
|
54
|
-
output_to
|
55
|
-
end
|
74
|
+
@output_buffer ||= XcodeBuild::OutputTranslator.new(reporter)
|
56
75
|
end
|
57
76
|
|
58
77
|
def build_opts_string(*additional_opts)
|
59
|
-
(build_opts + additional_opts).join(" ")
|
78
|
+
(build_opts + additional_opts).compact.join(" ")
|
79
|
+
end
|
80
|
+
|
81
|
+
def xcodebuild(action)
|
82
|
+
reporter.direct_raw_output_to = output_to unless formatter
|
83
|
+
|
84
|
+
status = Dir.chdir(invoke_from_within) do
|
85
|
+
XcodeBuild.run(build_opts_string(action), output_buffer)
|
86
|
+
end
|
87
|
+
|
88
|
+
check_status(status)
|
89
|
+
|
90
|
+
if reporter.build && reporter.build.failed?
|
91
|
+
# sometimes, a build/archive can fail and xcodebuild won't return a non-zero code
|
92
|
+
raise "xcodebuild failed (#{reporter.build.failed_steps.length} steps failed)"
|
93
|
+
end
|
94
|
+
|
95
|
+
case action
|
96
|
+
when :build
|
97
|
+
execute_hook(:after_build, reporter.build)
|
98
|
+
when :archive
|
99
|
+
execute_hook(:after_build, reporter.build)
|
100
|
+
execute_hook(:after_archive, reporter.build)
|
101
|
+
when :clean
|
102
|
+
execute_hook(:after_clean, reporter.clean)
|
103
|
+
end
|
60
104
|
end
|
61
105
|
|
62
106
|
def define
|
63
107
|
namespace(@namespace) do
|
108
|
+
desc "Creates an archive build of the specified target(s)."
|
109
|
+
task :archive do
|
110
|
+
raise "You need to specify a `scheme' in order to be able to create an archive build!" unless scheme
|
111
|
+
xcodebuild :archive
|
112
|
+
end
|
113
|
+
|
64
114
|
desc "Builds the specified target(s)."
|
65
115
|
task :build do
|
66
|
-
|
67
|
-
XcodeBuild.run(build_opts_string, output_buffer)
|
68
|
-
end
|
116
|
+
xcodebuild :build
|
69
117
|
end
|
70
118
|
|
71
119
|
desc "Cleans the build using the same build settings."
|
72
120
|
task :clean do
|
73
|
-
|
74
|
-
XcodeBuild.run(build_opts_string("clean"), output_buffer)
|
75
|
-
end
|
121
|
+
xcodebuild :clean
|
76
122
|
end
|
77
123
|
|
78
124
|
desc "Builds the specified target(s) from a clean slate."
|
79
125
|
task :cleanbuild => [:clean, :build]
|
80
126
|
end
|
81
127
|
end
|
128
|
+
|
129
|
+
def check_status(status)
|
130
|
+
raise "xcodebuild failed (exited with status: #{status})" unless status == 0
|
131
|
+
end
|
82
132
|
end
|
83
133
|
end
|
84
134
|
end
|