fastlane-plugin-mango 1.1.2 → 1.3.15

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: 262b7c820c80e2b6d4d36edce1a345f69fe0923ec8bd7fe9de6c425bf12ade03
4
- data.tar.gz: ca27b7a107b1ca9ab9ba84ae9b14a52fffea7f8e65342ee7f600662b439b1da6
3
+ metadata.gz: 789e89cc42d904d6f20d595d4e4e5e536688431cef29839e784e6fbe8dfd7e13
4
+ data.tar.gz: e4143d7a96c169910ec836972f4362b0244828f1899a7837b33911b62f31e7f3
5
5
  SHA512:
6
- metadata.gz: a324bce47acd844dd02f86041d627008c93389b953d3a9ec527f6b6a635257b84b5e72cf14d9c4f7c078b428365184ca370ee6363a45a15687aecbc4f7ba1ec6
7
- data.tar.gz: 3489dd604601c3185aafb09f9004919f1378ad485803cd8c9592d96905ee048c7f9467850a8174d3185236b67814a5e810fb3d2278721a27b1b30453190ff057
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,123 +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),
179
+
180
+ FastlaneCore::ConfigItem.new(key: :environment_variables,
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)
170
193
  ]
171
194
  end
172
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
@@ -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,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
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
@@ -26,7 +25,8 @@ module Fastlane
26
25
  @pre_action = params[:pre_action]
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]
29
+ @vnc_enabled = params[:vnc_enabled]
30
30
  @docker_commander = DockerCommander.new(container_name)
31
31
  @emulator_commander = EmulatorCommander.new(container_name)
32
32
  end
@@ -40,13 +40,11 @@ module Fastlane
40
40
  assign_unique_vnc_port if port_factor && is_running_on_emulator
41
41
 
42
42
  if container_available?
43
- @container.stop
44
- @container.delete(force: true)
43
+ UI.important('Container was already started. Stopping and removing..')
44
+ @docker_commander.delete_container
45
45
  end
46
46
 
47
- handle_ports_allocation if is_running_on_emulator
48
-
49
- execute_pre_action if @pre_action
47
+ handle_ports_allocation if is_running_on_emulator && vnc_enabled
50
48
 
51
49
  pull_from_registry if @pull_latest_image
52
50
 
@@ -67,14 +65,20 @@ module Fastlane
67
65
  end
68
66
 
69
67
  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)
68
+ UI.important("Will retry to create a healthy docker container after #{sleep_interval} seconds")
69
+ @docker_commander.delete_container
73
70
  sleep @sleep_interval
74
71
  create_container
75
72
 
76
73
  unless wait_for_healthy_container
77
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
78
82
  # We use code "2" as we need something than just standard error code 1, so we can differentiate the next step in CI
79
83
  exit 2
80
84
  end
@@ -89,6 +93,8 @@ module Fastlane
89
93
  @emulator_commander.disable_animations
90
94
  @emulator_commander.increase_logcat_storage
91
95
  end
96
+
97
+ execute_pre_action if @pre_action
92
98
  end
93
99
 
94
100
  def kvm_disabled?
@@ -100,12 +106,6 @@ module Fastlane
100
106
  @docker_commander.exec(command: 'cat kvm-ok.txt').include?('KVM acceleration can NOT be used')
101
107
  end
102
108
 
103
- # Stops and remove container
104
- def clean_container
105
- @container.stop
106
- @container.delete(force: true)
107
- end
108
-
109
109
  private
110
110
 
111
111
  # Sets path to adb
@@ -116,7 +116,7 @@ module Fastlane
116
116
  # assigns vnc port
117
117
  def assign_unique_vnc_port
118
118
  @no_vnc_port = 6080 + port_factor
119
- @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")
120
120
  UI.success("Port: #{@no_vnc_port} was chosen for VNC")
121
121
  UI.success("Link to VNC: http://#{@host_ip_address}:#{@no_vnc_port}")
122
122
  end
@@ -124,49 +124,54 @@ module Fastlane
124
124
  # Creates new container using params
125
125
  def create_container
126
126
  UI.important("Creating container: #{container_name}")
127
- print_cpu_load
127
+ CpuLoadHandler.print_cpu_load
128
128
  begin
129
129
  container = create_container_call
130
130
  set_container_name(container)
131
131
  rescue StandardError
132
132
  UI.important("Something went wrong while creating: #{container_name}, will retry in #{@sleep_interval} seconds")
133
- print_cpu_load
134
- @docker_commander.stop_container
133
+ CpuLoadHandler.print_cpu_load
135
134
  @docker_commander.delete_container
136
-
137
135
  sleep @sleep_interval
138
136
  container = create_container_call
139
137
  set_container_name(container)
140
138
  end
141
- 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
142
145
  end
143
146
 
144
147
  # Gets container instance by container ID
145
148
  def get_container_instance(container)
146
149
  Docker::Container.all(all: true).each do |cont|
147
- if cont.id == container
148
- @container = cont
149
- break
150
- end
150
+ return cont if cont.id == container
151
151
  end
152
152
  end
153
153
 
154
154
  # Call to create a container. We don't use Docker API here, as it doesn't support --privileged.
155
155
  def create_container_call
156
156
  # When CPU is under load we cannot create a healthy container
157
- wait_cpu_to_idle
157
+ CpuLoadHandler.wait_cpu_to_idle
158
158
 
159
+ additional_env = ''
160
+ environment_variables.each do |variable|
161
+ additional_env += " -e #{variable}"
162
+ end
159
163
  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)
164
+ emulator_args = "#{emulator_args}#{additional_env}"
165
+ @docker_commander.start_container(emulator_args: emulator_args, docker_image: docker_image, core_amount: core_amount)
162
166
  end
163
167
 
164
168
  def execute_pre_action
165
- Actions.sh(@pre_action)
169
+ @docker_commander.exec(command: @pre_action)
166
170
  end
167
171
 
168
172
  # Pull the docker images before creating a container
169
173
  def pull_from_registry
174
+ UI.important('Pulling the :latest image from the registry')
170
175
  docker_image_name = docker_image.gsub(':latest', '')
171
176
  Actions.sh(@docker_registry_login) if @docker_registry_login
172
177
  @docker_commander.pull_image(docker_image_name: docker_image_name)
@@ -183,7 +188,6 @@ module Fastlane
183
188
  if port_open?('0.0.0.0', @no_vnc_port)
184
189
  UI.important('Something went wrong. VNC port is still busy')
185
190
  sleep @sleep_interval
186
- @docker_commander.stop_container
187
191
  @docker_commander.delete_container
188
192
  end
189
193
  end
@@ -197,10 +201,6 @@ module Fastlane
197
201
  nil
198
202
  end
199
203
 
200
- def print_cpu_load(load = cpu_load)
201
- UI.important("CPU load is: #{load}")
202
- end
203
-
204
204
  # Checks if container is already available
205
205
  def container_available?
206
206
  return false unless container_name
@@ -246,6 +246,9 @@ module Fastlane
246
246
  end
247
247
  UI.important("The Container failed to load after '#{timeout}' seconds timeout. Reason: '#{@container.json['State']['Status']}'")
248
248
  false
249
+ rescue StandardError => e
250
+ puts e
251
+ false
249
252
  end
250
253
 
251
254
  # Checks if port is already openZ
@@ -257,41 +260,12 @@ module Fastlane
257
260
  false
258
261
  end
259
262
 
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
263
  # if we do not have container name, we cane use container ID that we got from create call
289
264
  def set_container_name(container)
290
265
  unless container_name
291
266
  @container_name = @emulator_commander.container_name = @docker_commander.container_name = container
292
267
  end
293
268
  end
294
-
295
269
  end
296
270
  end
297
271
  end
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module Mango
3
- VERSION = '1.1.2'.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.2
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: 2018-09-03 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