fastlane-plugin-rustore_sdk 0.2.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 +7 -0
- data/LICENSE +21 -0
- data/README.md +52 -0
- data/lib/fastlane/plugin/rustore_sdk/actions/rustore_get_app_version_action.rb +77 -0
- data/lib/fastlane/plugin/rustore_sdk/actions/rustore_get_auth_token_action.rb +85 -0
- data/lib/fastlane/plugin/rustore_sdk/actions/rustore_upload_aab_action.rb +93 -0
- data/lib/fastlane/plugin/rustore_sdk/helper/rustore_sdk_helper.rb +122 -0
- data/lib/fastlane/plugin/rustore_sdk/version.rb +5 -0
- data/lib/fastlane/plugin/rustore_sdk.rb +16 -0
- metadata +50 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 9c1901c7a951647562aad3a8b3413eff18dc1ddbd81141cc762d6511c63567bb
|
|
4
|
+
data.tar.gz: 60d9d10971826b145036139b9bc61cfc57041d6f1b6b11e894087f48e2fcf9a4
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 4394787891241a68beae27cdec392dbf16d5af2e41a98c8624b486b21adbea7352f420fc6467dd6f48e8158388bea589f8a52c434123f0a200ceeea06b9b3118
|
|
7
|
+
data.tar.gz: 58ce079aa6fe56acae30c3d68c54414f63d0a1397935f8001df8b3cf64a5c053f7c6c227da60c6d2c7f302ea19ec5f97d0ee5747ad6aa85eeaf0e47fd64f7819
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 apohodun <apohodun@sdvor.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,52 @@
|
|
|
1
|
+
# rustore_sdk_ plugin
|
|
2
|
+
|
|
3
|
+
[](https://rubygems.org/gems/fastlane-plugin-rustore_sdk_)
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
This project is a [_fastlane_](https://github.com/fastlane/fastlane) plugin. To get started with `fastlane-plugin-rustore_sdk_`, add it to your project by running:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
fastlane add_plugin rustore_sdk_
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## About rustore_sdk_
|
|
14
|
+
|
|
15
|
+
RuStore SDK
|
|
16
|
+
|
|
17
|
+
**Note to author:** Add a more detailed description about this plugin here. If your plugin contains multiple actions, make sure to mention them here.
|
|
18
|
+
|
|
19
|
+
## Example
|
|
20
|
+
|
|
21
|
+
Check out the [example `Fastfile`](fastlane/Fastfile) to see how to use this plugin. Try it by cloning the repo, running `fastlane install_plugins` and `bundle exec fastlane test`.
|
|
22
|
+
|
|
23
|
+
**Note to author:** Please set up a sample project to make it easy for users to explore what your plugin does. Provide everything that is necessary to try out the plugin in this project (including a sample Xcode/Android project if necessary)
|
|
24
|
+
|
|
25
|
+
## Run tests for this plugin
|
|
26
|
+
|
|
27
|
+
To run both the tests, and code style validation, run
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
rake
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
To automatically fix many of the styling issues, use
|
|
34
|
+
```
|
|
35
|
+
rubocop -a
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Issues and Feedback
|
|
39
|
+
|
|
40
|
+
For any other issues and feedback about this plugin, please submit it to this repository.
|
|
41
|
+
|
|
42
|
+
## Troubleshooting
|
|
43
|
+
|
|
44
|
+
If you have trouble using plugins, check out the [Plugins Troubleshooting](https://docs.fastlane.tools/plugins/plugins-troubleshooting/) guide.
|
|
45
|
+
|
|
46
|
+
## Using _fastlane_ Plugins
|
|
47
|
+
|
|
48
|
+
For more information about how the `fastlane` plugin system works, check out the [Plugins documentation](https://docs.fastlane.tools/plugins/create-plugin/).
|
|
49
|
+
|
|
50
|
+
## About _fastlane_
|
|
51
|
+
|
|
52
|
+
_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,77 @@
|
|
|
1
|
+
require 'fastlane/action'
|
|
2
|
+
require_relative '../helper/rustore_sdk_helper'
|
|
3
|
+
|
|
4
|
+
module Fastlane
|
|
5
|
+
module Actions
|
|
6
|
+
class RustoreGetAppVersionAction < Action
|
|
7
|
+
def self.run(params)
|
|
8
|
+
package_name = params[:package_name]
|
|
9
|
+
status = params[:status]
|
|
10
|
+
testing_type = params[:testing_type]
|
|
11
|
+
token = params[:auth_token] || Actions.lane_context[SharedValues::RUSTORE_AUTH_TOKEN]
|
|
12
|
+
|
|
13
|
+
UI.user_error!("No auth token found. Run 'rustore_get_auth_token' first or provide 'auth_token'") unless token
|
|
14
|
+
|
|
15
|
+
UI.message("Fetching app version (#{status}/#{testing_type}) for #{package_name}...")
|
|
16
|
+
version_info = Helper::RustoreSdkHelper.get_app_version(
|
|
17
|
+
token: token,
|
|
18
|
+
package_name: package_name,
|
|
19
|
+
status: status,
|
|
20
|
+
testing_type: testing_type
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
if version_info
|
|
24
|
+
UI.success("Found version: #{version_info['versionName']} (#{version_info['versionCode']}) with status #{version_info['versionStatus']}")
|
|
25
|
+
return version_info
|
|
26
|
+
else
|
|
27
|
+
UI.important("No version found with status #{status} and type #{testing_type}")
|
|
28
|
+
return nil
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.description
|
|
33
|
+
"Get app version information from RuStore with filters"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.available_options
|
|
37
|
+
[
|
|
38
|
+
FastlaneCore::ConfigItem.new(key: :package_name,
|
|
39
|
+
env_name: "RUSTORE_PACKAGE_NAME",
|
|
40
|
+
description: "Android package name",
|
|
41
|
+
default_value: ENV['PACKAGE_NAME'] || ENV['APP_IDENTIFIER'] || CredentialsManager::AppfileConfig.try_fetch_value(:package_name) || CredentialsManager::AppfileConfig.try_fetch_value(:app_identifier),
|
|
42
|
+
optional: false,
|
|
43
|
+
type: String),
|
|
44
|
+
FastlaneCore::ConfigItem.new(key: :status,
|
|
45
|
+
env_name: "RUSTORE_VERSION_STATUS",
|
|
46
|
+
description: "Filter by version status (DRAFT, MODERATION, ACTIVE, REJECTED_BY_MODERATOR, APPROVED, READY_FOR_PUBLICATION)",
|
|
47
|
+
default_value: "ACTIVE",
|
|
48
|
+
optional: true,
|
|
49
|
+
type: String,
|
|
50
|
+
verify_block: proc do |value|
|
|
51
|
+
allowed = ['DRAFT', 'MODERATION', 'ACTIVE', 'REJECTED_BY_MODERATOR', 'APPROVED', 'READY_FOR_PUBLICATION', 'TAKEN_FOR_MODERATION']
|
|
52
|
+
UI.user_error!("Invalid status: #{value}. Allowed: #{allowed.join(', ')}") unless allowed.include?(value)
|
|
53
|
+
end),
|
|
54
|
+
FastlaneCore::ConfigItem.new(key: :testing_type,
|
|
55
|
+
env_name: "RUSTORE_TESTING_TYPE",
|
|
56
|
+
description: "Filter by testing type (RELEASE, ALPHA)",
|
|
57
|
+
default_value: "RELEASE",
|
|
58
|
+
optional: true,
|
|
59
|
+
type: String),
|
|
60
|
+
FastlaneCore::ConfigItem.new(key: :auth_token,
|
|
61
|
+
env_name: "RUSTORE_AUTH_TOKEN",
|
|
62
|
+
description: "RuStore Auth Token (JWE)",
|
|
63
|
+
optional: true,
|
|
64
|
+
type: String)
|
|
65
|
+
]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def self.return_value
|
|
69
|
+
"A hash containing version information (versionName, versionCode, versionStatus, etc.)"
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def self.is_supported?(platform)
|
|
73
|
+
[:android].include?(platform)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
require 'fastlane/action'
|
|
2
|
+
require_relative '../helper/rustore_sdk_helper'
|
|
3
|
+
|
|
4
|
+
module Fastlane
|
|
5
|
+
module Actions
|
|
6
|
+
module SharedValues
|
|
7
|
+
RUSTORE_AUTH_TOKEN = :RUSTORE_AUTH_TOKEN
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class RustoreGetAuthTokenAction < Action
|
|
11
|
+
def self.run(params)
|
|
12
|
+
key_id = params[:key_id]
|
|
13
|
+
private_key_path = params[:private_key_path]
|
|
14
|
+
private_key_data = params[:private_key_data]
|
|
15
|
+
|
|
16
|
+
UI.message("RuStore Auth Config:")
|
|
17
|
+
UI.message(" Key ID: #{key_id[0..3]}***")
|
|
18
|
+
UI.message(" Private Key Path: #{private_key_path}") if private_key_path
|
|
19
|
+
UI.message(" Private Key Data: [PROVIDED]") if private_key_data
|
|
20
|
+
|
|
21
|
+
UI.user_error!("You must provide either 'private_key_path' or 'private_key_data' (or set RUSTORE_PRIVATE_KEY_PATH / RUSTORE_PRIVATE_KEY_DATA env vars)") if private_key_path.nil? && private_key_data.nil?
|
|
22
|
+
|
|
23
|
+
UI.message("Fetching auth token from RuStore...")
|
|
24
|
+
token = Helper::RustoreSdkHelper.get_auth_token(
|
|
25
|
+
key_id: key_id,
|
|
26
|
+
private_key_path: private_key_path,
|
|
27
|
+
private_key_data: private_key_data
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
UI.success("Successfully obtained RuStore auth token")
|
|
31
|
+
|
|
32
|
+
# Save token in shared_values for use in other actions
|
|
33
|
+
Actions.lane_context[SharedValues::RUSTORE_AUTH_TOKEN] = token
|
|
34
|
+
token
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.description
|
|
38
|
+
"Get RuStore Auth Token using RSA private key"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.authors
|
|
42
|
+
["apohodun"]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def self.return_value
|
|
46
|
+
"The RuStore Auth Token (JWE)"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def self.available_options
|
|
50
|
+
[
|
|
51
|
+
FastlaneCore::ConfigItem.new(key: :key_id,
|
|
52
|
+
env_name: "RUSTORE_KEY_ID",
|
|
53
|
+
description: "The ID of the private key from RuStore Console",
|
|
54
|
+
default_value: ENV['RUSTORE_KEY_ID'] || CredentialsManager::AppfileConfig.try_fetch_value(:rustore_key_id),
|
|
55
|
+
optional: false,
|
|
56
|
+
type: String),
|
|
57
|
+
FastlaneCore::ConfigItem.new(key: :private_key_path,
|
|
58
|
+
env_name: "RUSTORE_PRIVATE_KEY_PATH",
|
|
59
|
+
description: "Path to the RSA private key (.pem) file",
|
|
60
|
+
default_value: ENV['RUSTORE_PRIVATE_KEY_PATH'] || CredentialsManager::AppfileConfig.try_fetch_value(:rustore_private_key_path),
|
|
61
|
+
optional: true,
|
|
62
|
+
type: String,
|
|
63
|
+
conflicting_options: [:private_key_data]),
|
|
64
|
+
FastlaneCore::ConfigItem.new(key: :private_key_data,
|
|
65
|
+
env_name: "RUSTORE_PRIVATE_KEY_DATA",
|
|
66
|
+
description: "The content of the RSA private key (.pem)",
|
|
67
|
+
optional: true,
|
|
68
|
+
type: String,
|
|
69
|
+
sensitive: true,
|
|
70
|
+
conflicting_options: [:private_key_path])
|
|
71
|
+
]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def self.output
|
|
75
|
+
[
|
|
76
|
+
['RUSTORE_AUTH_TOKEN', 'The RuStore Auth Token']
|
|
77
|
+
]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def self.is_supported?(platform)
|
|
81
|
+
[:android].include?(platform)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
require 'fastlane/action'
|
|
2
|
+
require_relative '../helper/rustore_sdk_helper'
|
|
3
|
+
|
|
4
|
+
module Fastlane
|
|
5
|
+
module Actions
|
|
6
|
+
class RustoreUploadAabAction < Action
|
|
7
|
+
def self.run(params)
|
|
8
|
+
package_name = params[:package_name]
|
|
9
|
+
aab_path = params[:aab_path]
|
|
10
|
+
version_name = params[:version_name]
|
|
11
|
+
submit = params[:submit]
|
|
12
|
+
token = params[:auth_token] || Actions.lane_context[SharedValues::RUSTORE_AUTH_TOKEN]
|
|
13
|
+
|
|
14
|
+
UI.user_error!("No auth token found. Run 'rustore_get_auth_token' first or provide 'auth_token'") unless token
|
|
15
|
+
UI.user_error!("AAB file not found at path: #{aab_path}") unless File.exist?(aab_path)
|
|
16
|
+
|
|
17
|
+
# 1. Create a draft
|
|
18
|
+
UI.message("Creating draft version #{version_name} for #{package_name}...")
|
|
19
|
+
version_id = Helper::RustoreSdkHelper.create_draft(
|
|
20
|
+
token: token,
|
|
21
|
+
package_name: package_name,
|
|
22
|
+
version_number: version_name
|
|
23
|
+
)
|
|
24
|
+
UI.success("Draft created with ID: #{version_id}")
|
|
25
|
+
|
|
26
|
+
# 2. Upload AAB
|
|
27
|
+
UI.message("Uploading AAB file: #{aab_path}...")
|
|
28
|
+
Helper::RustoreSdkHelper.upload_aab(
|
|
29
|
+
token: token,
|
|
30
|
+
package_name: package_name,
|
|
31
|
+
version_id: version_id,
|
|
32
|
+
aab_path: aab_path
|
|
33
|
+
)
|
|
34
|
+
UI.success("AAB uploaded successfully")
|
|
35
|
+
|
|
36
|
+
# 3. Submit for moderation (if required)
|
|
37
|
+
if submit
|
|
38
|
+
UI.message("Submitting version #{version_id} for moderation...")
|
|
39
|
+
Helper::RustoreSdkHelper.submit_version(
|
|
40
|
+
token: token,
|
|
41
|
+
package_name: package_name,
|
|
42
|
+
version_id: version_id
|
|
43
|
+
)
|
|
44
|
+
UI.success("Version submitted for moderation!")
|
|
45
|
+
else
|
|
46
|
+
UI.important("Version remains in DRAFT state. You need to submit it manually or set 'submit: true'")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
version_id
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def self.description
|
|
53
|
+
"Upload AAB to RuStore and optionally submit for moderation"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def self.available_options
|
|
57
|
+
[
|
|
58
|
+
FastlaneCore::ConfigItem.new(key: :package_name,
|
|
59
|
+
env_name: "RUSTORE_PACKAGE_NAME",
|
|
60
|
+
description: "Android package name",
|
|
61
|
+
default_value: ENV['PACKAGE_NAME'] || ENV['APP_IDENTIFIER'] || CredentialsManager::AppfileConfig.try_fetch_value(:package_name) || CredentialsManager::AppfileConfig.try_fetch_value(:app_identifier),
|
|
62
|
+
optional: false,
|
|
63
|
+
type: String),
|
|
64
|
+
FastlaneCore::ConfigItem.new(key: :aab_path,
|
|
65
|
+
env_name: "RUSTORE_AAB_PATH",
|
|
66
|
+
description: "Path to the .aab file",
|
|
67
|
+
optional: false,
|
|
68
|
+
type: String),
|
|
69
|
+
FastlaneCore::ConfigItem.new(key: :version_name,
|
|
70
|
+
env_name: "RUSTORE_VERSION_NAME",
|
|
71
|
+
description: "Version name (e.g. 1.0.0)",
|
|
72
|
+
optional: false,
|
|
73
|
+
type: String),
|
|
74
|
+
FastlaneCore::ConfigItem.new(key: :auth_token,
|
|
75
|
+
env_name: "RUSTORE_AUTH_TOKEN",
|
|
76
|
+
description: "RuStore Auth Token (JWE)",
|
|
77
|
+
optional: true,
|
|
78
|
+
type: String),
|
|
79
|
+
FastlaneCore::ConfigItem.new(key: :submit,
|
|
80
|
+
env_name: "RUSTORE_SUBMIT",
|
|
81
|
+
description: "Should the version be submitted for moderation immediately?",
|
|
82
|
+
optional: true,
|
|
83
|
+
default_value: true,
|
|
84
|
+
type: Boolean)
|
|
85
|
+
]
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def self.is_supported?(platform)
|
|
89
|
+
[:android].include?(platform)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
require 'fastlane_core/ui/ui'
|
|
2
|
+
require 'openssl'
|
|
3
|
+
require 'base64'
|
|
4
|
+
require 'net/http'
|
|
5
|
+
require 'json'
|
|
6
|
+
require 'time'
|
|
7
|
+
|
|
8
|
+
module Fastlane
|
|
9
|
+
UI = FastlaneCore::UI unless Fastlane.const_defined?(:UI)
|
|
10
|
+
|
|
11
|
+
module Helper
|
|
12
|
+
class RustoreSdkHelper
|
|
13
|
+
BASE_URL = 'https://public-api.rustore.ru/public'
|
|
14
|
+
|
|
15
|
+
def self.get_auth_token(key_id:, private_key_path: nil, private_key_data: nil)
|
|
16
|
+
key_content = if private_key_data
|
|
17
|
+
private_key_data
|
|
18
|
+
elsif private_key_path
|
|
19
|
+
UI.user_error!("Private key file not found at: #{private_key_path}") unless File.exist?(private_key_path)
|
|
20
|
+
File.read(private_key_path)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
UI.user_error!("No private key provided. Set RUSTORE_PRIVATE_KEY_PATH or RUSTORE_PRIVATE_KEY_DATA") if key_content.nil? || key_content.empty?
|
|
24
|
+
|
|
25
|
+
unless key_content.include?("-----BEGIN")
|
|
26
|
+
clean_key = key_content.gsub(/\s+/, "")
|
|
27
|
+
key_content = "-----BEGIN PRIVATE KEY-----\n#{clean_key.scan(/.{1,64}/).join("\n")}\n-----END PRIVATE KEY-----"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
rsa_key = OpenSSL::PKey.read(key_content)
|
|
31
|
+
timestamp = Time.now.iso8601(3)
|
|
32
|
+
data_to_sign = "#{key_id}#{timestamp}"
|
|
33
|
+
signature = Base64.strict_encode64(rsa_key.sign(OpenSSL::Digest::SHA512.new, data_to_sign))
|
|
34
|
+
|
|
35
|
+
uri = URI("#{BASE_URL}/auth/")
|
|
36
|
+
request = Net::HTTP::Post.new(uri, { 'Content-Type' => 'application/json' })
|
|
37
|
+
request.body = { keyId: key_id, timestamp: timestamp, signature: signature }.to_json
|
|
38
|
+
|
|
39
|
+
response = perform_request(uri, request)
|
|
40
|
+
handle_response(response) { |b| b['body']['jwe'] }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.get_app_version(token:, package_name:, status: 'ACTIVE', testing_type: 'RELEASE')
|
|
44
|
+
query = "versionStatuses=#{status}&filterTestingType=#{testing_type}"
|
|
45
|
+
uri = URI("#{BASE_URL}/v1/application/#{package_name}/version?#{query}")
|
|
46
|
+
|
|
47
|
+
request = Net::HTTP::Get.new(uri)
|
|
48
|
+
request['Public-Token'] = token
|
|
49
|
+
|
|
50
|
+
response = perform_request(uri, request)
|
|
51
|
+
handle_response(response) do |b|
|
|
52
|
+
versions = b['body']['content']
|
|
53
|
+
versions.first if versions && !versions.empty?
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def self.create_draft(token:, package_name:, version_number: nil, whats_new: "Internal update")
|
|
58
|
+
uri = URI("#{BASE_URL}/v1/application/#{package_name}/version")
|
|
59
|
+
request = Net::HTTP::Post.new(uri, { 'Content-Type' => 'application/json', 'Public-Token' => token })
|
|
60
|
+
|
|
61
|
+
body = { whatsNew: whats_new }
|
|
62
|
+
body[:versionName] = version_number if version_number
|
|
63
|
+
request.body = body.to_json
|
|
64
|
+
|
|
65
|
+
response = perform_request(uri, request)
|
|
66
|
+
handle_response(response) { |b| b['body'] } # Returns versionId
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def self.upload_aab(token:, package_name:, version_id:, aab_path:)
|
|
70
|
+
uri = URI("#{BASE_URL}/v1/application/#{package_name}/version/#{version_id}/aab")
|
|
71
|
+
|
|
72
|
+
command = [
|
|
73
|
+
"curl -s -X POST '#{uri}'",
|
|
74
|
+
"-H 'Public-Token: #{token}'",
|
|
75
|
+
"-F 'file=@\"#{aab_path}\"'"
|
|
76
|
+
].join(" ")
|
|
77
|
+
|
|
78
|
+
result = `#{command}`
|
|
79
|
+
begin
|
|
80
|
+
body = JSON.parse(result)
|
|
81
|
+
if body['code'] == 'OK'
|
|
82
|
+
return true
|
|
83
|
+
else
|
|
84
|
+
UI.user_error!("RuStore upload error: #{body['message']}")
|
|
85
|
+
end
|
|
86
|
+
rescue JSON::ParserError
|
|
87
|
+
UI.user_error!("Failed to parse RuStore API response: #{result}")
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def self.submit_version(token:, package_name:, version_id:)
|
|
92
|
+
uri = URI("#{BASE_URL}/v1/application/#{package_name}/version/#{version_id}/submit")
|
|
93
|
+
request = Net::HTTP::Post.new(uri, { 'Public-Token' => token })
|
|
94
|
+
|
|
95
|
+
response = perform_request(uri, request)
|
|
96
|
+
handle_response(response) { true }
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
private
|
|
100
|
+
|
|
101
|
+
def self.perform_request(uri, request)
|
|
102
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
103
|
+
http.use_ssl = true
|
|
104
|
+
http.request(request)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def self.handle_response(response)
|
|
108
|
+
case response
|
|
109
|
+
when Net::HTTPSuccess
|
|
110
|
+
body = JSON.parse(response.body)
|
|
111
|
+
if body['code'] == 'OK'
|
|
112
|
+
yield(body)
|
|
113
|
+
else
|
|
114
|
+
UI.user_error!("RuStore API error: #{body['message']}")
|
|
115
|
+
end
|
|
116
|
+
else
|
|
117
|
+
UI.user_error!("HTTP error: #{response.code} #{response.message}\n#{response.body}")
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require 'fastlane/plugin/rustore_sdk/version'
|
|
2
|
+
|
|
3
|
+
module Fastlane
|
|
4
|
+
module RustoreSdk
|
|
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::RustoreSdk.all_classes.each do |current|
|
|
15
|
+
require current
|
|
16
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: fastlane-plugin-rustore_sdk
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.2.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- karbunkul
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-05-20 00:00:00.000000000 Z
|
|
12
|
+
dependencies: []
|
|
13
|
+
description:
|
|
14
|
+
email: apokhodyun@gmail.com
|
|
15
|
+
executables: []
|
|
16
|
+
extensions: []
|
|
17
|
+
extra_rdoc_files: []
|
|
18
|
+
files:
|
|
19
|
+
- LICENSE
|
|
20
|
+
- README.md
|
|
21
|
+
- lib/fastlane/plugin/rustore_sdk.rb
|
|
22
|
+
- lib/fastlane/plugin/rustore_sdk/actions/rustore_get_app_version_action.rb
|
|
23
|
+
- lib/fastlane/plugin/rustore_sdk/actions/rustore_get_auth_token_action.rb
|
|
24
|
+
- lib/fastlane/plugin/rustore_sdk/actions/rustore_upload_aab_action.rb
|
|
25
|
+
- lib/fastlane/plugin/rustore_sdk/helper/rustore_sdk_helper.rb
|
|
26
|
+
- lib/fastlane/plugin/rustore_sdk/version.rb
|
|
27
|
+
homepage: https://github.com/karbunkul/fastlane-plugin-rustore_sdk
|
|
28
|
+
licenses:
|
|
29
|
+
- MIT
|
|
30
|
+
metadata: {}
|
|
31
|
+
post_install_message:
|
|
32
|
+
rdoc_options: []
|
|
33
|
+
require_paths:
|
|
34
|
+
- lib
|
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '2.6'
|
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
41
|
+
requirements:
|
|
42
|
+
- - ">="
|
|
43
|
+
- !ruby/object:Gem::Version
|
|
44
|
+
version: '0'
|
|
45
|
+
requirements: []
|
|
46
|
+
rubygems_version: 3.5.21
|
|
47
|
+
signing_key:
|
|
48
|
+
specification_version: 4
|
|
49
|
+
summary: RuStore SDK
|
|
50
|
+
test_files: []
|