fastlane-plugin-upload_to_ru_store 1.0.2

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 188a6a5731e82ab480b88165bcd3d34e6bcdb6fa237b3516a32e1d642f24a25b
4
+ data.tar.gz: bdc3ac1405edb623d3aba986da974580f7eca7ea940968b44185ffb5eec62173
5
+ SHA512:
6
+ metadata.gz: df9e0563eeb904bf300c2de64b52a663fd318ab5b5f5e0f262f27b2d40ef287df4cd445335974126acb9eeb11e6ac4385d63f3907dd54b658f18c3e5b3363cbf
7
+ data.tar.gz: 5553edbfa6321bec486381545da6a986723cb418af422a574c764bb5ac0c8438af3473e647af7dbc2db706ca508dd641fc8e47e023e8868c28dc594fdce1be03
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ # Copyright (c) 2023 Vladislav Onishchenko <pinkey.950@gmail.com>
4
+ # Copyright (c) 2025 Ivan Koplov <mnrhwow@gmail.com>
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ of this software and associated documentation files (the "Software"), to deal
8
+ in the Software without restriction, including without limitation the rights
9
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ copies of the Software, and to permit persons to whom the Software is
11
+ furnished to do so, subject to the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included in all
14
+ copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # upload_to_ru_store
2
+
3
+ [![fastlane Plugin Badge](https://rawcdn.githack.com/fastlane/fastlane/master/fastlane/assets/plugin-badge.svg)](https://rubygems.org/gems/fastlane-plugin-upload_to_ru_store)
4
+
5
+ **Fastlane-плагин для автоматической публикации Android-приложений (AAB/APK) в RuStore.**
6
+
7
+ За основу взять плагин от Vladislav Onishchenko: https://github.com/stfbee/fastlane-plugin-rustore
8
+
9
+ ## Возможности
10
+
11
+ - Аутентификация через RSA-SHA512 и получение JWE-токена RuStore API
12
+ - Автоматическая очистка всех незавершённых черновиков (draft) перед созданием новой версии
13
+ - Создание драфта с указанием типа публикации и текста «Что нового»
14
+ - Загрузка AAB или APK (GMS и/или HMS) в один или два шага
15
+ - Фиксация (commit) драфта и отправка на модерацию
16
+
17
+ ## Установка
18
+
19
+ В каталоге с вашим Fastfile выполните:
20
+
21
+ ```bash
22
+ fastlane add_plugin upload_to_ru_store
23
+ ```
24
+
25
+ ## Пример использования
26
+
27
+ ```ruby
28
+ lane :publish_to_rustore do
29
+ upload_to_ru_store(
30
+ package_name: "com.example.app",
31
+ key_id: ENV["RUSTORE_KEY_ID"],
32
+ private_key: ENV["RUSTORE_PRIVATE_KEY"],
33
+ publish_type: "INSTANTLY", # MANUAL, DELAYED или INSTANTLY (по умолчанию INSTANTLY)
34
+ changelog_path: "metadata/android/ru-RU/changelog.txt", # опционально, макс. 500 символов
35
+ aab: "app/build/outputs/bundle/release/app-release.aab", # если указан, зальётся только AAB
36
+ gms_apk: "app/build/outputs/apk/release/app-release.apk", # путь к Google-APK (если не указан AAB)
37
+ hms_apk: "app-huawei-release.apk" # путь к Huawei-APK (опционально)
38
+ )
39
+ end
40
+ ```
41
+
42
+ **Плагин автоматически:**
43
+ 1. Получит JWE-токен RuStore
44
+ 2. Удалит все существующие черновики приложения
45
+ 3. Создаст новый драфт
46
+ 4. Загрузит указанные сборки (AAB и/или APK)
47
+ 5. Закоммитит драфт и отправит на модерацию
48
+
49
+ ## Опции
50
+
51
+ | Параметр | Описание | Обязательный | Формат |
52
+ | ---------------- | ------------------------------------------------------------------------------------------------ | ------------ | --------- |
53
+ | `package_name` | Уникальный идентификатор пакета (например, `com.example.app`) | да | `String` |
54
+ | `key_id` | Идентификатор RSA-ключа в консоли RuStore | да | `String` |
55
+ | `private_key` | PEM-строка RSA-приватного ключа (без обёрток `BEGIN/END`) | да | `String` |
56
+ | `publish_type` | Тип публикации: `MANUAL`, `DELAYED` или `INSTANTLY` (по умолчанию `INSTANTLY`) | нет | `String` |
57
+ | `changelog_path` | Путь к `.txt`-файлу с описанием «Что нового?» (макс. 500 символов) | нет | `String` |
58
+ | `aab` | Путь к Android App Bundle (`.aab`). Если указан, APK не загружается | нет | `String` |
59
+ | `gms_apk` | Путь к APK с Google Mobile Services. Используется, если не указан `aab` | нет | `String` |
60
+ | `hms_apk` | Путь к APK с Huawei Mobile Services (опционально) | нет | `String` |
61
+
62
+ ## Требования
63
+
64
+ - Ruby >= 2.6
65
+ - Fastlane >= 2.214.0
66
+
67
+ ## Лицензия
68
+
69
+ MIT. Смотрите [LICENSE](LICENSE)
70
+
71
+ ## Полезные ссылки
72
+
73
+ - [Документация RuStore API](https://help.rustore.ru/rustore/for_developers/work_with_RuStore_API)
74
+ - [Fastlane Plugins Guide](https://docs.fastlane.tools/plugins/create-plugin/)
@@ -0,0 +1,92 @@
1
+ require 'fastlane/action'
2
+ require 'fastlane_core/ui/ui'
3
+ require_relative '../helper/upload_to_ru_store_helper'
4
+
5
+ module Fastlane
6
+ module Actions
7
+ # Uploads Android builds (AAB/APK) to RuStore
8
+ class UploadToRuStoreAction < Action
9
+ def self.authors
10
+ ['Kopylov Ivan']
11
+ end
12
+
13
+ def self.description
14
+ 'Uploads AAB and optional APK bundles to RuStore, cleans up drafts before publishing.'
15
+ end
16
+
17
+ def self.available_options
18
+ [
19
+ FastlaneCore::ConfigItem.new(key: :package_name, env_name: 'RUSTORE_PACKAGE_NAME', description: 'App package (e.g. com.example.app)', optional: false, type: String),
20
+ FastlaneCore::ConfigItem.new(key: :key_id, env_name: 'RUSTORE_KEY_ID', description: 'RuStore API key ID', optional: false, type: String),
21
+ FastlaneCore::ConfigItem.new(key: :private_key, env_name: 'RUSTORE_PRIVATE_KEY', description: 'RUStore RSA private key (PEM)', optional: false, type: String),
22
+ FastlaneCore::ConfigItem.new(key: :publish_type, env_name: 'RUSTORE_PUBLISH_TYPE', description: 'Publication type: MANUAL/DELAYED/INSTANTLY', optional: true, type: String),
23
+ FastlaneCore::ConfigItem.new(key: :aab, env_name: 'RUSTORE_AAB', description: 'Path to AAB', optional: true, type: String),
24
+ FastlaneCore::ConfigItem.new(key: :gms_apk, env_name: 'RUSTORE_GMS_APK', description: 'Path to GMS APK', optional: true, type: String),
25
+ FastlaneCore::ConfigItem.new(key: :hms_apk, env_name: 'RUSTORE_HMS_APK', description: 'Path to HMS APK (optional)', optional: true, type: String),
26
+ FastlaneCore::ConfigItem.new(key: :changelog_path, env_name: 'RUSTORE_CHANGELOG_PATH', description: 'Path to changelog .txt', optional: true, type: String)
27
+ ]
28
+ end
29
+
30
+ def self.is_supported?(platform)
31
+ platform == :android
32
+ end
33
+
34
+ def self.run(params)
35
+ token = Helper::UploadToRuStoreHelper.fetch_token(
36
+ key_id: params[:key_id],
37
+ private_key: params[:private_key]
38
+ )
39
+
40
+ Helper::UploadToRuStoreHelper.remove_drafts(
41
+ token: token,
42
+ package_name: params[:package_name]
43
+ )
44
+
45
+ draft_id = Helper::UploadToRuStoreHelper.create_draft(
46
+ token: token,
47
+ package_name: params[:package_name],
48
+ publish_type: params[:publish_type],
49
+ changelog_path: params[:changelog_path]
50
+ )
51
+
52
+ if params[:aab]
53
+ Helper::UploadToRuStoreHelper.upload_build(
54
+ token: token,
55
+ draft_id: draft_id,
56
+ file_path: params[:aab],
57
+ package_name: params[:package_name],
58
+ build_type: 'aab'
59
+ )
60
+ elsif params[:gms_apk]
61
+ Helper::UploadToRuStoreHelper.upload_build(
62
+ token: token,
63
+ draft_id: draft_id,
64
+ file_path: params[:gms_apk],
65
+ package_name: params[:package_name],
66
+ build_type: 'apk',
67
+ service_type: 'GMS'
68
+ )
69
+ else
70
+ UI.user_error!('Необходимо указать AAB или GMS_APK')
71
+ end
72
+
73
+ if params[:hms_apk]
74
+ Helper::UploadToRuStoreHelper.upload_build(
75
+ token: token,
76
+ draft_id: draft_id,
77
+ file_path: params[:hms_apk],
78
+ package_name: params[:package_name],
79
+ build_type: 'apk',
80
+ service_type: 'HMS'
81
+ )
82
+ end
83
+
84
+ Helper::UploadToRuStoreHelper.commit_draft(
85
+ token: token,
86
+ draft_id: draft_id,
87
+ package_name: params[:package_name]
88
+ )
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,176 @@
1
+ require 'fastlane_core/ui/ui'
2
+ require 'faraday'
3
+ require 'faraday_middleware'
4
+ require 'openssl'
5
+ require 'base64'
6
+ require 'date'
7
+ require 'json'
8
+
9
+ module Fastlane
10
+ UI = FastlaneCore::UI
11
+
12
+ module Helper
13
+ # Helper for Fastlane plugin "upload_to_ru_store"
14
+ # Encapsulates authentication, draft management, upload and commit operations
15
+ class UploadToRuStoreHelper
16
+ BASE_URL = 'https://public-api.rustore.ru'.freeze
17
+ DEFAULT_PAGE_SIZE = 100
18
+
19
+ class << self
20
+ # Obtain JWE token using RSA-SHA512 signature
21
+ # @param key_id [String] API key identifier
22
+ # @param private_key [String] PEM-formatted RSA private key
23
+ # @return [String] JWE token
24
+ def fetch_token(key_id:, private_key:)
25
+ timestamp = DateTime.now.iso8601(3)
26
+ signature = rsa_sign(key_id: key_id, timestamp: timestamp, private_key: private_key)
27
+
28
+ response = client.post('/public/auth/') do |req|
29
+ req.body = { keyId: key_id, timestamp: timestamp, signature: signature }
30
+ end
31
+ debug(response)
32
+ response.dig('body', 'jwe') || UI.user_error!('Не удалось получить токен из RuStore')
33
+ end
34
+
35
+ # Remove all existing drafts for package
36
+ # @param token [String]
37
+ # @param package_name [String]
38
+ def remove_drafts(token:, package_name:)
39
+ draft_ids(token: token, package_name: package_name).each do |id|
40
+ delete_draft(token: token, package_name: package_name, draft_id: id)
41
+ end
42
+ end
43
+
44
+ # Create new draft version, optionally with changelog and publish type
45
+ # @param token [String]
46
+ # @param package_name [String]
47
+ # @param publish_type [String, nil]
48
+ # @param changelog_path [String, nil]
49
+ # @return [Integer] draft_id
50
+ def create_draft(token:, package_name:, publish_type: nil, changelog_path: nil)
51
+ payload = {}
52
+ payload[:publishType] = publish_type if publish_type
53
+ payload[:whatsNew] = read_changelog(changelog_path) if changelog_path
54
+
55
+ response = client.post("/public/v1/application/#{package_name}/version") do |req|
56
+ req.headers['Public-Token'] = token
57
+ req.body = payload
58
+ end
59
+ debug(response)
60
+ extract_draft_id(response)
61
+ end
62
+
63
+ # Upload application build (APK or AAB)
64
+ # @param token [String]
65
+ # @param draft_id [Integer]
66
+ # @param file_path [String]
67
+ # @param package_name [String]
68
+ # @param build_type ['apk','aab']
69
+ # @param service_type ['GMS','HMS',nil]
70
+ def upload_build(token:, draft_id:, file_path:, package_name:, build_type:, service_type: nil)
71
+ endpoint = "/public/v1/application/#{package_name}/version/#{draft_id}/#{build_type}"
72
+ part = Faraday::Multipart::FilePart.new(file_path, mime_type(build_type))
73
+
74
+ response = client.post(endpoint) do |req|
75
+ req.headers['Public-Token'] = token
76
+ req.params['servicesType'] = service_type if service_type
77
+ req.params['isMainApk'] = true if service_type == 'GMS'
78
+ req.body = { file: part }
79
+ end
80
+ debug(response)
81
+
82
+ if response.body.dig('message')&.include?('must be larger')
83
+ UI.user_error!('Сборка с таким versionCode уже была загружена ранее')
84
+ end
85
+ end
86
+
87
+ # Commit the draft to publish
88
+ # @param token [String]
89
+ # @param draft_id [Integer]
90
+ # @param package_name [String]
91
+ def commit_draft(token:, draft_id:, package_name:)
92
+ response = client.post("/public/v1/application/#{package_name}/version/#{draft_id}/commit") do |req|
93
+ req.headers['Public-Token'] = token
94
+ end
95
+ debug(response)
96
+ end
97
+
98
+ private
99
+
100
+ # Initialize Faraday client
101
+ def client
102
+ @client ||= Faraday.new(url: BASE_URL) do |f|
103
+ f.request :multipart
104
+ f.request :json
105
+ f.request :url_encoded
106
+ f.response :json, content_type: /\bjson$/
107
+ f.response :logger, Logger.new($stderr, level: Logger::DEBUG)
108
+ f.use FaradayMiddleware::FollowRedirects
109
+ f.adapter :net_http
110
+ end
111
+ end
112
+
113
+ # Sign payload with RSA-SHA512
114
+ def rsa_sign(key_id:, timestamp:, private_key:)
115
+ rsa = OpenSSL::PKey::RSA.new(private_key)
116
+ sig = rsa.sign(OpenSSL::Digest::SHA512.new, key_id + timestamp)
117
+ Base64.strict_encode64(sig)
118
+ end
119
+
120
+ # List draft IDs
121
+ def draft_ids(token:, package_name:)
122
+ resp = client.get("/public/v1/application/#{package_name}/version") do |req|
123
+ req.headers['Public-Token'] = token
124
+ req.params['filterTestingType'] = 'ALL'
125
+ req.params['page'] = 0
126
+ req.params['size'] = DEFAULT_PAGE_SIZE
127
+ end
128
+ resp.body.dig('body', 'content').to_a
129
+ .select { |v| v['versionStatus'] == 'DRAFT' }
130
+ .map { |v| v['versionId'] }
131
+ end
132
+
133
+ # Delete a single draft
134
+ def delete_draft(token:, package_name:, draft_id:)
135
+ resp = client.delete("/public/v1/application/#{package_name}/version/#{draft_id}") do |req|
136
+ req.headers['Public-Token'] = token
137
+ end
138
+ if resp.status == 204
139
+ UI.message("Deleted draft ##{draft_id}")
140
+ else
141
+ UI.important("Failed to delete draft ##{draft_id}: #{resp.body['message']}")
142
+ end
143
+ end
144
+
145
+ # Read changelog and validate length
146
+ def read_changelog(path)
147
+ text = File.read(path)
148
+ UI.user_error!('Файл Что нового? более 500 символов') if text.size > 500
149
+ text
150
+ end
151
+
152
+ # Parse draft ID from create response
153
+ def extract_draft_id(response)
154
+ body = response.body
155
+ return body['body'] if body['body']
156
+ return body['message'][/\d+/].to_i if body['message']
157
+ UI.user_error!('Не удалось получить draftId из RuStore')
158
+ end
159
+
160
+ # Determine MIME type
161
+ def mime_type(type)
162
+ case type
163
+ when 'aab' then 'application/x-authorware-bin'
164
+ when 'apk' then 'application/vnd.android.package-archive'
165
+ else UI.user_error!("Неизвестный тип сборки: #{type}")
166
+ end
167
+ end
168
+
169
+ # Log response body when DEBUG
170
+ def debug(response)
171
+ UI.message("Debug: #{response.body}") if ENV['DEBUG']
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end
@@ -0,0 +1,5 @@
1
+ module Fastlane
2
+ module UploadToRuStore
3
+ VERSION = "1.0.2"
4
+ end
5
+ end
@@ -0,0 +1,15 @@
1
+ require 'fastlane/plugin/upload_to_ru_store/version'
2
+
3
+ module Fastlane
4
+ module UploadToRuStore
5
+ def self.all_classes
6
+ Dir.glob(
7
+ File.expand_path('upload_to_ru_store/{actions,helper}/*.rb', __dir__)
8
+ )
9
+ end
10
+ end
11
+ end
12
+
13
+ Fastlane::UploadToRuStore
14
+ .all_classes
15
+ .each { |file| require file }
metadata ADDED
@@ -0,0 +1,188 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fastlane-plugin-upload_to_ru_store
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Kopylov Ivan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-05-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: fastlane
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 2.214.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 2.214.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
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: rake
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: rspec
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: rspec_junit_formatter
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: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 1.12.1
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 1.12.1
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop-performance
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop-require_tools
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: simplecov
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ description:
154
+ email: mnrhwow@gmail.com
155
+ executables: []
156
+ extensions: []
157
+ extra_rdoc_files: []
158
+ files:
159
+ - LICENSE
160
+ - README.md
161
+ - lib/fastlane/plugin/upload_to_ru_store.rb
162
+ - lib/fastlane/plugin/upload_to_ru_store/actions/upload_to_ru_store_action.rb
163
+ - lib/fastlane/plugin/upload_to_ru_store/helper/upload_to_ru_store_helper.rb
164
+ - lib/fastlane/plugin/upload_to_ru_store/version.rb
165
+ homepage: https://github.com/kopylovis/fastlane-upload-to-ru-store
166
+ licenses:
167
+ - MIT
168
+ metadata: {}
169
+ post_install_message:
170
+ rdoc_options: []
171
+ require_paths:
172
+ - lib
173
+ required_ruby_version: !ruby/object:Gem::Requirement
174
+ requirements:
175
+ - - ">="
176
+ - !ruby/object:Gem::Version
177
+ version: '2.6'
178
+ required_rubygems_version: !ruby/object:Gem::Requirement
179
+ requirements:
180
+ - - ">="
181
+ - !ruby/object:Gem::Version
182
+ version: '0'
183
+ requirements: []
184
+ rubygems_version: 3.2.33
185
+ signing_key:
186
+ specification_version: 4
187
+ summary: Fastlane plugin to upload Android builds to RuStore
188
+ test_files: []