ios_ci 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/ios_ci +4 -0
- data/lib/commands/base_command.rb +44 -0
- data/lib/commands/build_app.rb +36 -0
- data/lib/commands/download_calabash.rb +24 -0
- data/lib/commands/test_calabash.rb +24 -0
- data/lib/commands/test_cedar.rb +31 -0
- data/lib/extra/print_file.rb +13 -0
- data/lib/factories/command_factory.rb +43 -0
- data/lib/ios_ci.rb +34 -0
- data/lib/launcher/launcher.rb +47 -0
- data/lib/model/params.rb +128 -0
- data/lib/usage.txt +32 -0
- metadata +58 -0
data/bin/ios_ci
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require "model/params.rb"
|
2
|
+
|
3
|
+
class BaseCommand
|
4
|
+
|
5
|
+
# public methods
|
6
|
+
public
|
7
|
+
|
8
|
+
def initialize(params)
|
9
|
+
@params = params
|
10
|
+
end
|
11
|
+
|
12
|
+
def all_commands
|
13
|
+
[before_command, main_command, after_command].compact
|
14
|
+
end
|
15
|
+
|
16
|
+
def empty?
|
17
|
+
all_commands.empty?
|
18
|
+
end
|
19
|
+
|
20
|
+
def log_file
|
21
|
+
@params.log_file
|
22
|
+
end
|
23
|
+
|
24
|
+
# override in subclasses
|
25
|
+
def before_command
|
26
|
+
raise "Invoking of abstract method 'before_command' of 'BaseCommand class'"
|
27
|
+
end
|
28
|
+
|
29
|
+
def main_command
|
30
|
+
raise "Invoking of abstract method 'main_command' of 'BaseCommand class'"
|
31
|
+
end
|
32
|
+
|
33
|
+
def after_command
|
34
|
+
raise "Invoking of abstract method 'after_command' of 'BaseCommand class'"
|
35
|
+
end
|
36
|
+
|
37
|
+
# private methods
|
38
|
+
private
|
39
|
+
|
40
|
+
def app_path
|
41
|
+
"#{@params.source_root}/#{@params.build_path}/#{@params.configuration}-#{@params.architecture}/#{@params.app_name}.app"
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "commands/base_command.rb"
|
2
|
+
|
3
|
+
class BuildApp < BaseCommand
|
4
|
+
|
5
|
+
# overriding base class methods
|
6
|
+
def before_command
|
7
|
+
"cd #{@params.source_root} && pod install" if cocoapods?
|
8
|
+
end
|
9
|
+
|
10
|
+
def main_command
|
11
|
+
"cd #{@params.source_root} && xcodebuild #{build_args} -sdk #{@params.architecture} -configuration #{@params.configuration} clean build CONFIGURATION_BUILD_DIR=#{clean_dir}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def after_command
|
15
|
+
end
|
16
|
+
|
17
|
+
def log_file
|
18
|
+
end
|
19
|
+
|
20
|
+
# private methods
|
21
|
+
private
|
22
|
+
|
23
|
+
def build_args
|
24
|
+
@params.target? ? "-target '#{@params.target}'" :
|
25
|
+
"-scheme '#{@params.scheme}' -workspace '#{@params.workspace}'"
|
26
|
+
end
|
27
|
+
|
28
|
+
def clean_dir
|
29
|
+
"#{@params.source_root}/#{@params.build_path}/#{@params.configuration}-#{@params.architecture}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def cocoapods?
|
33
|
+
File.exist?("#{@params.source_root}/Podfile")
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "commands/base_command.rb"
|
2
|
+
|
3
|
+
class DownloadCalabash < BaseCommand
|
4
|
+
|
5
|
+
# overrides from base class
|
6
|
+
def before_command
|
7
|
+
"cd #{@params.source_root} && rm -rf calabash.framework" if framework?
|
8
|
+
end
|
9
|
+
|
10
|
+
def main_command
|
11
|
+
"cd #{@params.source_root} && calabash-ios download"
|
12
|
+
end
|
13
|
+
|
14
|
+
def after_command
|
15
|
+
end
|
16
|
+
|
17
|
+
# private
|
18
|
+
private
|
19
|
+
|
20
|
+
def framework?
|
21
|
+
File.directory?("#{@params.source_root}/calabash.framework")
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "commands/base_command.rb"
|
2
|
+
|
3
|
+
class TestCalabash < BaseCommand
|
4
|
+
|
5
|
+
# overrides from base class
|
6
|
+
def before_command
|
7
|
+
end
|
8
|
+
|
9
|
+
def main_command
|
10
|
+
"cd #{@params.source_root} && APP_BUNDLE_PATH='#{app_path}' #{test_command} -o #{log_file} --require features"
|
11
|
+
end
|
12
|
+
|
13
|
+
def after_command
|
14
|
+
"! grep -q \"failed\" #{log_file} && grep -q \"passed\" #{log_file}"
|
15
|
+
end
|
16
|
+
|
17
|
+
# private methods
|
18
|
+
private
|
19
|
+
|
20
|
+
def test_command
|
21
|
+
"cucumber"
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require "commands/base_command.rb"
|
2
|
+
|
3
|
+
SIM_PATH = "/usr/local/bin/ios-sim"
|
4
|
+
|
5
|
+
class TestCedar < BaseCommand
|
6
|
+
|
7
|
+
# overrides from base class
|
8
|
+
def before_command
|
9
|
+
end
|
10
|
+
|
11
|
+
def main_command
|
12
|
+
"#{test_command} > #{self.log_file} 2>&1"
|
13
|
+
end
|
14
|
+
|
15
|
+
def after_command
|
16
|
+
"grep -q \"0 failures\" #{self.log_file}"
|
17
|
+
end
|
18
|
+
|
19
|
+
# private methods
|
20
|
+
private
|
21
|
+
|
22
|
+
def test_command
|
23
|
+
command = "#{SIM_PATH} launch #{app_path} --setenv CEDAR_HEADLESS_SPECS=1\
|
24
|
+
--setenv CEDAR_REPORTER_CLASS=CDRColorizedReporter,CDRJUnitXMLReporter\
|
25
|
+
--setenv CEDAR_JUNIT_XML_FILE=#{@params.source_root}/test-reports/cedar.xml"
|
26
|
+
command += " --family #{@params.family} " unless @params.family.nil?
|
27
|
+
command += " --sdk #{@params.sdk} " unless @params.sdk.nil?
|
28
|
+
command
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require "model/params.rb"
|
2
|
+
require "commands/build_app.rb"
|
3
|
+
require "commands/test_cedar.rb"
|
4
|
+
require "commands/test_calabash.rb"
|
5
|
+
require "commands/download_calabash.rb"
|
6
|
+
|
7
|
+
class CommandFactory
|
8
|
+
# instance variables
|
9
|
+
@params = nil
|
10
|
+
|
11
|
+
# public methods
|
12
|
+
public
|
13
|
+
|
14
|
+
def initialize(params)
|
15
|
+
@params = params
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_commands
|
19
|
+
if @params.action == ACTION_BUILD
|
20
|
+
[get_build]
|
21
|
+
elsif @params.action == ACTION_CEDAR
|
22
|
+
get_cedar
|
23
|
+
elsif @params.action == ACTION_CALABASH
|
24
|
+
get_calabash
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
#private methods
|
29
|
+
private
|
30
|
+
|
31
|
+
def get_build
|
32
|
+
BuildApp.new(@params)
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_cedar
|
36
|
+
[get_build, TestCedar.new(@params)]
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_calabash
|
40
|
+
[DownloadCalabash.new(@params), get_build, TestCalabash.new(@params)]
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
data/lib/ios_ci.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require "model/params.rb"
|
2
|
+
require "launcher/launcher.rb"
|
3
|
+
require "factories/command_factory.rb"
|
4
|
+
|
5
|
+
class IOSCI
|
6
|
+
# instance variables
|
7
|
+
@launcher = nil
|
8
|
+
@params = nil
|
9
|
+
|
10
|
+
# public methods
|
11
|
+
public
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@launcher = Launcher.new
|
15
|
+
@params = Params.new
|
16
|
+
factory = CommandFactory.new(@params)
|
17
|
+
run(factory.get_commands)
|
18
|
+
end
|
19
|
+
|
20
|
+
# private methods
|
21
|
+
private
|
22
|
+
|
23
|
+
def run(commands)
|
24
|
+
@launcher.run(commands)
|
25
|
+
if @launcher.success?
|
26
|
+
puts "#{@params.action} succeeded"
|
27
|
+
exit 0
|
28
|
+
else
|
29
|
+
puts "#{@params.action} failed"
|
30
|
+
exit 1
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require "commands/base_command.rb"
|
2
|
+
require "extra/print_file.rb"
|
3
|
+
|
4
|
+
class Launcher
|
5
|
+
|
6
|
+
# instance variables
|
7
|
+
@result = nil
|
8
|
+
|
9
|
+
# public methods
|
10
|
+
public
|
11
|
+
|
12
|
+
def run(commands)
|
13
|
+
commands.map { | command |
|
14
|
+
next if command.empty?
|
15
|
+
@result = run_command(command)
|
16
|
+
break unless @result
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def success?
|
21
|
+
@result
|
22
|
+
end
|
23
|
+
|
24
|
+
# private
|
25
|
+
private
|
26
|
+
|
27
|
+
def run_command(command)
|
28
|
+
close_simulator
|
29
|
+
invoke_result = invoke(command.all_commands)
|
30
|
+
print_file(command.log_file) unless command.log_file.nil?
|
31
|
+
return invoke_result
|
32
|
+
end
|
33
|
+
|
34
|
+
def invoke(commands)
|
35
|
+
commands.map { | cmd |
|
36
|
+
puts ">>>>> Running commands <<<<<\n#{cmd}\n"
|
37
|
+
system(cmd)
|
38
|
+
}.last
|
39
|
+
end
|
40
|
+
|
41
|
+
def close_simulator
|
42
|
+
puts "Closing iPhone Simulator"
|
43
|
+
%x[ killall "iPhone Simulator" ]
|
44
|
+
puts ""
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
data/lib/model/params.rb
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
require "getoptlong"
|
2
|
+
require "extra/print_file.rb"
|
3
|
+
|
4
|
+
ACTION_BUILD = "build"
|
5
|
+
ACTION_CEDAR = "cedar"
|
6
|
+
ACTION_CALABASH = "calabash"
|
7
|
+
|
8
|
+
class Params
|
9
|
+
# attributes
|
10
|
+
attr_reader :action, :source_root, :target, :scheme, :workspace, :configuration,
|
11
|
+
:architecture, :sdk, :family, :build_path, :log_file
|
12
|
+
|
13
|
+
# public methods
|
14
|
+
public
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
set_defaults
|
18
|
+
begin
|
19
|
+
parse_action
|
20
|
+
getoptlong = get_options
|
21
|
+
parse_options(getoptlong)
|
22
|
+
check_options
|
23
|
+
set_log_file
|
24
|
+
|
25
|
+
rescue StandardError=>error
|
26
|
+
puts "\n#{error}\n#{usage}"
|
27
|
+
exit 1
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def app_name
|
32
|
+
target? ? @target : @scheme
|
33
|
+
end
|
34
|
+
|
35
|
+
def workspace?
|
36
|
+
!@scheme.nil? && !@workspace.nil?
|
37
|
+
end
|
38
|
+
|
39
|
+
def target?
|
40
|
+
!@target.nil?
|
41
|
+
end
|
42
|
+
|
43
|
+
# private methods
|
44
|
+
private
|
45
|
+
|
46
|
+
def set_defaults
|
47
|
+
@architecture = "iphonesimulator"
|
48
|
+
@configuration = "Release"
|
49
|
+
@build_path = "build"
|
50
|
+
end
|
51
|
+
|
52
|
+
def parse_action
|
53
|
+
@action = ARGV.shift
|
54
|
+
raise unless check_action
|
55
|
+
end
|
56
|
+
|
57
|
+
def get_options
|
58
|
+
GetoptLong.new(
|
59
|
+
[ '--target', '-t', GetoptLong::OPTIONAL_ARGUMENT ],
|
60
|
+
[ '--scheme', '-h', GetoptLong::OPTIONAL_ARGUMENT ],
|
61
|
+
[ '--workspace', '-w', GetoptLong::OPTIONAL_ARGUMENT ],
|
62
|
+
[ '--source-root', '-r', GetoptLong::OPTIONAL_ARGUMENT ],
|
63
|
+
[ '--arch', '-a' ,GetoptLong::OPTIONAL_ARGUMENT ],
|
64
|
+
[ '--configuration', '-c', GetoptLong::OPTIONAL_ARGUMENT ],
|
65
|
+
[ '--sdk', '-s', GetoptLong::OPTIONAL_ARGUMENT ],
|
66
|
+
[ '--log-file', '-l', GetoptLong::OPTIONAL_ARGUMENT ],
|
67
|
+
[ '--family', '-f' ,GetoptLong::OPTIONAL_ARGUMENT ],
|
68
|
+
[ '--build-path', '-b' ,GetoptLong::OPTIONAL_ARGUMENT ]
|
69
|
+
)
|
70
|
+
end
|
71
|
+
|
72
|
+
def parse_options(getoptlong)
|
73
|
+
getoptlong.each do |opt, arg|
|
74
|
+
case opt
|
75
|
+
when ACTION_BUILD
|
76
|
+
@action = ACTION_BUILD
|
77
|
+
when ACTION_CEDAR
|
78
|
+
@action = ACTION_CEDAR
|
79
|
+
when ACTION_CALABASH
|
80
|
+
@action = ACTION_CALABASH
|
81
|
+
when "--source-root"
|
82
|
+
@source_root = arg
|
83
|
+
when "--target"
|
84
|
+
@target = arg
|
85
|
+
when "--scheme"
|
86
|
+
@scheme = arg
|
87
|
+
when "--workspace"
|
88
|
+
@workspace = arg
|
89
|
+
when "--configuration"
|
90
|
+
@configuration = arg
|
91
|
+
when "--arch"
|
92
|
+
@architecture = arg
|
93
|
+
when "--sdk"
|
94
|
+
@sdk = arg
|
95
|
+
when "--family"
|
96
|
+
@family = arg
|
97
|
+
when "--build-path"
|
98
|
+
@build_path = arg
|
99
|
+
when "--log-file"
|
100
|
+
@log_file = arg
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def check_action
|
106
|
+
@action == ACTION_BUILD || @action == ACTION_CEDAR || @action == ACTION_CALABASH
|
107
|
+
end
|
108
|
+
def check_options
|
109
|
+
if self.action.nil?
|
110
|
+
puts "You must specify action type"
|
111
|
+
raise
|
112
|
+
elsif self.source_root.nil?
|
113
|
+
puts "You must specify source root"
|
114
|
+
raise
|
115
|
+
elsif !self.target? && !self.workspace?
|
116
|
+
puts "You must specify target root or scheme and workspace"
|
117
|
+
raise
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def set_log_file
|
122
|
+
@log_file = "/tmp/#{@action}-#{app_name}-#{Time.now.to_i}.log" if @log_file.nil?
|
123
|
+
end
|
124
|
+
|
125
|
+
def usage
|
126
|
+
print_file("lib/usage.txt")
|
127
|
+
end
|
128
|
+
end
|
data/lib/usage.txt
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
Usage:
|
2
|
+
ios_ci Action ProjectOptions
|
3
|
+
|
4
|
+
=== Action
|
5
|
+
|
6
|
+
build :: build project
|
7
|
+
cedar :: build and run cedar-tests
|
8
|
+
calabash :: build and run calabash-tests
|
9
|
+
|
10
|
+
|
11
|
+
=== Project Options
|
12
|
+
|
13
|
+
--source-root :: path to project source code directory
|
14
|
+
(required)
|
15
|
+
--target :: project target name
|
16
|
+
(required if no scheme and workspace specified)
|
17
|
+
--scheme :: project build scheme
|
18
|
+
(required if no target specified)
|
19
|
+
--workspace :: project worspace
|
20
|
+
(required id no target specified)
|
21
|
+
--configuration :: Release, Debug
|
22
|
+
(optional, default: Release)
|
23
|
+
--architecture :: iphoneos, iphonesimulator
|
24
|
+
(optional, default: iphonesimulator)
|
25
|
+
--sdk :: version
|
26
|
+
(optional, default: latest)
|
27
|
+
--family :: iphone, ipad
|
28
|
+
(optional, default: iphone)
|
29
|
+
--build-path :: relative path from source root to app build
|
30
|
+
(optional, default: $source-root/build/)
|
31
|
+
--log-file :: path to log file
|
32
|
+
(optional, default: /tmp/$action-$target-$timestamp.log)
|
metadata
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ios_ci
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Alexey Belkevich
|
9
|
+
- Alexey Denisov
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2012-11-28 00:00:00.000000000 Z
|
14
|
+
dependencies: []
|
15
|
+
description: Script for iOS continuous integration
|
16
|
+
email: belkevich@okolodev.org
|
17
|
+
executables:
|
18
|
+
- ios_ci
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- lib/ios_ci.rb
|
23
|
+
- lib/usage.txt
|
24
|
+
- lib/commands/base_command.rb
|
25
|
+
- lib/commands/build_app.rb
|
26
|
+
- lib/commands/test_calabash.rb
|
27
|
+
- lib/commands/download_calabash.rb
|
28
|
+
- lib/commands/test_cedar.rb
|
29
|
+
- lib/factories/command_factory.rb
|
30
|
+
- lib/launcher/launcher.rb
|
31
|
+
- lib/model/params.rb
|
32
|
+
- lib/extra/print_file.rb
|
33
|
+
- bin/ios_ci
|
34
|
+
homepage: https://github.com/okolodev/ios_ci
|
35
|
+
licenses: []
|
36
|
+
post_install_message:
|
37
|
+
rdoc_options: []
|
38
|
+
require_paths:
|
39
|
+
- lib
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ! '>='
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
requirements: []
|
53
|
+
rubyforge_project:
|
54
|
+
rubygems_version: 1.8.24
|
55
|
+
signing_key:
|
56
|
+
specification_version: 3
|
57
|
+
summary: iOS continuous integration
|
58
|
+
test_files: []
|