fastlane-plugin-upload_to_loadly 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6a6eae114f64d57c57315cf39bcbdac15af713fe390a965a2568645fccd5f761
4
+ data.tar.gz: 92323f470504447d7d8b6149f93e0d50b8e9cd368027d6afd5e614beceac93a4
5
+ SHA512:
6
+ metadata.gz: f939ddbf1cf42101333cbf0abedd7ce994c38eac085d6cf3c86d77b28528716eacb2309911394adb93eaf3b6d4854659f4cc4d439b94bbee9c1893595d04c57d
7
+ data.tar.gz: ffc008aeb5044198b26b9704dee59e903d6e19dfbbab8ffb25ec28a8e2068290f7e09b8ed238686131fbf5e718bce2978658c65eed55663f1608fe8c4803e55c
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 aliffazfar <aliffazfar34@gmail.com>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # Fastlane plugin upload_to_loadly
2
+
3
+ [![fastlane Plugin Badge](https://rawcdn.githack.com/fastlane/fastlane/master/fastlane/assets/plugin-badge.svg)](https://rubygems.org/gems/fastlane-plugin-loadlyio)
4
+
5
+ ## Getting Started
6
+
7
+ This project is a [_fastlane_](https://github.com/fastlane/fastlane) plugin. To get started with `fastlane-plugin-upload_to_loadly`, add it to your project by running:
8
+
9
+ ```bash
10
+ fastlane add_plugin upload_to_loadly
11
+ ```
12
+
13
+ Or you can add it directly on your Pluginfile
14
+
15
+ ```ruby
16
+ gem "fastlane-plugin-upload_to_loadly", git: "https://github.com/aliffazfar/fastlane-plugin-loadlyio"
17
+ ```
18
+
19
+ ## About upload_to_loadly
20
+
21
+ Loadly.io is the ultimate platform for app beta testing and distribution, offering unlimited app uploads and downloads, enhanced security, detailed analytics, and seamless integration. Alternative to TestFlight and Diawi
22
+
23
+ This plugin can upload .ipa and .apk file to Loadly.
24
+
25
+ ## Available options
26
+
27
+ | Key | Required | Type | Description |
28
+ | --------------------- | ---------- | -------- | ---------------------------------------------------------------------------------------------------------- |
29
+ | **api_key** | **`true`** | `String` | [Loadly API Key](https://loadly.io/doc/view/api) |
30
+ | **file** | `true` | `String` | Path to .ipa or .apk file.<br>**Default**: `IPA_OUTPUT_PATH` or `GRADLE_APK_OUTPUT_PATH` based on platform |
31
+ | **build_password** | `false` | `String` | Set the App installation password. If the password is empty, public installation is used by default |
32
+ | **build_description** | `false` | `String` | Additional information to your users on this build: the comment will be displayed on the installation page |
33
+ | **callback_url** | `false` | `String` | The URL loadly should call with the result |
34
+ | **timeout** | `false` | `Int` | Timeout for uploading file to Loadly.<br>**Default**: 600<br>**Range**: (60, 1800) |
35
+
36
+ ## Result link
37
+
38
+ If file upload successfully, you can access result link by:
39
+
40
+ `lane_context[SharedValues::UPLOADED_FILE_LINK_TO_LOADLY]`
41
+ `lane_context[SharedValues::QR_CODE_URL_TO_LOADLY]`
42
+ `lane_context[SharedValues::SHORTCUT_URL_TO_LOADLY]`
43
+
44
+ ## Example
45
+
46
+ Minimal plugin configuration is:
47
+
48
+ ```ruby
49
+ upload_to_loadly(
50
+ api_key: "your_api_key",
51
+ file: "your_app_file_path",
52
+ )
53
+ ```
54
+
55
+ Advanced usage with all available options
56
+
57
+ ```ruby
58
+ upload_to_loadly(
59
+ api_key: ENV["LOADLY_API_KEY"],
60
+ file: "./build/YourApp.ipa",
61
+ build_password: "optional_password",
62
+ build_description: "New version with feature X and Y",
63
+ callback_url: "https://your-server.com/callback",
64
+ timeout: 900 # Custom timeout in seconds (60-1800)
65
+ )
66
+ ```
67
+
68
+ For more options see [**Available options**](#available-options) section.
69
+
70
+ ## Issues and Feedback
71
+
72
+ For any other issues and feedback about this plugin, please submit it to this repository.
73
+
74
+ ## Troubleshooting
75
+
76
+ If you have trouble using plugins, check out the [Plugins Troubleshooting](https://docs.fastlane.tools/plugins/plugins-troubleshooting/) guide.
77
+
78
+ ## Using _fastlane_ Plugins
79
+
80
+ For more information about how the `fastlane` plugin system works, check out the [Plugins documentation](https://docs.fastlane.tools/plugins/create-plugin/).
81
+
82
+ ## About _fastlane_
83
+
84
+ _fastlane_ is the easiest way to automate beta deployments and releases for your iOS and Android apps. To learn more, check out [fastlane.tools](https://fastlane.tools).
@@ -0,0 +1,198 @@
1
+ module Fastlane
2
+ module Actions
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
29
+ 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
+
50
+ response = RestClient::Request.execute(
51
+ method: :post,
52
+ url: UPLOAD_URL,
53
+ 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
+ }
63
+ )
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
+
75
+ data = JSON.parse(response.body)['data']
76
+
77
+ if data
78
+ download_url = "#{LOADLY_FILE_LINK}/#{data['buildKey']}"
79
+ qr_code_url = "#{LOADLY_FILE_LINK}/#{data['buildQRCodeURL']}"
80
+ shortcut_url = data['buildShortcutUrl']
81
+
82
+ Actions.lane_context[SharedValues::UPLOADED_FILE_LINK_TO_LOADLY] = download_url
83
+ Actions.lane_context[SharedValues::QR_CODE_URL_TO_LOADLY] = qr_code_url
84
+ Actions.lane_context[SharedValues::SHORTCUT_URL_TO_LOADLY] = shortcut_url
85
+
86
+ total_time = Time.now - started_at
87
+ UI.success("✅ Upload completed successfully in #{format_time(total_time)}")
88
+ UI.success("📱 Install URLs:")
89
+ UI.message(" • Download URL: #{download_url}")
90
+ UI.message(" • Shortcut URL: #{shortcut_url}")
91
+ UI.message(" • QR Code URL: #{qr_code_url}")
92
+
93
+ if !options[:callback_url].nil?
94
+ data['download_url'] = download_url
95
+ self.callback(options[:callback_url], data)
96
+ end
97
+
98
+ 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
+ else
123
+ hours = (seconds / 3600).floor
124
+ remaining_minutes = ((seconds % 3600) / 60).floor
125
+ "#{hours}h #{remaining_minutes}m"
126
+ end
127
+ 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"
182
+ end
183
+
184
+ def self.authors
185
+ ["aliffazfar"]
186
+ end
187
+
188
+ def self.details
189
+ "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
195
+ end
196
+ end
197
+ end
198
+
@@ -0,0 +1,16 @@
1
+ require 'fastlane_core/ui/ui'
2
+
3
+ module Fastlane
4
+ UI = FastlaneCore::UI unless Fastlane.const_defined?(:UI)
5
+
6
+ module Helper
7
+ class LoadlyioHelper
8
+ # class methods that you define here become available in your action
9
+ # as `Helper::LoadlyioHelper.your_method`
10
+ #
11
+ def self.show_message
12
+ UI.message("Hello from the loadlyio plugin helper!")
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,5 @@
1
+ module Fastlane
2
+ module UploadToLoadly
3
+ VERSION = "1.1.0"
4
+ end
5
+ end
@@ -0,0 +1,16 @@
1
+ require 'fastlane/plugin/upload_to_loadly/version'
2
+
3
+ module Fastlane
4
+ module UploadToLoadly
5
+ # Return all .rb files inside the "actions" and "helper" directory
6
+ def self.all_classes
7
+ Dir[File.expand_path('**/{actions,helper}/*.rb', File.dirname(__FILE__))]
8
+ end
9
+ end
10
+ end
11
+
12
+ # By default we want to import all available actions and helpers
13
+ # A plugin can contain any number of actions and plugins
14
+ Fastlane::UploadToLoadly.all_classes.each do |current|
15
+ require current
16
+ end
metadata ADDED
@@ -0,0 +1,149 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fastlane-plugin-upload_to_loadly
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ platform: ruby
6
+ authors:
7
+ - aliffazfar
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2024-11-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rest-client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 2.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 2.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: pry
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: fastlane
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 1.93.0
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 1.93.0
111
+ description:
112
+ email: aliffazfar34@gmail.com
113
+ executables: []
114
+ extensions: []
115
+ extra_rdoc_files: []
116
+ files:
117
+ - LICENSE
118
+ - README.md
119
+ - lib/fastlane/plugin/upload_to_loadly.rb
120
+ - lib/fastlane/plugin/upload_to_loadly/actions/upload_to_loadly_action.rb
121
+ - lib/fastlane/plugin/upload_to_loadly/helper/upload_to_loadly_helper.rb
122
+ - lib/fastlane/plugin/upload_to_loadly/version.rb
123
+ homepage: https://github.com/aliffazfar/fastlane-plugin-loadlyio
124
+ licenses:
125
+ - MIT
126
+ metadata:
127
+ rubygems_mfa_required: 'true'
128
+ post_install_message:
129
+ rdoc_options: []
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ requirements: []
143
+ rubygems_version: 3.1.6
144
+ signing_key:
145
+ specification_version: 4
146
+ summary: Loadly.io is the ultimate platform for app beta testing and distribution,
147
+ offering unlimited app uploads and downloads, enhanced security, detailed analytics,
148
+ and seamless integration. Alternative to TestFlight and Diawi
149
+ test_files: []