hive-runner-ios 1.0.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.
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,12 @@
1
+ require 'hive/device'
2
+
3
+ module Hive
4
+ class Device
5
+ class Ios < Device
6
+ def initialize(config)
7
+ @identity = config['id']
8
+ super
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,11 @@
1
+ require 'hive/messages'
2
+
3
+ module Hive
4
+ module Messages
5
+ class IosJob < Hive::Messages::Job
6
+ def build
7
+ self.target.symbolize_keys[:build]
8
+ end
9
+ end
10
+ end
11
+ 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: []