fastlane-plugin-upload_to_loadly 1.1.0 → 2.0.0

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