fastlane-plugin-mango 1.1.3 → 1.3.23

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9194c8b391c61584dc3f7869e34408e9ea8cbd3bd83e358411eb88991047867e
4
- data.tar.gz: 77a3155ba799fab155fef7c91f28c77b92e60e68ab89354d69b1b498bd1fb31b
3
+ metadata.gz: c5e9db6561834f87bc0a4c5607f7ca117532d38d35f846ed6a389e16c7da3223
4
+ data.tar.gz: fbdff88d36c647a249c76c58a9345e5aee75a23bc231ffcd01f86986bad41357
5
5
  SHA512:
6
- metadata.gz: 8f4ec7d68b57f29587b863d1e4b7c198b0bec97034ff2da5e6aa7097be4ea02d97331fc378859f6a383de49cbd5a9d66609677b05fd226af0d92c0f617a1ab9d
7
- data.tar.gz: 69b0e5012298849306f3bc138f67311615040d14af7be6657c7cb097be136f435b842ca846ff7a54f53a1954899573dcd7968173ac97836acb4fc38d1ee143dc
6
+ metadata.gz: 3e015e871f2eceac9afb44618dab0023819f96d3066d709b540f2e7fdd4a830c970897d192f6ac0ac36a73d06fffb7992805a1ccc8f813439d3144d3a7abf569
7
+ data.tar.gz: 077d01545b646eea107ac015b1d7f847d8ffe41a66f1c33786ae0318d39b71e7ae6321564b9a420121f86c0676ae1150ce42774c57e00240694324fcb912f522
data/README.md CHANGED
@@ -78,6 +78,7 @@ The `mango` action has plenty of options to configure it.
78
78
  | `docker_image` | Name of the Docker image, that should be started and used to run your tasks. | butomo1989/docker-android-x86-5.1.1 | ❌ | `String` |
79
79
  | `container_timeout` | Timeout (in seconds) to get a healthy docker container. Depending on your `docker_image` it may take some time until it's started up and ready to use. | 450 (this equals 7.5 minutes) | ❌ | `Integer` |
80
80
  | `android_task` | A generic Android task you want to execute. | - | ❌ | `String` |
81
+ | `core_amount` | Cpu core amount while starting docker container with limited resource. | - | ✅ | `Integer` |
81
82
  | `sdk_path` | The path to your Android sdk directory. | `ANDROID_HOME` environment variable | ✅ | `String` |
82
83
  | `port_factor` | Base for calculating a unique port for noVNC. We recommend to use the `EXECUTOR_NUMBER` from your Jenkins environment. | - | ✅ | `String` |
83
84
  | `workspace_dir` | Path to the workspace to execute commands. If you want to execute your `android_task` from a different directory you have to specify `workspace_dir`. | `/root/tests/` | ✅ | `String` |
@@ -4,7 +4,9 @@ module Fastlane
4
4
  module Actions
5
5
  class RunDockerizedTaskAction < Action
6
6
  def self.run(params)
7
- UI.important("The mango plugin is working!")
7
+ UI.important('The mango plugin is working!')
8
+ workspace_dir = params[:workspace_dir]
9
+ ENV['DOCKER_CONFIG'] = "#{ENV['WORKSPACE']}/.docker"
8
10
  mango_helper = Fastlane::Helper::MangoHelper.new(params)
9
11
  mango_helper.setup_container
10
12
 
@@ -12,32 +14,45 @@ module Fastlane
12
14
 
13
15
  failure_buffer_timeout = 5
14
16
  timeout_command = "timeout #{params[:maximal_run_time] - failure_buffer_timeout}m"
15
- workspace_dir = params[:workspace_dir]
16
17
 
17
18
  android_task = params[:android_task]
18
19
  if android_task
19
- UI.success("Starting Android Task.")
20
+ UI.success('Starting Android Task.')
20
21
  bundle_install = params[:bundle_install] ? '&& bundle install ' : ''
21
22
 
22
23
  docker_commander.exec(command: "cd #{workspace_dir} #{bundle_install}&& #{timeout_command} #{android_task} || exit 1")
23
24
  end
24
-
25
+ rescue StandardError => e
26
+ begin
27
+ Actions.sh("docker logs #{mango_helper.container_name} --tail 200")
28
+ rescue StandardError
29
+ # do nothing
30
+ end
31
+ docker_commander.exec(command:
32
+ 'cat /var/log/supervisor/docker-android.stderr.log', raise_when_fail: false)
33
+ docker_commander.exec(command: 'cat /var/log/supervisor/supervisord.log',
34
+ raise_when_fail: false)
35
+ raise e
25
36
  ensure
26
- post_actions = params[:post_actions]
27
- if post_actions && !mango_helper.kvm_disabled?
28
- docker_commander&.exec(command: "cd #{workspace_dir} && #{post_actions}")
37
+ begin
38
+ post_actions = params[:post_actions]
39
+ if post_actions && !mango_helper.kvm_disabled?
40
+ docker_commander&.exec(command: "cd #{workspace_dir} && #{post_actions}")
41
+ end
42
+
43
+ UI.important("Cleaning up #{params[:emulator_name]} container")
44
+ docker_commander.delete_container if mango_helper&.instance_variable_get('@container')
45
+ rescue StandardError => e
46
+ puts e
29
47
  end
30
-
31
- UI.important("Cleaning up #{params[:emulator_name]} container")
32
- mango_helper.clean_container if mango_helper&.instance_variable_get('@container')
33
48
  end
34
49
 
35
50
  def self.description
36
- "Action that runs Android tasks on a specified Docker image"
51
+ 'Action that runs Android tasks on a specified Docker image'
37
52
  end
38
53
 
39
54
  def self.authors
40
- ["Serghei Moret", "Daniel Hartwich"]
55
+ ['Serghei Moret', 'Daniel Hartwich']
41
56
  end
42
57
 
43
58
  def self.return_value
@@ -50,123 +65,144 @@ module Fastlane
50
65
 
51
66
  def self.details
52
67
  # Optional:
53
- ""
68
+ ''
54
69
  end
55
70
 
56
71
  def self.available_options
57
72
  [
58
73
  FastlaneCore::ConfigItem.new(key: :container_name,
59
- env_name: "CONTAINER_NAME",
60
- description: "Name of the docker container. Will be generated randomly if not defined",
61
- optional: true,
62
- type: String),
74
+ env_name: 'CONTAINER_NAME',
75
+ description: 'Name of the docker container. Will be generated randomly if not defined',
76
+ optional: true,
77
+ type: String),
63
78
 
64
79
  FastlaneCore::ConfigItem.new(key: :no_vnc_port,
65
- env_name: "NO_VNC_PORT",
66
- description: "Port to redirect noVNC. 6080 by default",
80
+ env_name: 'NO_VNC_PORT',
81
+ description: 'Port to redirect noVNC. 6080 by default',
67
82
  default_value: 6080,
68
83
  optional: false,
69
84
  type: Integer),
70
85
 
71
86
  FastlaneCore::ConfigItem.new(key: :device_name,
72
- env_name: "DEVICE_NAME",
73
- description: "Name of the Android device. Nexus 5X by default",
87
+ env_name: 'DEVICE_NAME',
88
+ description: 'Name of the Android device. Nexus 5X by default',
74
89
  default_value: 'Nexus 5X',
75
90
  optional: false,
76
91
  type: String),
77
92
 
78
93
  FastlaneCore::ConfigItem.new(key: :emulator_name,
79
- env_name: "EMULATOR_NAME",
80
- description: "Name of the Android emulator. emulator-5554 by default",
94
+ env_name: 'EMULATOR_NAME',
95
+ description: 'Name of the Android emulator. emulator-5554 by default',
81
96
  default_value: 'emulator-5554',
82
97
  optional: false,
83
98
  type: String),
84
99
 
85
100
  FastlaneCore::ConfigItem.new(key: :docker_image,
86
- env_name: "DOCKER_IMAGE",
87
- description: "Name of the Docker image. butomo1989/docker-android-x86-5.1.1 by default",
101
+ env_name: 'DOCKER_IMAGE',
102
+ description: 'Name of the Docker image. butomo1989/docker-android-x86-5.1.1 by default',
88
103
  default_value: 'butomo1989/docker-android-x86-5.1.1',
89
104
  optional: false,
90
105
  type: String),
91
106
 
92
107
  FastlaneCore::ConfigItem.new(key: :container_timeout,
93
- env_name: "CONTAINER_TIMEOUT",
94
- description: "Timeout (in seconds) to get the healthy docker container. 450 (7.5 minutes) by default",
95
- default_value: 450,
96
- optional: false,
97
- type: Integer),
98
-
99
- FastlaneCore::ConfigItem.new(key: :android_task,
100
- env_name: "ANDROID TASK",
101
- description: "A generic Android task you want to execute",
102
- is_string: true,
103
- optional: false),
108
+ env_name: 'CONTAINER_TIMEOUT',
109
+ description: 'Timeout (in seconds) to get the healthy docker container. 450 (7.5 minutes) by default',
110
+ default_value: 450,
111
+ optional: false,
112
+ type: Integer),
113
+
114
+ FastlaneCore::ConfigItem.new(key: :android_task,
115
+ env_name: 'ANDROID TASK',
116
+ description: 'A generic Android task you want to execute',
117
+ is_string: true,
118
+ optional: false),
104
119
 
105
120
  FastlaneCore::ConfigItem.new(key: :sdk_path,
106
- env_name: "SDK_PATH",
107
- description: "The path to your Android sdk directory (root). ANDROID_HOME by default",
121
+ env_name: 'SDK_PATH',
122
+ description: 'The path to your Android sdk directory (root). ANDROID_HOME by default',
108
123
  default_value: ENV['ANDROID_HOME'],
109
124
  is_string: true,
110
125
  optional: true),
111
126
 
112
127
  FastlaneCore::ConfigItem.new(key: :port_factor,
113
- env_name: "PORT_FACTOR",
114
- description: "Base for calculating a unique port for noVNC. You can pass EXECUTOR_NUMBER from Jenkins for example, this will be unique and not clash in case of several instances running on the same machine",
115
- optional: true,
116
- type: String),
128
+ env_name: 'PORT_FACTOR',
129
+ description: 'Base for calculating a unique port for noVNC. You can pass EXECUTOR_NUMBER from Jenkins for example, this will be unique and not clash in case of several instances running on the same machine',
130
+ optional: true,
131
+ type: String),
132
+
133
+ FastlaneCore::ConfigItem.new(key: :core_amount,
134
+ env_name: 'CORE_AMOUNT',
135
+ default_value: 0,
136
+ description: 'Define if we want to start docker container with the limitation',
137
+ optional: true,
138
+ type: Integer),
117
139
 
118
140
  FastlaneCore::ConfigItem.new(key: :workspace_dir,
119
- env_name: "WORKSPACE_DIR",
141
+ env_name: 'WORKSPACE_DIR',
120
142
  default_value: '/root/tests/',
121
- description: "Path to the workspace to execute commands. If you want to execute your `android_task` from a different directory you have to specify `workspace_dir`",
143
+ description: 'Path to the workspace to execute commands. If you want to execute your `android_task` from a different directory you have to specify `workspace_dir`',
122
144
  optional: true,
123
145
  type: String),
124
146
 
125
147
  FastlaneCore::ConfigItem.new(key: :maximal_run_time,
126
- env_name: "MAXIMAL_RUN_TIME",
148
+ env_name: 'MAXIMAL_RUN_TIME',
127
149
  default_value: 60,
128
- description: "Defines the maximal time of your test run. Defaults to 60 minutes",
150
+ description: 'Defines the maximal time of your test run. Defaults to 60 minutes',
129
151
  optional: true,
130
152
  type: Integer),
131
153
 
132
154
  FastlaneCore::ConfigItem.new(key: :bundle_install,
133
- env_name: "BUNDLE_INSTALL",
155
+ env_name: 'BUNDLE_INSTALL',
134
156
  default_value: false,
135
- description: "Defines if the Android task must execute bundle install before running a build",
157
+ description: 'Defines if the Android task must execute bundle install before running a build',
136
158
  optional: true,
137
159
  type: Boolean),
138
160
 
139
161
  FastlaneCore::ConfigItem.new(key: :is_running_on_emulator,
140
- env_name: "IS_RUNNING_ON_EMULATOR",
162
+ env_name: 'IS_RUNNING_ON_EMULATOR',
141
163
  default_value: true,
142
- description: "Define if we want to run the emulator in the container",
164
+ description: 'Define if we want to run the emulator in the container',
143
165
  optional: true,
144
166
  type: Boolean),
145
167
 
146
168
  FastlaneCore::ConfigItem.new(key: :post_actions,
147
- env_name: "POST_ACTIONS",
148
- description: "Actions that will be executed after the main command has been executed",
149
- is_string: true,
150
- optional: true),
169
+ env_name: 'POST_ACTIONS',
170
+ description: 'Actions that will be executed after the main command has been executed',
171
+ is_string: true,
172
+ optional: true),
151
173
 
152
174
  FastlaneCore::ConfigItem.new(key: :pre_action,
153
- env_name: "PRE_ACTION",
154
- description: "Actions that will be executed before the docker image gets pulled",
155
- is_string: true,
156
- optional: true),
175
+ env_name: 'PRE_ACTION',
176
+ description: 'Actions that will be executed before the docker image gets pulled',
177
+ is_string: true,
178
+ optional: true),
157
179
 
158
180
  FastlaneCore::ConfigItem.new(key: :docker_registry_login,
159
- env_name: "DOCKER_REGISTRY_LOGIN",
160
- description: "Authenticating yourself to a custom Docker registry",
161
- type: String,
162
- optional: true),
181
+ env_name: 'DOCKER_REGISTRY_LOGIN',
182
+ description: 'Authenticating yourself to a custom Docker registry',
183
+ type: String,
184
+ optional: true),
163
185
 
164
186
  FastlaneCore::ConfigItem.new(key: :pull_latest_image,
165
- env_name: "PULL_LATEST_IMAGE",
166
- description: "Define if you want to pull the latest image",
167
- type: Boolean,
168
- default_value: false,
169
- optional: true)
187
+ env_name: 'PULL_LATEST_IMAGE',
188
+ description: 'Define if you want to pull the latest image',
189
+ type: Boolean,
190
+ default_value: false,
191
+ optional: true),
192
+
193
+ FastlaneCore::ConfigItem.new(key: :environment_variables,
194
+ env_name: 'ENVIRONMENT_VARIABLES',
195
+ description: 'Comma seperated list of environment variables which are passed into the docker container',
196
+ type: Array,
197
+ default_value: [],
198
+ optional: true),
199
+
200
+ FastlaneCore::ConfigItem.new(key: :vnc_enabled,
201
+ env_name: 'VNC_ENABLED',
202
+ description: 'A bool. True for vnc_enabled False for vnc_disabled',
203
+ type: Boolean,
204
+ default_value: true,
205
+ optional: true)
170
206
  ]
171
207
  end
172
208
  end
@@ -0,0 +1,40 @@
1
+ require 'os'
2
+
3
+ module Fastlane
4
+ module Helper
5
+ module CpuLoadHandler
6
+ def self.print_cpu_load(load = cpu_load)
7
+ UI.important("CPU load is: #{load}") if load
8
+ end
9
+
10
+ # Gets load average of Linux machine
11
+ def self.cpu_load
12
+ load = Actions.sh('cat /proc/loadavg')
13
+ load.split(' ').first.to_f unless load.empty?
14
+ end
15
+
16
+ # Gets amount of the CPU cores
17
+ def self.cpu_core_amount
18
+ Actions.sh("cat /proc/cpuinfo | awk '/^processor/{print $3}' | tail -1")
19
+ end
20
+
21
+ # For half an hour waiting until CPU load average is less than number of cores*2 (which considers that CPU is ready)
22
+ # Raises when 30 minutes timeout exceeds
23
+ def self.wait_cpu_to_idle
24
+ if OS.linux?
25
+ 30.times do
26
+ load = cpu_load
27
+ return true if load <= cpu_core_amount.to_i * 1.5
28
+
29
+ print_cpu_load(load)
30
+ UI.important('Waiting for available resources..')
31
+ sleep 60
32
+ end
33
+ else
34
+ return true
35
+ end
36
+ raise "CPU was overloaded. Couldn't start emulator"
37
+ end
38
+ end
39
+ end
40
+ end
@@ -1,10 +1,8 @@
1
1
  require 'docker'
2
- require 'os'
3
2
 
4
3
  module Fastlane
5
4
  module Helper
6
5
  class DockerCommander
7
-
8
6
  attr_accessor :container_name
9
7
 
10
8
  def initialize(container_name)
@@ -12,66 +10,63 @@ module Fastlane
12
10
  end
13
11
 
14
12
  def pull_image(docker_image_name:)
15
- handle_thin_pool_exception do
16
- Actions.sh("docker pull #{docker_image_name}")
17
- end
13
+ Actions.sh("docker pull #{docker_image_name}")
14
+ rescue StandardError => e
15
+ prune if e.message =~ /Create more free space in thin pool/
16
+ Actions.sh("docker pull #{docker_image_name}")
18
17
  end
19
18
 
20
- def start_container(emulator_args:, docker_image:)
19
+ def start_container(emulator_args:, docker_image:, core_amount:)
20
+ retries ||= 0
21
21
  docker_name = if container_name
22
22
  "--name #{container_name}"
23
23
  else
24
24
  ''
25
25
  end
26
+ # if core_amount value is defined then limit the container while starting
27
+ core_amount = if core_amount && core_amount > 0
28
+ "--cpus=#{core_amount}"
29
+ else
30
+ ''
31
+ end
26
32
 
27
33
  # Action.sh returns all output that the command produced but we are only
28
34
  # interested in the last line, since it contains the id of the created container.
29
35
  UI.important("Attaching #{ENV['PWD']} to the docker container")
30
- handle_thin_pool_exception do
31
- Actions.sh("docker run -v $PWD:/root/tests --privileged -t -d #{emulator_args} #{docker_name} #{docker_image}").chomp
36
+ Actions.sh("docker run -v $PWD:/root/tests --privileged -t -d #{core_amount} #{emulator_args} #{docker_name} #{docker_image}").chomp
37
+ rescue StandardError => e
38
+ if e.message =~ /Create more free space in thin pool/ && (retries += 1) < 2
39
+ prune
40
+ retry
32
41
  end
33
42
  end
34
43
 
35
- def stop_container
36
- Actions.sh("docker stop #{container_name}") if container_name
37
- end
38
-
39
44
  def delete_container
40
- Actions.sh("docker rm #{container_name}") if container_name
45
+ Actions.sh("docker rm -f #{container_name}") if container_name
41
46
  end
42
47
 
43
48
  def disconnect_network_bridge
49
+ UI.important('Disconnecting from the network bridge')
44
50
  Actions.sh("docker network disconnect -f bridge #{container_name}") if container_name
45
51
  rescue StandardError
46
52
  # Do nothing if the network bridge is already gone
47
53
  end
48
54
 
49
- def exec(command:)
55
+ def exec(command:, raise_when_fail: true)
50
56
  if container_name
51
- Actions.sh("docker exec -i #{container_name} bash -l -c \"#{command}\"")
57
+ begin
58
+ Actions.sh("docker exec #{container_name} bash -l -c \"#{command}\"")
59
+ rescue StandardError => e
60
+ raise(e) if raise_when_fail
61
+ end
52
62
  else
53
63
  raise('Cannot execute docker command because the container name is unknown')
54
64
  end
55
65
  end
56
-
66
+
57
67
  def prune
58
68
  Action.sh('docker system prune -f')
59
69
  end
60
-
61
- def handle_thin_pool_exception(&block)
62
- begin
63
- block.call
64
- rescue FastlaneCore::Interface::FastlaneShellError => exception
65
- retry_counter = retry_counter.to_i + 1
66
- if exception.message =~ /Create more free space in thin pool/ && retry_counter < 2
67
- prune
68
- retry
69
- else
70
- raise exception
71
- end
72
- end
73
- end
74
-
75
70
  end
76
71
  end
77
- end
72
+ end
@@ -2,9 +2,7 @@ require_relative 'docker_commander'
2
2
 
3
3
  module Fastlane
4
4
  module Helper
5
-
6
5
  class EmulatorCommander
7
-
8
6
  attr_accessor :container_name
9
7
 
10
8
  def initialize(container_name)
@@ -22,7 +20,7 @@ module Fastlane
22
20
  # it recovers after some time, so wait and retry
23
21
  retry_counter = retry_counter.to_i + 1
24
22
  if retry_counter <= 5
25
- sleep 10*retry_counter
23
+ sleep 10 * retry_counter
26
24
  retry
27
25
  else
28
26
  raise e
@@ -50,7 +48,17 @@ module Fastlane
50
48
  def emulator_is_healthy?
51
49
  list_devices = @docker_commander.exec(command: 'adb devices')
52
50
  list_devices.include? "\tdevice"
51
+ rescue FastlaneCore::Interface::FastlaneShellError => e
52
+ # Under weird circumstances it can happen that adb is running but adb is not completely up
53
+ # it recovers after some time, so wait and retry
54
+ retry_counter = retry_counter.to_i + 1
55
+ if retry_counter <= 5
56
+ sleep 10 * retry_counter
57
+ retry
58
+ else
59
+ raise e
60
+ end
53
61
  end
54
62
  end
55
63
  end
56
- end
64
+ end
@@ -1,14 +1,13 @@
1
- require 'docker'
2
- require 'timeout'
3
- require 'os'
4
1
  require 'net/http'
5
2
  require_relative 'docker_commander'
6
3
  require_relative 'emulator_commander'
4
+ require_relative 'cpu_load_handler'
7
5
 
8
6
  module Fastlane
9
7
  module Helper
10
8
  class MangoHelper
11
- attr_reader :container_name, :no_vnc_port, :device_name, :docker_image, :timeout, :port_factor, :maximal_run_time, :sleep_interval, :is_running_on_emulator
9
+ attr_reader :container_name, :no_vnc_port, :device_name, :docker_image, :timeout, :port_factor,
10
+ :maximal_run_time, :sleep_interval, :is_running_on_emulator, :environment_variables, :vnc_enabled, :core_amount
12
11
 
13
12
  def initialize(params)
14
13
  @container_name = params[:container_name]
@@ -18,6 +17,7 @@ module Fastlane
18
17
  @timeout = params[:container_timeout]
19
18
  @sdk_path = params[:sdk_path]
20
19
  @port_factor = params[:port_factor].to_i
20
+ @core_amount = params[:core_amount].to_i
21
21
  @maximal_run_time = params[:maximal_run_time]
22
22
  @sleep_interval = 5
23
23
  @container = nil
@@ -26,7 +26,8 @@ module Fastlane
26
26
  @pre_action = params[:pre_action]
27
27
  @docker_registry_login = params[:docker_registry_login]
28
28
  @pull_latest_image = params[:pull_latest_image]
29
-
29
+ @environment_variables = params[:environment_variables]
30
+ @vnc_enabled = params[:vnc_enabled]
30
31
  @docker_commander = DockerCommander.new(container_name)
31
32
  @emulator_commander = EmulatorCommander.new(container_name)
32
33
  end
@@ -40,13 +41,11 @@ module Fastlane
40
41
  assign_unique_vnc_port if port_factor && is_running_on_emulator
41
42
 
42
43
  if container_available?
43
- @container.stop
44
- @container.delete(force: true)
44
+ UI.important('Container was already started. Stopping and removing..')
45
+ @docker_commander.delete_container
45
46
  end
46
47
 
47
- handle_ports_allocation if is_running_on_emulator
48
-
49
- execute_pre_action if @pre_action
48
+ handle_ports_allocation if is_running_on_emulator && vnc_enabled
50
49
 
51
50
  pull_from_registry if @pull_latest_image
52
51
 
@@ -67,14 +66,20 @@ module Fastlane
67
66
  end
68
67
 
69
68
  unless container_state
70
- UI.important("Will retry checking for a healthy docker container after #{sleep_interval} seconds")
71
- @container.stop
72
- @container.delete(force: true)
69
+ UI.important("Will retry to create a healthy docker container after #{sleep_interval} seconds")
70
+ @docker_commander.delete_container
73
71
  sleep @sleep_interval
74
72
  create_container
75
73
 
76
74
  unless wait_for_healthy_container
77
75
  UI.important('Container is unhealthy. Exiting..')
76
+ begin
77
+ Actions.sh("docker logs #{container_name} --tail 200")
78
+ Actions.sh("docker exec -i #{container_name} cat /var/log/supervisor/docker-android.stderr.log")
79
+ Actions.sh("docker exec -i #{container_name} cat /var/log/supervisor/supervisord.log")
80
+ rescue StandardError
81
+ # do nothing
82
+ end
78
83
  # We use code "2" as we need something than just standard error code 1, so we can differentiate the next step in CI
79
84
  exit 2
80
85
  end
@@ -89,6 +94,8 @@ module Fastlane
89
94
  @emulator_commander.disable_animations
90
95
  @emulator_commander.increase_logcat_storage
91
96
  end
97
+
98
+ execute_pre_action if @pre_action
92
99
  end
93
100
 
94
101
  def kvm_disabled?
@@ -100,12 +107,6 @@ module Fastlane
100
107
  @docker_commander.exec(command: 'cat kvm-ok.txt').include?('KVM acceleration can NOT be used')
101
108
  end
102
109
 
103
- # Stops and remove container
104
- def clean_container
105
- @container.stop
106
- @container.delete(force: true)
107
- end
108
-
109
110
  private
110
111
 
111
112
  # Sets path to adb
@@ -116,7 +117,7 @@ module Fastlane
116
117
  # assigns vnc port
117
118
  def assign_unique_vnc_port
118
119
  @no_vnc_port = 6080 + port_factor
119
- @host_ip_address = `hostname -I | head -n1 | awk '{print $1;}'`.delete!("\n")
120
+ @host_ip_address = `hostname -i | head -n1 | awk '{print $1;}'`.delete!("\n")
120
121
  UI.success("Port: #{@no_vnc_port} was chosen for VNC")
121
122
  UI.success("Link to VNC: http://#{@host_ip_address}:#{@no_vnc_port}")
122
123
  end
@@ -124,49 +125,55 @@ module Fastlane
124
125
  # Creates new container using params
125
126
  def create_container
126
127
  UI.important("Creating container: #{container_name}")
127
- print_cpu_load
128
+ CpuLoadHandler.print_cpu_load
128
129
  begin
129
130
  container = create_container_call
130
131
  set_container_name(container)
131
132
  rescue StandardError
132
133
  UI.important("Something went wrong while creating: #{container_name}, will retry in #{@sleep_interval} seconds")
133
- print_cpu_load
134
- @docker_commander.stop_container
134
+ CpuLoadHandler.print_cpu_load
135
135
  @docker_commander.delete_container
136
-
137
136
  sleep @sleep_interval
138
137
  container = create_container_call
139
138
  set_container_name(container)
140
139
  end
141
- get_container_instance(container)
140
+ @container = get_container_instance(container)
141
+
142
+ if @container.nil?
143
+ sleep 3
144
+ @container = get_container_instance(container)
145
+ end
142
146
  end
143
147
 
144
148
  # Gets container instance by container ID
145
149
  def get_container_instance(container)
146
150
  Docker::Container.all(all: true).each do |cont|
147
- if cont.id == container
148
- @container = cont
149
- break
150
- end
151
+ return cont if cont.id == container
151
152
  end
152
153
  end
153
154
 
154
155
  # Call to create a container. We don't use Docker API here, as it doesn't support --privileged.
155
156
  def create_container_call
156
157
  # When CPU is under load we cannot create a healthy container
157
- wait_cpu_to_idle
158
+ CpuLoadHandler.wait_cpu_to_idle
158
159
 
160
+ additional_env = ''
161
+ environment_variables.each do |variable|
162
+ additional_env += " -e #{variable}"
163
+ end
159
164
  emulator_args = is_running_on_emulator ? "-p #{no_vnc_port}:6080 -e DEVICE='#{device_name}'" : ''
160
-
161
- @docker_commander.start_container(emulator_args: emulator_args, docker_image: docker_image)
165
+ emulator_args = "#{emulator_args}#{additional_env}"
166
+ @docker_commander.start_container(emulator_args: emulator_args, docker_image: docker_image,
167
+ core_amount: core_amount)
162
168
  end
163
169
 
164
170
  def execute_pre_action
165
- Actions.sh(@pre_action)
171
+ @docker_commander.exec(command: @pre_action)
166
172
  end
167
173
 
168
174
  # Pull the docker images before creating a container
169
175
  def pull_from_registry
176
+ UI.important('Pulling the :latest image from the registry')
170
177
  docker_image_name = docker_image.gsub(':latest', '')
171
178
  Actions.sh(@docker_registry_login) if @docker_registry_login
172
179
  @docker_commander.pull_image(docker_image_name: docker_image_name)
@@ -183,7 +190,6 @@ module Fastlane
183
190
  if port_open?('0.0.0.0', @no_vnc_port)
184
191
  UI.important('Something went wrong. VNC port is still busy')
185
192
  sleep @sleep_interval
186
- @docker_commander.stop_container
187
193
  @docker_commander.delete_container
188
194
  end
189
195
  end
@@ -197,17 +203,14 @@ module Fastlane
197
203
  nil
198
204
  end
199
205
 
200
- def print_cpu_load(load = cpu_load)
201
- UI.important("CPU load is: #{load}")
202
- end
203
-
204
206
  # Checks if container is already available
205
207
  def container_available?
206
208
  return false unless container_name
209
+
207
210
  all_containers = Docker::Container.all(all: true)
208
211
 
209
212
  all_containers.each do |container|
210
- if container.info['Names'].first[1..-1] == container_name
213
+ if container.info['Names'].first[1..] == container_name
211
214
  @container = container
212
215
  return true
213
216
  end
@@ -246,6 +249,9 @@ module Fastlane
246
249
  end
247
250
  UI.important("The Container failed to load after '#{timeout}' seconds timeout. Reason: '#{@container.json['State']['Status']}'")
248
251
  false
252
+ rescue StandardError => e
253
+ puts e
254
+ false
249
255
  end
250
256
 
251
257
  # Checks if port is already openZ
@@ -257,41 +263,12 @@ module Fastlane
257
263
  false
258
264
  end
259
265
 
260
- # Gets load average of Linux machine
261
- def cpu_load
262
- load = `cat /proc/loadavg`
263
- load.split(' ').first.to_f
264
- end
265
-
266
- # Gets amount of the CPU cores
267
- def cpu_core_amount
268
- `cat /proc/cpuinfo | awk '/^processor/{print $3}' | tail -1`
269
- end
270
-
271
- # For half an hour waiting until CPU load average is less than number of cores*2 (which considers that CPU is ready)
272
- # Raises when 30 minutes timeout exceeds
273
- def wait_cpu_to_idle
274
- if OS.linux?
275
- 30.times do
276
- load = cpu_load
277
- return true if load < cpu_core_amount.to_i * 1.5
278
- print_cpu_load(load)
279
- UI.important('Waiting for available resources..')
280
- sleep 60
281
- end
282
- else
283
- return true
284
- end
285
- raise "CPU was overloaded. Couldn't start emulator"
286
- end
287
-
288
266
  # if we do not have container name, we cane use container ID that we got from create call
289
267
  def set_container_name(container)
290
268
  unless container_name
291
269
  @container_name = @emulator_commander.container_name = @docker_commander.container_name = container
292
270
  end
293
271
  end
294
-
295
272
  end
296
273
  end
297
274
  end
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module Mango
3
- VERSION = '1.1.3'.freeze
3
+ VERSION = '1.3.23'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane-plugin-mango
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.3
4
+ version: 1.3.23
5
5
  platform: ruby
6
6
  authors:
7
7
  - Serghei Moret, Daniel Hartwich
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-09-03 00:00:00.000000000 Z
11
+ date: 2021-03-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: docker-api
@@ -112,16 +112,16 @@ dependencies:
112
112
  name: rubocop
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - '='
115
+ - - ">="
116
116
  - !ruby/object:Gem::Version
117
- version: 0.58.2
117
+ version: '0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - '='
122
+ - - ">="
123
123
  - !ruby/object:Gem::Version
124
- version: 0.58.2
124
+ version: '0'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: simplecov
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -136,7 +136,7 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
- description:
139
+ description:
140
140
  email: serghei.moret@xing.com, hartwich.daniel@gmail.com
141
141
  executables: []
142
142
  extensions: []
@@ -146,6 +146,7 @@ files:
146
146
  - README.md
147
147
  - lib/fastlane/plugin/mango.rb
148
148
  - lib/fastlane/plugin/mango/actions/run_dockerized_task_action.rb
149
+ - lib/fastlane/plugin/mango/helper/cpu_load_handler.rb
149
150
  - lib/fastlane/plugin/mango/helper/docker_commander.rb
150
151
  - lib/fastlane/plugin/mango/helper/emulator_commander.rb
151
152
  - lib/fastlane/plugin/mango/helper/mango_helper.rb
@@ -154,7 +155,7 @@ homepage: https://github.com/xing/mango
154
155
  licenses:
155
156
  - MIT
156
157
  metadata: {}
157
- post_install_message:
158
+ post_install_message:
158
159
  rdoc_options: []
159
160
  require_paths:
160
161
  - lib
@@ -169,9 +170,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
169
170
  - !ruby/object:Gem::Version
170
171
  version: '0'
171
172
  requirements: []
172
- rubyforge_project:
173
- rubygems_version: 2.7.4
174
- signing_key:
173
+ rubygems_version: 3.1.2
174
+ signing_key:
175
175
  specification_version: 4
176
176
  summary: This plugin Android tasks on docker images
177
177
  test_files: []