hive-runner-ios 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +19 -0
- data/lib/hive/controller/ios.rb +171 -0
- data/lib/hive/device/ios.rb +12 -0
- data/lib/hive/messages/ios_job.rb +11 -0
- data/lib/hive/worker/ios.rb +125 -0
- metadata +76 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 21392f8328f698d89ed6fc4a48fa7b136b7cba6e
|
4
|
+
data.tar.gz: 1e9121c47f1317f7e2c2da79ecac0bc23a2c1208
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 21656ea02cab268e6eb98b20707639c67c87f7086ab5a303d3272d56046f2539e5fecfb5a9387615493f9a47a04a047ddbfe451077916ef3438d3ec762b5646e
|
7
|
+
data.tar.gz: 1d70d6e1c672a0bdedcb3355dc1459c076452d1e62fc90ae98dfdf1835b63bf09e643ac7576ed133e22ce1327eb16fb62beb3d802992be6602d14031be64f98c
|
data/README.md
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# hive-runner-ios
|
2
|
+
|
3
|
+
iOS component for the hive-runner
|
4
|
+
|
5
|
+
## Quick start
|
6
|
+
|
7
|
+
Install the hive-runner and setup your hive as described in the [hive-runner Readme](https://github.com/bbc/hive-runner/blob/master/README.md).
|
8
|
+
|
9
|
+
When presented with the option of adding a module, do so and enter 'ios' as the module name, select yes to retrieve from Github and enter BBC as the account name.
|
10
|
+
|
11
|
+
## Configuration file
|
12
|
+
|
13
|
+
The configuration file allows you to specify the Development Team, Provisioning Certificate, Signing Identity and Bundle ID to use when testing your app, please change these as appropriate:
|
14
|
+
|
15
|
+
ios:
|
16
|
+
provisioning_cert: iOS Team Provisioning Profile: *
|
17
|
+
development_team: DEVELOPMENT_TEAM_ID
|
18
|
+
signing_identity: iPhone Developer
|
19
|
+
bundle_id: TEST_APP
|
@@ -0,0 +1,171 @@
|
|
1
|
+
require 'hive/controller'
|
2
|
+
require 'hive/worker/ios'
|
3
|
+
require 'device_api/ios'
|
4
|
+
|
5
|
+
module Hive
|
6
|
+
class Controller
|
7
|
+
class Ios < Controller
|
8
|
+
|
9
|
+
def detect
|
10
|
+
Hive.logger.debug("#{Time.now} Polling hive: #{Hive.id}")
|
11
|
+
Hive.devicedb('Hive').poll(Hive.id)
|
12
|
+
Hive.logger.debug("#{Time.now} Finished polling hive: #{Hive.id}")
|
13
|
+
devices = DeviceAPI::IOS.devices
|
14
|
+
|
15
|
+
Hive.logger.debug('No devices attached') if devices.empty?
|
16
|
+
Hive.logger.debug("#{Time.now} Retrieving hive details")
|
17
|
+
hive_details = Hive.devicedb('Hive').find(Hive.id)
|
18
|
+
Hive.logger.debug("#{Time.now} Finished retrieving hive details")
|
19
|
+
|
20
|
+
unless hive_details.key?('devices')
|
21
|
+
Hive.logger.debug('Could not connect to DeviceDB at this time')
|
22
|
+
return []
|
23
|
+
end
|
24
|
+
|
25
|
+
unless hive_details['devices'].empty?
|
26
|
+
hive_details['devices'].select {|a| a['os'] == 'ios'}.each do |device|
|
27
|
+
registered_device = devices.select { |a| a.serial == device['serial'] }
|
28
|
+
if registered_device.empty?
|
29
|
+
# A previously registered device isn't attached
|
30
|
+
Hive.logger.debug("Removing previously registered device - #{device}")
|
31
|
+
Hive.devicedb('Device').hive_disconnect(device['id'])
|
32
|
+
else
|
33
|
+
# A previously registered device is attached, poll it
|
34
|
+
Hive.logger.debug("#{Time.now} Polling attached device - #{device}")
|
35
|
+
Hive.devicedb('Device').poll(device['id'])
|
36
|
+
Hive.logger.debug("#{Time.now} Finished polling device - #{device}")
|
37
|
+
|
38
|
+
populate_queues(device)
|
39
|
+
devices = devices - registered_device
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
display_untrusted(devices)
|
45
|
+
display_devices
|
46
|
+
|
47
|
+
if hive_details.key?('devices')
|
48
|
+
hive_details['devices'].select {|a| a['os'] == 'ios'}.collect do |device|
|
49
|
+
object = Object
|
50
|
+
@device_class.split('::').each { |sub| object = object.const_get(sub) }
|
51
|
+
object.new(@config.merge(device))
|
52
|
+
end
|
53
|
+
else
|
54
|
+
[]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def display_untrusted(devices)
|
59
|
+
untrusted_devices = []
|
60
|
+
# We will now have a list of devices that haven't previously been added
|
61
|
+
devices.each do |device|
|
62
|
+
begin
|
63
|
+
if !device.trusted?
|
64
|
+
untrusted_devices << device.serial
|
65
|
+
next
|
66
|
+
end
|
67
|
+
|
68
|
+
register_new_device(device)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
if !untrusted_devices.empty?
|
73
|
+
puts Terminal::Table.new headings: ['Untrusted Devices'], rows: [untrusted_devices]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def display_devices
|
78
|
+
rows = []
|
79
|
+
|
80
|
+
hive_details = Hive.devicedb('Hive').find(Hive.id)
|
81
|
+
if hive_details.key?('devices')
|
82
|
+
unless hive_details['devices'].empty?
|
83
|
+
rows = hive_details['devices'].map do |device|
|
84
|
+
[
|
85
|
+
"#{device['device_brand']} #{device['device_model']}",
|
86
|
+
device['serial'],
|
87
|
+
(device['device_queues'].map { |queue| queue['name']}).join("\n"),
|
88
|
+
device['status']
|
89
|
+
]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
table = Terminal::Table.new :headings => ['Device', 'Serial', 'Queue Name', 'Status'], :rows => rows
|
94
|
+
|
95
|
+
puts(table)
|
96
|
+
end
|
97
|
+
|
98
|
+
def register_new_device(device)
|
99
|
+
Hive.logger.debug("Found iOS device: #{device.model}")
|
100
|
+
|
101
|
+
attributes = {
|
102
|
+
os: 'ios',
|
103
|
+
os_version: device.version,
|
104
|
+
serial: device.serial,
|
105
|
+
device_type: device.type,
|
106
|
+
device_model: device.model.to_s.gsub(',','_'),
|
107
|
+
device_range: device.device_class,
|
108
|
+
device_brand: 'Apple',
|
109
|
+
hive: Hive.id
|
110
|
+
}
|
111
|
+
|
112
|
+
registration = Hive.devicedb('Device').register(attributes)
|
113
|
+
Hive.devicedb('Device').hive_connect(registration['id'], Hive.id)
|
114
|
+
end
|
115
|
+
|
116
|
+
def populate_queues(device)
|
117
|
+
queues = calculate_queue_names(device)
|
118
|
+
|
119
|
+
devicedb_queues = device['device_queues'].map { |d| d['name'] }
|
120
|
+
# Check to see if the queues have already been registered with this device
|
121
|
+
missing_queues = (queues - devicedb_queues) + (devicedb_queues - queues)
|
122
|
+
return if missing_queues.empty?
|
123
|
+
|
124
|
+
queues << missing_queues
|
125
|
+
|
126
|
+
queue_ids = queues.flatten.uniq.map { |queue| find_or_create_queue(queue) }
|
127
|
+
|
128
|
+
values = {
|
129
|
+
name: device['name'],
|
130
|
+
hive_id: device['hive_id'],
|
131
|
+
feature_list: device['features'],
|
132
|
+
device_queue_ids: queue_ids
|
133
|
+
}
|
134
|
+
|
135
|
+
Hive.devicedb('Device').edit(device['id'], values)
|
136
|
+
end
|
137
|
+
|
138
|
+
def find_or_create_queue(name)
|
139
|
+
queue = Hive.devicedb('Queue').find_by_name(name)
|
140
|
+
return queue.first['id'] unless queue.empty?
|
141
|
+
|
142
|
+
create_queue(name, "#{name} queue created by Hive Runner")['id']
|
143
|
+
end
|
144
|
+
|
145
|
+
def create_queue(name, description)
|
146
|
+
queue_attributes = {
|
147
|
+
name: name,
|
148
|
+
description: description
|
149
|
+
}
|
150
|
+
|
151
|
+
Hive.devicedb('Queue').register(device_queue: queue_attributes )
|
152
|
+
end
|
153
|
+
|
154
|
+
def calculate_queue_names(device)
|
155
|
+
|
156
|
+
queues = [
|
157
|
+
device['device_model'],
|
158
|
+
device['os'],
|
159
|
+
"#{device['os']}-#{device['os_version']}",
|
160
|
+
"#{device['os']}-#{device['os_version']}-#{device['device_model']}",
|
161
|
+
device['device_type'],
|
162
|
+
"#{device['os']}-#{device['device_type']}"
|
163
|
+
]
|
164
|
+
|
165
|
+
queues << device["features"] unless device["features"].empty?
|
166
|
+
|
167
|
+
queues.flatten
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'hive/worker'
|
2
|
+
require 'hive/messages/ios_job'
|
3
|
+
require 'fruity_builder'
|
4
|
+
|
5
|
+
module Hive
|
6
|
+
class PortReserver
|
7
|
+
attr_accessor :ports
|
8
|
+
def initialize
|
9
|
+
self.ports = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def reserve(queue_name)
|
13
|
+
self.ports[queue_name] = yield
|
14
|
+
self.ports[queue_name]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Worker
|
19
|
+
class Ios < Worker
|
20
|
+
|
21
|
+
attr_accessor :device
|
22
|
+
|
23
|
+
def initialize(device)
|
24
|
+
@worker_ports = PortReserver.new
|
25
|
+
self.device = device
|
26
|
+
super(device)
|
27
|
+
end
|
28
|
+
|
29
|
+
def alter_project(project_path)
|
30
|
+
dev_team = @options['development_team'] || ''
|
31
|
+
signing_identity = @options['signing_identity'] || ''
|
32
|
+
provisioning_profile = @options['provisioning_profile'] || ''
|
33
|
+
|
34
|
+
helper = FruityBuilder::IOS::Helper.new(project_path)
|
35
|
+
|
36
|
+
helper.build.replace_bundle_id(@options['bundle_id'])
|
37
|
+
|
38
|
+
helper.build.replace_dev_team(dev_team)
|
39
|
+
helper.build.replace_code_sign_identity(signing_identity)
|
40
|
+
helper.build.replace_provisioning_profile(provisioning_profile)
|
41
|
+
helper.build.save_project_properties
|
42
|
+
end
|
43
|
+
|
44
|
+
def replace_project_data(options = {})
|
45
|
+
regex = Regexp.new(options[:regex])
|
46
|
+
replacements = options[:data].scan(regex).uniq.flatten
|
47
|
+
|
48
|
+
result = options[:data]
|
49
|
+
replacements.each do |to_replace|
|
50
|
+
result = result.gsub(to_replace, options[:new_value])
|
51
|
+
end
|
52
|
+
|
53
|
+
result
|
54
|
+
end
|
55
|
+
|
56
|
+
def pre_script(job, file_system, script)
|
57
|
+
Hive.devicedb('Device').poll(@options['id'], 'busy')
|
58
|
+
|
59
|
+
if job.build
|
60
|
+
FileUtils.mkdir(file_system.home_path + '/build')
|
61
|
+
app_path = file_system.home_path + '/build/' + 'build.ipa'
|
62
|
+
|
63
|
+
file_system.fetch_build(job.build, app_path)
|
64
|
+
app_info = DeviceAPI::IOS::Plistutil.get_bundle_id_from_app(app_path)
|
65
|
+
app_bundle = app_info['CFBundleIdentifier']
|
66
|
+
script.set_env 'BUNDLE_ID', app_bundle
|
67
|
+
else
|
68
|
+
alter_project(file_system.home_path + '/test_code/code/')
|
69
|
+
end
|
70
|
+
|
71
|
+
ip_address = DeviceAPI::IOS::IPAddress.address(self.device['serial'])
|
72
|
+
|
73
|
+
script.set_env 'CHARLES_PROXY_PORT', @ports.reserve(queue_name: 'Charles')
|
74
|
+
|
75
|
+
# TODO: Allow the scheduler to specify the ports to use
|
76
|
+
|
77
|
+
script.set_env 'APPIUM_PORT', @worker_ports.reserve(queue_name: 'Appium') { self.allocate_port }
|
78
|
+
script.set_env 'BOOTSTRAP_PORT', @worker_ports.reserve(queue_name: 'Bootstrap') { self.allocate_port }
|
79
|
+
script.set_env 'CHROMEDRIVER_PORT', @worker_ports.reserve(queue_name: 'Chromedriver') { self.allocate_port }
|
80
|
+
|
81
|
+
script.set_env 'APP_PATH', app_path
|
82
|
+
script.set_env 'APP_BUNDLE_PATH', app_path
|
83
|
+
script.set_env 'DEVICE_TARGET', self.device['serial']
|
84
|
+
script.set_env 'DEVICE_ENDPOINT', "http://#{ip_address}:37265"
|
85
|
+
|
86
|
+
"#{self.device['serial']} #{@ports.ports['Appium']} #{app_path} #{file_system.results_path}"
|
87
|
+
end
|
88
|
+
|
89
|
+
def job_message_klass
|
90
|
+
Hive::Messages::IosJob
|
91
|
+
end
|
92
|
+
|
93
|
+
def post_script(job, file_system, script)
|
94
|
+
@log.info('Post script')
|
95
|
+
@worker_ports.ports.each do |name, port|
|
96
|
+
self.release_port(port)
|
97
|
+
end
|
98
|
+
set_device_status('idle')
|
99
|
+
end
|
100
|
+
|
101
|
+
def device_status
|
102
|
+
details = Hive.devicedb('Device').find(@options['id'])
|
103
|
+
if details.key?('status')
|
104
|
+
@state = details['status']
|
105
|
+
else
|
106
|
+
@state
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def set_device_status(status)
|
111
|
+
@state = status
|
112
|
+
begin
|
113
|
+
details = Hive.devicedb('Device').poll(@options['id'], status)
|
114
|
+
if details.key?('status')
|
115
|
+
@state = details['status']
|
116
|
+
else
|
117
|
+
@state
|
118
|
+
end
|
119
|
+
rescue
|
120
|
+
@state
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hive-runner-ios
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jon Wilson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-10-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: device_api-ios
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: fruity_builder
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
description: The iOS controller module for Hive Runner
|
42
|
+
email: jon.wilson01@bbc.co.uk
|
43
|
+
executables: []
|
44
|
+
extensions: []
|
45
|
+
extra_rdoc_files: []
|
46
|
+
files:
|
47
|
+
- README.md
|
48
|
+
- lib/hive/controller/ios.rb
|
49
|
+
- lib/hive/device/ios.rb
|
50
|
+
- lib/hive/messages/ios_job.rb
|
51
|
+
- lib/hive/worker/ios.rb
|
52
|
+
homepage: https://github.com/bbc/hive-runner-ios
|
53
|
+
licenses:
|
54
|
+
- MIT
|
55
|
+
metadata: {}
|
56
|
+
post_install_message:
|
57
|
+
rdoc_options: []
|
58
|
+
require_paths:
|
59
|
+
- lib
|
60
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
requirements: []
|
71
|
+
rubyforge_project:
|
72
|
+
rubygems_version: 2.4.8
|
73
|
+
signing_key:
|
74
|
+
specification_version: 4
|
75
|
+
summary: Hive Runner iOS
|
76
|
+
test_files: []
|