fastlane-plugin-mango 1.1.3 → 1.3.23

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: 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: []