fastlane-plugin-upload_to_loadly 1.1.0 → 2.0.0

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: 6a6eae114f64d57c57315cf39bcbdac15af713fe390a965a2568645fccd5f761
4
- data.tar.gz: 92323f470504447d7d8b6149f93e0d50b8e9cd368027d6afd5e614beceac93a4
3
+ metadata.gz: 436b4865c186354b530ffe8d39b953ce5e2e1a1b5182bb4ce7916f4ac791b642
4
+ data.tar.gz: 0f6b59c543ad5630f58509ee9629416d4fd4dc4ceb4e71a8b70f98311ca414e7
5
5
  SHA512:
6
- metadata.gz: f939ddbf1cf42101333cbf0abedd7ce994c38eac085d6cf3c86d77b28528716eacb2309911394adb93eaf3b6d4854659f4cc4d439b94bbee9c1893595d04c57d
7
- data.tar.gz: ffc008aeb5044198b26b9704dee59e903d6e19dfbbab8ffb25ec28a8e2068290f7e09b8ed238686131fbf5e718bce2978658c65eed55663f1608fe8c4803e55c
6
+ metadata.gz: 7d0cf968133de79370e557a008a6580db352da368684ab984635127b12bb5dbac16926b3784aa4a68b2b883dac21ef0caa05b415d5804fca5846ede5765b547b
7
+ data.tar.gz: 07feb7b105b844a15d1f737218bd8545ec0ffa62904ee97384fb3ceb498c394bf441532f617c1f536a7cee3a0b5646203da3a27c476eb0fb50120c51b14157bb
@@ -1,198 +1,207 @@
1
1
  module Fastlane
2
- module Actions
2
+ module Actions
3
3
 
4
- module SharedValues
5
- UPLOADED_FILE_LINK_TO_LOADLY = :UPLOADED_FILE_LINK_TO_LOADLY
6
- QR_CODE_URL_TO_LOADLY = :QR_CODE_URL_TO_LOADLY
7
- SHORTCUT_URL_TO_LOADLY = :SHORTCUT_URL_TO_LOADLY
8
- end
9
-
10
- class UploadToLoadlyAction < Action
11
-
12
- UPLOAD_URL = "https://api.loadly.io/apiv2/app/upload"
13
- LOADLY_FILE_LINK = "https://i.loadly.io"
14
-
15
- def self.run(options)
16
- Actions.verify_gem!('rest-client')
17
- require 'rest-client'
18
- require 'json'
19
-
20
- if options[:file].nil?
21
- UI.important("File didn't come to LOADLY_plugin. Uploading is unavailable.")
22
- return
23
- end
24
-
25
- if options[:api_key].nil?
26
- UI.important("Loadly.io api_key is empty - uploading is unavailable.")
27
- UI.important("Try to upload file by yourself. Path: #{options[:file]}")
28
- return
4
+ module SharedValues
5
+ UPLOADED_FILE_LINK_TO_LOADLY = :UPLOADED_FILE_LINK_TO_LOADLY
6
+ QR_CODE_URL_TO_LOADLY = :QR_CODE_URL_TO_LOADLY
7
+ SHORTCUT_URL_TO_LOADLY = :SHORTCUT_URL_TO_LOADLY
8
+ end
9
+
10
+ class UploadToLoadlyAction < Action
11
+
12
+ UPLOAD_URL = "https://api.loadly.io/apiv2/app/upload"
13
+ LOADLY_FILE_LINK = "https://i.loadly.io"
14
+
15
+ def self.run(options)
16
+ Actions.verify_gem!('rest-client')
17
+ require 'rest-client'
18
+ require 'json'
19
+ require 'thread'
20
+
21
+ if options[:file].nil?
22
+ UI.important("File didn't come to LOADLY_plugin. Uploading is unavailable.")
23
+ return
24
+ end
25
+
26
+ if options[:api_key].nil?
27
+ UI.important("Loadly.io api_key is empty - uploading is unavailable.")
28
+ UI.important("Try to upload file by yourself. Path: #{options[:file]}")
29
+ return
30
+ end
31
+
32
+ file_size = File.size(options[:file])
33
+ file_name = File.basename(options[:file])
34
+
35
+ upload_options = {
36
+ _api_key: options[:api_key],
37
+ buildPassword: options[:build_password],
38
+ buildUpdateDescription: options[:build_description],
39
+ file: File.new(options[:file], 'rb'),
40
+ }
41
+
42
+ timeout = options[:timeout]
43
+
44
+ UI.message("📦 Preparing to upload #{file_name} (#{format_size(file_size)})")
45
+ UI.message("⏳ Initializing upload to Loadly.io...")
46
+
47
+ started_at = Time.now
48
+ spinner_chars = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
49
+ spinner_index = 0
50
+ spinner_running = true
51
+
52
+ # Start the spinner thread
53
+ spinner_thread = Thread.new do
54
+ while spinner_running
55
+ spinner = spinner_chars[spinner_index % spinner_chars.length]
56
+ elapsed = Time.now - started_at
57
+ UI.message("#{spinner} Uploading... (#{format_time(elapsed)})")
58
+ spinner_index += 1
59
+ sleep(0.9)
29
60
  end
30
-
31
- file_size = File.size(options[:file])
32
- file_name = File.basename(options[:file])
33
-
34
- upload_options = {
35
- _api_key: options[:api_key],
36
- buildPassword: options[:build_password],
37
- buildUpdateDescription: options[:build_description],
38
- file: File.new(options[:file], 'rb'),
39
- }
40
-
41
- timeout = options[:timeout]
42
-
43
- UI.message("📦 Preparing to upload #{file_name} (#{format_size(file_size)})")
44
- UI.message("⏳ Initializing upload to Loadly.io...")
45
-
46
- started_at = Time.now
47
- spinner_chars = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
48
- spinner_index = 0
49
-
61
+ end
62
+
63
+ begin
50
64
  response = RestClient::Request.execute(
51
65
  method: :post,
52
66
  url: UPLOAD_URL,
53
67
  timeout: timeout,
54
- payload: upload_options,
55
- block_response: proc { |response|
56
- if Time.now - started_at > spinner_index
57
- spinner_index += 1
58
- spinner = spinner_chars[spinner_index % spinner_chars.length]
59
- elapsed = Time.now - started_at
60
- UI.message("#{spinner} Uploading... (#{format_time(elapsed)})")
61
- end
62
- }
68
+ payload: upload_options
63
69
  )
64
-
65
- begin
66
- response
67
- rescue RestClient::ExceptionWithResponse => error
68
- UI.error("❌ Upload failed!")
69
- UI.important("Failed to upload file to loadly, because of:")
70
- UI.important(error)
71
- UI.important("Try to upload file by yourself. Path: #{options[:file]}")
72
- return
73
- end
74
-
70
+ spinner_running = false
71
+ spinner_thread.join # Wait for spinner to finish
72
+ UI.message("\r ") # Clear spinner line
73
+
75
74
  data = JSON.parse(response.body)['data']
76
-
75
+
77
76
  if data
78
77
  download_url = "#{LOADLY_FILE_LINK}/#{data['buildKey']}"
79
- qr_code_url = "#{LOADLY_FILE_LINK}/#{data['buildQRCodeURL']}"
80
- shortcut_url = data['buildShortcutUrl']
81
-
78
+ qr_code_url = data['buildQRCodeURL']
79
+ shortcut_url = "#{LOADLY_FILE_LINK}/#{data['buildShortcutUrl']}"
80
+
82
81
  Actions.lane_context[SharedValues::UPLOADED_FILE_LINK_TO_LOADLY] = download_url
83
82
  Actions.lane_context[SharedValues::QR_CODE_URL_TO_LOADLY] = qr_code_url
84
83
  Actions.lane_context[SharedValues::SHORTCUT_URL_TO_LOADLY] = shortcut_url
85
-
84
+
86
85
  total_time = Time.now - started_at
87
- UI.success("✅ Upload completed successfully in #{format_time(total_time)}")
86
+ UI.success("✅ Upload completed successfully: #{file_name} (#{format_size(file_size)})")
88
87
  UI.success("📱 Install URLs:")
89
88
  UI.message(" • Download URL: #{download_url}")
90
89
  UI.message(" • Shortcut URL: #{shortcut_url}")
91
90
  UI.message(" • QR Code URL: #{qr_code_url}")
92
-
91
+
93
92
  if !options[:callback_url].nil?
94
93
  data['download_url'] = download_url
95
94
  self.callback(options[:callback_url], data)
96
95
  end
97
-
96
+
98
97
  return
99
- end
100
- end
101
-
102
- def self.format_size(size_in_bytes)
103
- units = ['B', 'KB', 'MB', 'GB']
104
- unit_index = 0
105
- size = size_in_bytes.to_f
106
-
107
- while size > 1024 && unit_index < units.length - 1
108
- size /= 1024
109
- unit_index += 1
110
- end
111
-
112
- "%.2f %s" % [size, units[unit_index]]
113
- end
114
-
115
- def self.format_time(seconds)
116
- if seconds < 60
117
- "#{seconds.round}s"
118
- elsif seconds < 3600
119
- minutes = (seconds / 60).floor
120
- remaining_seconds = (seconds % 60).round
121
- "#{minutes}m #{remaining_seconds}s"
122
98
  else
123
- hours = (seconds / 3600).floor
124
- remaining_minutes = ((seconds % 3600) / 60).floor
125
- "#{hours}h #{remaining_minutes}m"
99
+ UI.error("❌ Upload failed! No response data received.")
126
100
  end
101
+ rescue RestClient::ExceptionWithResponse => error
102
+ spinner_running = false
103
+ spinner_thread.join
104
+ UI.message("\r ") # Clear spinner line
105
+ UI.error("❌ Upload failed!")
106
+ UI.important("Failed to upload file to loadly, because of:")
107
+ UI.important(error.message)
108
+ UI.important("Try to upload file by yourself. Path: #{options[:file]}")
127
109
  end
128
-
129
- def self.callback(url, data)
130
- UI.success("Performing callback to #{url}")
131
- RestClient.post(url, data)
132
- UI.success("Callback successfully")
133
- end
134
-
135
- def self.default_file_path
136
- platform = Actions.lane_context[SharedValues::PLATFORM_NAME]
137
- ios_path = Actions.lane_context[SharedValues::IPA_OUTPUT_PATH]
138
- android_path = Actions.lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH]
139
- return platform == :ios ? ios_path : android_path
140
- end
141
-
142
- def self.available_options
143
- [
144
- FastlaneCore::ConfigItem.new(key: :api_key,
145
- env_name: "LOADLY_API_KEY",
146
- description: "Loadly API Key",
147
- optional: false),
148
- FastlaneCore::ConfigItem.new(key: :file,
149
- env_name: "LOADLY_FILE",
150
- description: "Path to .ipa or .apk file. Default - `IPA_OUTPUT_PATH` or `GRADLE_APK_OUTPUT_PATH` based on platform",
151
- optional: true,
152
- default_value: self.default_file_path),
153
- FastlaneCore::ConfigItem.new(key: :build_password,
154
- env_name: "LOADLY_BUILD_PASSWORD",
155
- description: "Set the App installation password. If the password is empty, public installation is used by default",
156
- optional: true),
157
- FastlaneCore::ConfigItem.new(key: :build_description,
158
- env_name: "LOADLY_BUILD_UPDATE_DESCRIPTION",
159
- description: "Additional information to your users on this build: the comment will be displayed on the installation page",
160
- optional: true),
161
- FastlaneCore::ConfigItem.new(key: :callback_url,
162
- env_name: "LOADLY_CALLBACK_URL",
163
- description: "The URL loadly should call with the result",
164
- optional: true),
165
- FastlaneCore::ConfigItem.new(key: :timeout,
166
- env_name: "LOADLY_TIMEOUT",
167
- description: "Timeout for uploading file to Loadly. Default: 600, range: (60, 1800)",
168
- is_string: false,
169
- optional: true,
170
- default_value: 600),
171
- ]
172
- end
173
-
174
- def self.output
175
- [
176
- ['UPLOADED_FILE_LINK_TO_LOADLY', 'URL to uploaded .ipa or .apk file to loadly.']
177
- ]
178
- end
179
-
180
- def self.description
181
- "Upload .ipa/.apk file to loadly.io"
110
+ end
111
+
112
+ def self.format_size(size_in_bytes)
113
+ units = ['B', 'KB', 'MB', 'GB']
114
+ unit_index = 0
115
+ size = size_in_bytes.to_f
116
+
117
+ while size > 1024 && unit_index < units.length - 1
118
+ size /= 1024
119
+ unit_index += 1
182
120
  end
183
-
184
- def self.authors
185
- ["aliffazfar"]
121
+
122
+ "%.2f %s" % [size, units[unit_index]]
123
+ end
124
+
125
+ def self.format_time(seconds)
126
+ if seconds < 60
127
+ "#{seconds.round}s"
128
+ elsif seconds < 3600
129
+ minutes = (seconds / 60).floor
130
+ remaining_seconds = (seconds % 60).round
131
+ "#{minutes}m #{remaining_seconds}s"
132
+ else
133
+ hours = (seconds / 3600).floor
134
+ remaining_minutes = ((seconds % 3600) / 60).floor
135
+ "#{hours}h #{remaining_minutes}m"
186
136
  end
187
-
188
- def self.details
137
+ end
138
+
139
+ def self.callback(url, data)
140
+ UI.success("Performing callback to #{url}")
141
+ RestClient.post(url, data)
142
+ UI.success("Callback successfully")
143
+ end
144
+
145
+ def self.default_file_path
146
+ platform = Actions.lane_context[SharedValues::PLATFORM_NAME]
147
+ ios_path = Actions.lane_context[SharedValues::IPA_OUTPUT_PATH]
148
+ android_path = Actions.lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH]
149
+ return platform == :ios ? ios_path : android_path
150
+ end
151
+
152
+ def self.available_options
153
+ [
154
+ FastlaneCore::ConfigItem.new(key: :api_key,
155
+ env_name: "LOADLY_API_KEY",
156
+ description: "Loadly API Key",
157
+ optional: false),
158
+ FastlaneCore::ConfigItem.new(key: :file,
159
+ env_name: "LOADLY_FILE",
160
+ description: "Path to .ipa or .apk file. Default - `IPA_OUTPUT_PATH` or `GRADLE_APK_OUTPUT_PATH` based on platform",
161
+ optional: true,
162
+ default_value: self.default_file_path),
163
+ FastlaneCore::ConfigItem.new(key: :build_password,
164
+ env_name: "LOADLY_BUILD_PASSWORD",
165
+ description: "Set the App installation password. If the password is empty, public installation is used by default",
166
+ optional: true),
167
+ FastlaneCore::ConfigItem.new(key: :build_description,
168
+ env_name: "LOADLY_BUILD_UPDATE_DESCRIPTION",
169
+ description: "Additional information to your users on this build: the comment will be displayed on the installation page",
170
+ optional: true),
171
+ FastlaneCore::ConfigItem.new(key: :callback_url,
172
+ env_name: "LOADLY_CALLBACK_URL",
173
+ description: "The URL loadly should call with the result",
174
+ optional: true),
175
+ FastlaneCore::ConfigItem.new(key: :timeout,
176
+ env_name: "LOADLY_TIMEOUT",
177
+ description: "Timeout for uploading file to Loadly. Default: 600, range: (60, 1800)",
178
+ is_string: false,
179
+ optional: true,
180
+ default_value: 600),
181
+ ]
182
+ end
183
+
184
+ def self.output
185
+ [
186
+ ['UPLOADED_FILE_LINK_TO_LOADLY', 'URL to uploaded .ipa or .apk file to loadly.']
187
+ ]
188
+ end
189
+
190
+ def self.description
191
+ "Upload .ipa/.apk file to loadly.io"
192
+ end
193
+
194
+ def self.authors
195
+ ["aliffazfar"]
196
+ end
197
+
198
+ def self.details
189
199
  "This action upload .ipa/.apk file to https://loadly.io and return link to uploaded file."
190
- end
191
-
192
- def self.is_supported?(platform)
193
- [:ios, :android].include?(platform)
194
- end
200
+ end
201
+
202
+ def self.is_supported?(platform)
203
+ [:ios, :android].include?(platform)
195
204
  end
196
205
  end
197
206
  end
198
-
207
+ end
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module UploadToLoadly
3
- VERSION = "1.1.0"
3
+ VERSION = "2.0.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane-plugin-upload_to_loadly
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - aliffazfar