fastlane-plugin-mango 1.1.6 → 1.3.15

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ed170b21d2657138918bb05cda96147bcec67db16311d04b179f7a897f67b0df
4
- data.tar.gz: c57446317b989992adfc8917a7e413a41f171110be888d38bde576e4bdde1a33
3
+ metadata.gz: 789e89cc42d904d6f20d595d4e4e5e536688431cef29839e784e6fbe8dfd7e13
4
+ data.tar.gz: e4143d7a96c169910ec836972f4362b0244828f1899a7837b33911b62f31e7f3
5
5
  SHA512:
6
- metadata.gz: 4486ba5047f7a8757bd93cdaed54ceb35a1cc2997da737771cce5adcde318e989e76eed1a957da5bcb2f5a13b1856723e110d621e80d62218ffdfbfe1d218b9f
7
- data.tar.gz: e8ddca2399e990354181dc65ba64d23614763a10183a73e973be87fa5a3eee4b283b2da942adb48b37ee59697d8d94c4d98a4adbf3f8e4d0467c5484d6d50f54
6
+ metadata.gz: '0243850ec81a9f5108d5c6ca0a46770238fced448407bdb0c6abacb734bc7804bedc58880275187908cf2a7993a52c635d84749d155d62265e8401788b53dcd4'
7
+ data.tar.gz: f0dc414874f535ac73ba139fe5476516bc340d5b66b78fd162b6760ca4f783e4911d18ee4d36bec31032431869d093e6e364756ad7c216e6685bd91ae7846c61
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,32 @@ 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
25
  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}")
26
+ begin
27
+ post_actions = params[:post_actions]
28
+ docker_commander&.exec(command: "cd #{workspace_dir} && #{post_actions}") if post_actions && !mango_helper.kvm_disabled?
29
+
30
+ UI.important("Cleaning up #{params[:emulator_name]} container")
31
+ docker_commander.delete_container if mango_helper&.instance_variable_get('@container')
32
+ rescue StandardError => e
33
+ puts e
29
34
  end
30
-
31
- UI.important("Cleaning up #{params[:emulator_name]} container")
32
- mango_helper.clean_container if mango_helper&.instance_variable_get('@container')
33
35
  end
34
36
 
35
37
  def self.description
36
- "Action that runs Android tasks on a specified Docker image"
38
+ 'Action that runs Android tasks on a specified Docker image'
37
39
  end
38
40
 
39
41
  def self.authors
40
- ["Serghei Moret", "Daniel Hartwich"]
42
+ ['Serghei Moret', 'Daniel Hartwich']
41
43
  end
42
44
 
43
45
  def self.return_value
@@ -50,130 +52,144 @@ module Fastlane
50
52
 
51
53
  def self.details
52
54
  # Optional:
53
- ""
55
+ ''
54
56
  end
55
57
 
56
58
  def self.available_options
57
59
  [
58
60
  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),
61
+ env_name: 'CONTAINER_NAME',
62
+ description: 'Name of the docker container. Will be generated randomly if not defined',
63
+ optional: true,
64
+ type: String),
63
65
 
64
66
  FastlaneCore::ConfigItem.new(key: :no_vnc_port,
65
- env_name: "NO_VNC_PORT",
66
- description: "Port to redirect noVNC. 6080 by default",
67
+ env_name: 'NO_VNC_PORT',
68
+ description: 'Port to redirect noVNC. 6080 by default',
67
69
  default_value: 6080,
68
70
  optional: false,
69
71
  type: Integer),
70
72
 
71
73
  FastlaneCore::ConfigItem.new(key: :device_name,
72
- env_name: "DEVICE_NAME",
73
- description: "Name of the Android device. Nexus 5X by default",
74
+ env_name: 'DEVICE_NAME',
75
+ description: 'Name of the Android device. Nexus 5X by default',
74
76
  default_value: 'Nexus 5X',
75
77
  optional: false,
76
78
  type: String),
77
79
 
78
80
  FastlaneCore::ConfigItem.new(key: :emulator_name,
79
- env_name: "EMULATOR_NAME",
80
- description: "Name of the Android emulator. emulator-5554 by default",
81
+ env_name: 'EMULATOR_NAME',
82
+ description: 'Name of the Android emulator. emulator-5554 by default',
81
83
  default_value: 'emulator-5554',
82
84
  optional: false,
83
85
  type: String),
84
86
 
85
87
  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",
88
+ env_name: 'DOCKER_IMAGE',
89
+ description: 'Name of the Docker image. butomo1989/docker-android-x86-5.1.1 by default',
88
90
  default_value: 'butomo1989/docker-android-x86-5.1.1',
89
91
  optional: false,
90
92
  type: String),
91
93
 
92
94
  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),
95
+ env_name: 'CONTAINER_TIMEOUT',
96
+ description: 'Timeout (in seconds) to get the healthy docker container. 450 (7.5 minutes) by default',
97
+ default_value: 450,
98
+ optional: false,
99
+ type: Integer),
100
+
101
+ FastlaneCore::ConfigItem.new(key: :android_task,
102
+ env_name: 'ANDROID TASK',
103
+ description: 'A generic Android task you want to execute',
104
+ is_string: true,
105
+ optional: false),
104
106
 
105
107
  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",
108
+ env_name: 'SDK_PATH',
109
+ description: 'The path to your Android sdk directory (root). ANDROID_HOME by default',
108
110
  default_value: ENV['ANDROID_HOME'],
109
111
  is_string: true,
110
112
  optional: true),
111
113
 
112
114
  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),
115
+ env_name: 'PORT_FACTOR',
116
+ 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',
117
+ optional: true,
118
+ type: String),
119
+
120
+ FastlaneCore::ConfigItem.new(key: :core_amount,
121
+ env_name: 'CORE_AMOUNT',
122
+ default_value: 0,
123
+ description: 'Define if we want to start docker container with the limitation',
124
+ optional: true,
125
+ type: Integer),
117
126
 
118
127
  FastlaneCore::ConfigItem.new(key: :workspace_dir,
119
- env_name: "WORKSPACE_DIR",
128
+ env_name: 'WORKSPACE_DIR',
120
129
  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`",
130
+ 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
131
  optional: true,
123
132
  type: String),
124
133
 
125
134
  FastlaneCore::ConfigItem.new(key: :maximal_run_time,
126
- env_name: "MAXIMAL_RUN_TIME",
135
+ env_name: 'MAXIMAL_RUN_TIME',
127
136
  default_value: 60,
128
- description: "Defines the maximal time of your test run. Defaults to 60 minutes",
137
+ description: 'Defines the maximal time of your test run. Defaults to 60 minutes',
129
138
  optional: true,
130
139
  type: Integer),
131
140
 
132
141
  FastlaneCore::ConfigItem.new(key: :bundle_install,
133
- env_name: "BUNDLE_INSTALL",
142
+ env_name: 'BUNDLE_INSTALL',
134
143
  default_value: false,
135
- description: "Defines if the Android task must execute bundle install before running a build",
144
+ description: 'Defines if the Android task must execute bundle install before running a build',
136
145
  optional: true,
137
146
  type: Boolean),
138
147
 
139
148
  FastlaneCore::ConfigItem.new(key: :is_running_on_emulator,
140
- env_name: "IS_RUNNING_ON_EMULATOR",
149
+ env_name: 'IS_RUNNING_ON_EMULATOR',
141
150
  default_value: true,
142
- description: "Define if we want to run the emulator in the container",
151
+ description: 'Define if we want to run the emulator in the container',
143
152
  optional: true,
144
153
  type: Boolean),
145
154
 
146
155
  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),
156
+ env_name: 'POST_ACTIONS',
157
+ description: 'Actions that will be executed after the main command has been executed',
158
+ is_string: true,
159
+ optional: true),
151
160
 
152
161
  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),
162
+ env_name: 'PRE_ACTION',
163
+ description: 'Actions that will be executed before the docker image gets pulled',
164
+ is_string: true,
165
+ optional: true),
157
166
 
158
167
  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),
168
+ env_name: 'DOCKER_REGISTRY_LOGIN',
169
+ description: 'Authenticating yourself to a custom Docker registry',
170
+ type: String,
171
+ optional: true),
163
172
 
164
173
  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),
174
+ env_name: 'PULL_LATEST_IMAGE',
175
+ description: 'Define if you want to pull the latest image',
176
+ type: Boolean,
177
+ default_value: false,
178
+ optional: true),
170
179
 
171
180
  FastlaneCore::ConfigItem.new(key: :environment_variables,
172
- env_name: "ENVIRONMENT_VARIABLES",
173
- description: "Comma seperated list of environment variables which are passed into the docker container",
174
- type: Array,
175
- default_value: [],
176
- optional: true)
181
+ env_name: 'ENVIRONMENT_VARIABLES',
182
+ description: 'Comma seperated list of environment variables which are passed into the docker container',
183
+ type: Array,
184
+ default_value: [],
185
+ optional: true),
186
+
187
+ FastlaneCore::ConfigItem.new(key: :vnc_enabled,
188
+ env_name: 'VNC_ENABLED',
189
+ description: 'A bool. True for vnc_enabled False for vnc_disabled',
190
+ type: Boolean,
191
+ default_value: true,
192
+ optional: true)
177
193
  ]
178
194
  end
179
195
  end
@@ -0,0 +1,39 @@
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
+ print_cpu_load(load)
29
+ UI.important('Waiting for available resources..')
30
+ sleep 60
31
+ end
32
+ else
33
+ return true
34
+ end
35
+ raise "CPU was overloaded. Couldn't start emulator"
36
+ end
37
+ end
38
+ end
39
+ 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,35 +10,43 @@ 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 => exception
15
+ prune if exception.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 => exception
38
+ if exception.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
@@ -53,25 +59,10 @@ module Fastlane
53
59
  raise('Cannot execute docker command because the container name is unknown')
54
60
  end
55
61
  end
56
-
62
+
57
63
  def prune
58
64
  Action.sh('docker system prune -f')
59
65
  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
66
  end
76
67
  end
77
- end
68
+ 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
@@ -55,7 +53,7 @@ module Fastlane
55
53
  # it recovers after some time, so wait and retry
56
54
  retry_counter = retry_counter.to_i + 1
57
55
  if retry_counter <= 5
58
- sleep 10*retry_counter
56
+ sleep 10 * retry_counter
59
57
  retry
60
58
  else
61
59
  raise e
@@ -63,4 +61,4 @@ module Fastlane
63
61
  end
64
62
  end
65
63
  end
66
- end
64
+ end
@@ -1,14 +1,12 @@
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, :environment_variables
9
+ attr_reader :container_name, :no_vnc_port, :device_name, :docker_image, :timeout, :port_factor, :maximal_run_time, :sleep_interval, :is_running_on_emulator, :environment_variables, :vnc_enabled, :core_amount
12
10
 
13
11
  def initialize(params)
14
12
  @container_name = params[:container_name]
@@ -18,6 +16,7 @@ module Fastlane
18
16
  @timeout = params[:container_timeout]
19
17
  @sdk_path = params[:sdk_path]
20
18
  @port_factor = params[:port_factor].to_i
19
+ @core_amount = params[:core_amount].to_i
21
20
  @maximal_run_time = params[:maximal_run_time]
22
21
  @sleep_interval = 5
23
22
  @container = nil
@@ -27,7 +26,7 @@ module Fastlane
27
26
  @docker_registry_login = params[:docker_registry_login]
28
27
  @pull_latest_image = params[:pull_latest_image]
29
28
  @environment_variables = params[:environment_variables]
30
-
29
+ @vnc_enabled = params[:vnc_enabled]
31
30
  @docker_commander = DockerCommander.new(container_name)
32
31
  @emulator_commander = EmulatorCommander.new(container_name)
33
32
  end
@@ -41,11 +40,11 @@ module Fastlane
41
40
  assign_unique_vnc_port if port_factor && is_running_on_emulator
42
41
 
43
42
  if container_available?
44
- @container.stop
45
- @container.delete(force: true)
43
+ UI.important('Container was already started. Stopping and removing..')
44
+ @docker_commander.delete_container
46
45
  end
47
46
 
48
- handle_ports_allocation if is_running_on_emulator
47
+ handle_ports_allocation if is_running_on_emulator && vnc_enabled
49
48
 
50
49
  pull_from_registry if @pull_latest_image
51
50
 
@@ -67,13 +66,19 @@ module Fastlane
67
66
 
68
67
  unless container_state
69
68
  UI.important("Will retry to create a healthy docker container after #{sleep_interval} seconds")
70
- @container.stop
71
- @container.delete(force: true)
69
+ @docker_commander.delete_container
72
70
  sleep @sleep_interval
73
71
  create_container
74
72
 
75
73
  unless wait_for_healthy_container
76
74
  UI.important('Container is unhealthy. Exiting..')
75
+ begin
76
+ Actions.sh("docker logs #{container_name} --tail 200")
77
+ Actions.sh("docker exec -i #{container_name} cat /var/log/supervisor/docker-android.stderr.log")
78
+ Actions.sh("docker exec -i #{container_name} cat /var/log/supervisor/supervisord.log")
79
+ rescue StandardError
80
+ # do nothing
81
+ end
77
82
  # We use code "2" as we need something than just standard error code 1, so we can differentiate the next step in CI
78
83
  exit 2
79
84
  end
@@ -101,12 +106,6 @@ module Fastlane
101
106
  @docker_commander.exec(command: 'cat kvm-ok.txt').include?('KVM acceleration can NOT be used')
102
107
  end
103
108
 
104
- # Stops and remove container
105
- def clean_container
106
- @container.stop
107
- @container.delete(force: true)
108
- end
109
-
110
109
  private
111
110
 
112
111
  # Sets path to adb
@@ -117,7 +116,7 @@ module Fastlane
117
116
  # assigns vnc port
118
117
  def assign_unique_vnc_port
119
118
  @no_vnc_port = 6080 + port_factor
120
- @host_ip_address = `hostname -I | head -n1 | awk '{print $1;}'`.delete!("\n")
119
+ @host_ip_address = `hostname -i | head -n1 | awk '{print $1;}'`.delete!("\n")
121
120
  UI.success("Port: #{@no_vnc_port} was chosen for VNC")
122
121
  UI.success("Link to VNC: http://#{@host_ip_address}:#{@no_vnc_port}")
123
122
  end
@@ -125,46 +124,45 @@ module Fastlane
125
124
  # Creates new container using params
126
125
  def create_container
127
126
  UI.important("Creating container: #{container_name}")
128
- print_cpu_load
127
+ CpuLoadHandler.print_cpu_load
129
128
  begin
130
129
  container = create_container_call
131
130
  set_container_name(container)
132
131
  rescue StandardError
133
132
  UI.important("Something went wrong while creating: #{container_name}, will retry in #{@sleep_interval} seconds")
134
- print_cpu_load
135
- @docker_commander.stop_container
133
+ CpuLoadHandler.print_cpu_load
136
134
  @docker_commander.delete_container
137
-
138
135
  sleep @sleep_interval
139
136
  container = create_container_call
140
137
  set_container_name(container)
141
138
  end
142
- get_container_instance(container)
139
+ @container = get_container_instance(container)
140
+
141
+ if @container.nil?
142
+ sleep 3
143
+ @container = get_container_instance(container)
144
+ end
143
145
  end
144
146
 
145
147
  # Gets container instance by container ID
146
148
  def get_container_instance(container)
147
149
  Docker::Container.all(all: true).each do |cont|
148
- if cont.id == container
149
- @container = cont
150
- break
151
- end
150
+ return cont if cont.id == container
152
151
  end
153
152
  end
154
153
 
155
154
  # Call to create a container. We don't use Docker API here, as it doesn't support --privileged.
156
155
  def create_container_call
157
156
  # When CPU is under load we cannot create a healthy container
158
- wait_cpu_to_idle
157
+ CpuLoadHandler.wait_cpu_to_idle
159
158
 
160
159
  additional_env = ''
161
160
  environment_variables.each do |variable|
162
- additional_env = additional_env + " -e #{variable}"
161
+ additional_env += " -e #{variable}"
163
162
  end
164
163
  emulator_args = is_running_on_emulator ? "-p #{no_vnc_port}:6080 -e DEVICE='#{device_name}'" : ''
165
164
  emulator_args = "#{emulator_args}#{additional_env}"
166
-
167
- @docker_commander.start_container(emulator_args: emulator_args, docker_image: docker_image)
165
+ @docker_commander.start_container(emulator_args: emulator_args, docker_image: docker_image, core_amount: core_amount)
168
166
  end
169
167
 
170
168
  def execute_pre_action
@@ -173,6 +171,7 @@ module Fastlane
173
171
 
174
172
  # Pull the docker images before creating a container
175
173
  def pull_from_registry
174
+ UI.important('Pulling the :latest image from the registry')
176
175
  docker_image_name = docker_image.gsub(':latest', '')
177
176
  Actions.sh(@docker_registry_login) if @docker_registry_login
178
177
  @docker_commander.pull_image(docker_image_name: docker_image_name)
@@ -189,7 +188,6 @@ module Fastlane
189
188
  if port_open?('0.0.0.0', @no_vnc_port)
190
189
  UI.important('Something went wrong. VNC port is still busy')
191
190
  sleep @sleep_interval
192
- @docker_commander.stop_container
193
191
  @docker_commander.delete_container
194
192
  end
195
193
  end
@@ -203,10 +201,6 @@ module Fastlane
203
201
  nil
204
202
  end
205
203
 
206
- def print_cpu_load(load = cpu_load)
207
- UI.important("CPU load is: #{load}")
208
- end
209
-
210
204
  # Checks if container is already available
211
205
  def container_available?
212
206
  return false unless container_name
@@ -252,6 +246,9 @@ module Fastlane
252
246
  end
253
247
  UI.important("The Container failed to load after '#{timeout}' seconds timeout. Reason: '#{@container.json['State']['Status']}'")
254
248
  false
249
+ rescue StandardError => e
250
+ puts e
251
+ false
255
252
  end
256
253
 
257
254
  # Checks if port is already openZ
@@ -263,41 +260,12 @@ module Fastlane
263
260
  false
264
261
  end
265
262
 
266
- # Gets load average of Linux machine
267
- def cpu_load
268
- load = `cat /proc/loadavg`
269
- load.split(' ').first.to_f
270
- end
271
-
272
- # Gets amount of the CPU cores
273
- def cpu_core_amount
274
- `cat /proc/cpuinfo | awk '/^processor/{print $3}' | tail -1`
275
- end
276
-
277
- # For half an hour waiting until CPU load average is less than number of cores*2 (which considers that CPU is ready)
278
- # Raises when 30 minutes timeout exceeds
279
- def wait_cpu_to_idle
280
- if OS.linux?
281
- 30.times do
282
- load = cpu_load
283
- return true if load < cpu_core_amount.to_i * 1.5
284
- print_cpu_load(load)
285
- UI.important('Waiting for available resources..')
286
- sleep 60
287
- end
288
- else
289
- return true
290
- end
291
- raise "CPU was overloaded. Couldn't start emulator"
292
- end
293
-
294
263
  # if we do not have container name, we cane use container ID that we got from create call
295
264
  def set_container_name(container)
296
265
  unless container_name
297
266
  @container_name = @emulator_commander.container_name = @docker_commander.container_name = container
298
267
  end
299
268
  end
300
-
301
269
  end
302
270
  end
303
271
  end
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module Mango
3
- VERSION = '1.1.6'.freeze
3
+ VERSION = '1.3.15'.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.6
4
+ version: 1.3.15
5
5
  platform: ruby
6
6
  authors:
7
7
  - Serghei Moret, Daniel Hartwich
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-16 00:00:00.000000000 Z
11
+ date: 2020-07-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: docker-api
@@ -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
@@ -169,8 +170,7 @@ 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
173
+ rubygems_version: 3.0.6
174
174
  signing_key:
175
175
  specification_version: 4
176
176
  summary: This plugin Android tasks on docker images