fastlane-plugin-moss 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5eca42de5969555ab02555f9bb86baeb87cbc109
4
+ data.tar.gz: 9bec893e5990f2b895a98e8de9ab8a7c35a2409d
5
+ SHA512:
6
+ metadata.gz: 77200f39d0f1a6bc23447c1e155d8eca12f8ed8bef4d823e8edb07cc9dacd611a8a1c6b02901fa02151fde8e2e708b8d6da506063985c988d53b3586c5d62ad3
7
+ data.tar.gz: a8a81b3c9d4581facf835d07545c1d4a0f2907121f04c42ec14773ef278ba62fb4f199c6788f84ddeba67724155fb0ffc8ecc4dcd569a608e1bd340e4c67489c
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Shaggon du <shaggon.du@farfetch.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.
@@ -0,0 +1,52 @@
1
+ # moss plugin
2
+
3
+ [![fastlane Plugin Badge](https://rawcdn.githack.com/fastlane/fastlane/master/fastlane/assets/plugin-badge.svg)](https://rubygems.org/gems/fastlane-plugin-moss)
4
+
5
+ ## Getting Started
6
+
7
+ This project is a [_fastlane_](https://github.com/fastlane/fastlane) plugin. To get started with `fastlane-plugin-moss`, add it to your project by running:
8
+
9
+ ```bash
10
+ fastlane add_plugin moss
11
+ ```
12
+
13
+ ## About moss
14
+
15
+ Moss is a tool that allows developers on Apple platforms to use any frameworks as a shared cache for frameworks built with Carthage.
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,16 @@
1
+ require 'fastlane/plugin/moss/version'
2
+
3
+ module Fastlane
4
+ module Moss
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::Moss.all_classes.each do |current|
15
+ require current
16
+ end
@@ -0,0 +1,385 @@
1
+ require 'fastlane/action'
2
+ require 'json'
3
+ require_relative '../helper/moss_helper'
4
+
5
+ module Fastlane
6
+ module Actions
7
+ class MossAction < Action
8
+
9
+ #####################################################
10
+ # @!group constant name
11
+ #####################################################
12
+ HASH_LIST_NAME = 'HashList'.freeze
13
+ CARTFILE_RESOLVED_NAME = 'Cartfile.resolved'.freeze
14
+
15
+
16
+ #####################################################
17
+ # @!group constant paths
18
+ #####################################################
19
+ WORK_PATH = '~/.moss'.freeze
20
+ CACHE_PATH = (WORK_PATH + '/cache').freeze
21
+ TMP_PATH = (WORK_PATH + '/tmp').freeze
22
+ RECEIVE_TMP_PATH = (WORK_PATH + '/receive_tmp').freeze
23
+ CARTFILE_RESOLVED_PATH = CARTFILE_RESOLVED_NAME
24
+ HASH_LIST_PATH = (WORK_PATH + '/' + HASH_LIST_NAME).freeze
25
+ CARTHAGE_PATH = 'Carthage'.freeze
26
+ CARTHAGE_BUILD_PATH = (CARTHAGE_PATH + '/Build').freeze
27
+ CARTHAGE_BUILD_IOS_PATH = (CARTHAGE_BUILD_PATH + '/iOS').freeze
28
+ CARTHAGE_BUILD_IOS_STATIC_PATH = (CARTHAGE_BUILD_IOS_PATH + '/Static').freeze
29
+
30
+
31
+ #####################################################
32
+ # @!group constant messages
33
+ #####################################################
34
+ CAN_NOT_FIND_FILE = 'Can not find file '.freeze
35
+ SKIP_FETCH_FRAMEWORK = '[Skip fetch framework] '.freeze
36
+ SKIP_STORAGE_FRAMEWORK = '[Skip storage framework] '.freeze
37
+
38
+
39
+ #####################################################
40
+ # @!group constant suffix
41
+ #####################################################
42
+ SUFFIX_VERSION = '.version'.freeze
43
+ SUFFIX_ZIP = '.zip'.freeze
44
+ SUFFIX_FRAMEWORK = '.framework'.freeze
45
+ SUFFIX_DSYM = '.dSYM'.freeze
46
+
47
+
48
+ #####################################################
49
+ # @!group constant cmd
50
+ #####################################################
51
+ CART_BOOT = 'carthage bootstrap --platform iOS --cache-builds --new-resolver --configuration Debug'.freeze
52
+
53
+
54
+ #####################################################
55
+ # @!group constant other
56
+ #####################################################
57
+ BINARY = 'binary'.freeze
58
+
59
+
60
+ def self.run(params)
61
+ server = params[:server]
62
+ username = params[:username]
63
+ producer = params[:producer]
64
+
65
+ ssh_path = username + '@' + server
66
+
67
+ if File::exists?(CARTFILE_RESOLVED_PATH)
68
+ # pre validation if user have the right ssh permission to target host
69
+ ssh_connection_check(ssh_path)
70
+
71
+ # check if hashlist contains the hash of current resolve file
72
+ shasum = Digest::SHA256.file CARTFILE_RESOLVED_PATH
73
+ UI.header('Start to validate hashList')
74
+ stdout = `ssh #{ssh_path} 'cat #{HASH_LIST_PATH} | grep -c #{shasum}'`
75
+
76
+ # current resolve file doesn't have cache, start bootstrap
77
+ if Integer(stdout) == 0
78
+ UI.header('No cache match')
79
+ if producer then progress_producer(ssh_path, shasum) end
80
+ return
81
+ end
82
+
83
+ # Hit a cache, start fetch cached framework
84
+ fetch_cache(ssh_path)
85
+
86
+ # Clean
87
+ `rm #{CARTHAGE_BUILD_IOS_PATH}/*.bcsymbolmap`
88
+
89
+ return
90
+ end
91
+
92
+ UI.important("[Skip moss] No Carthage.resolve file found")
93
+ end
94
+
95
+ #####################################################
96
+ # @!group private functions
97
+ #####################################################
98
+ private
99
+ def self.progress_producer(ssh_path, shasum)
100
+ if !system(CART_BOOT) then UI.user_error!('Carthage bootstrap failed') end
101
+ UI.header('Start to storage frameworks')
102
+ # Path init
103
+ execute_cmd("rm -rf #{TMP_PATH};mkdir -p #{TMP_PATH}")
104
+
105
+ # Get the zip list from remote server
106
+ target_library_list = target_library_list(ssh_path)
107
+
108
+ # Storage the frameworks that found in local but not found in remote server
109
+ ((target_library_list + library_list()).uniq { |library| library.name + library.version } - target_library_list).each do |library|
110
+
111
+ local_zip_file = TMP_PATH + '/' + library.name + SUFFIX_ZIP
112
+
113
+ # Find .version file and .framework file and zip them into one zip file
114
+ version_file_path = CARTHAGE_BUILD_PATH + '/.' + library.name + SUFFIX_VERSION
115
+ file_exist_validation(version_file_path)
116
+
117
+ frameworks_path = ""
118
+ dsym_files_path = ""
119
+
120
+ static_framework_path = CARTHAGE_BUILD_IOS_STATIC_PATH + '/' + library.name + SUFFIX_FRAMEWORK
121
+ static_framework_file_path = static_framework_path + '/' + library.name
122
+
123
+ if library.frameworks.nil? then next end
124
+ if library.frameworks.size == 0
125
+ if !File::exists?(static_framework_file_path)
126
+ UI.important(SKIP_STORAGE_FRAMEWORK + "No framework found for " + library.name)
127
+ next
128
+ end
129
+
130
+ frameworks_path = static_framework_path
131
+ dsym_files_path = CARTHAGE_BUILD_IOS_STATIC_PATH + '/' + library.name + SUFFIX_FRAMEWORK + SUFFIX_DSYM
132
+ end
133
+
134
+ # hash validation stop if not success
135
+ library.frameworks.each do |framework|
136
+ if !framework_validation(framework) then UI.user_error!("framework validation failed for " + framework.name) end
137
+
138
+ frameworks_path = frameworks_path + ' ' + CARTHAGE_BUILD_IOS_PATH + '/' + framework.name + SUFFIX_FRAMEWORK
139
+ dsym_files_path = dsym_files_path + ' ' + CARTHAGE_BUILD_IOS_PATH + '/' + framework.name + SUFFIX_FRAMEWORK + SUFFIX_DSYM
140
+ end
141
+
142
+ UI.message('Start Zipping ' + library.name + SUFFIX_ZIP)
143
+ execute_cmd("zip #{local_zip_file} #{version_file_path} #{dsym_files_path} -r #{frameworks_path} >> /dev/null 2>&1")
144
+
145
+ # storage zip file
146
+ target_zip_file_path = CACHE_PATH + '/' + library.name + '/' + library.version
147
+ target_zip_file = target_zip_file_path + '/' + library.name + SUFFIX_ZIP
148
+
149
+ UI.message('Start storage ' + library.name + SUFFIX_ZIP)
150
+ execute_cmd("ssh #{ssh_path} 'mkdir -p #{target_zip_file_path}';scp -p #{local_zip_file} #{ssh_path}:#{target_zip_file}")
151
+ end
152
+
153
+ # update hashlist
154
+ UI.message('Start Update HashList!')
155
+ execute_cmd("ssh #{ssh_path} 'echo #{shasum} >> #{HASH_LIST_PATH}'")
156
+ UI.success('Update HashList succeed!')
157
+ end
158
+
159
+ private
160
+ def self.fetch_cache(ssh_path)
161
+ UI.header('Hit a cache, start fetch cached frameworks!')
162
+ execute_cmd("rm -rf #{RECEIVE_TMP_PATH};mkdir -p #{RECEIVE_TMP_PATH};mkdir -p #{CACHE_PATH}")
163
+
164
+ # Fetch the frameworks that found in remote server but not found in local
165
+ library_list = library_list()
166
+ target_library_list = target_library_list(ssh_path)
167
+ fetch_need_library_list = (target_library_list + library_list) - (target_library_list + library_list).uniq { |library| library.name + library.version }
168
+
169
+ (library_list - fetch_need_library_list).each do |library|
170
+ UI.message(SKIP_FETCH_FRAMEWORK + "Remote server does not contain " + library.name)
171
+ end
172
+
173
+ fetch_need_library_list.each do |library|
174
+
175
+ if !library.commitish.nil? &&
176
+ library.commitish == library.version &&
177
+ !library.frameworks.nil? &&
178
+ ((library.frameworks.size > 0 && library.frameworks.select {|framework| !framework_validation(framework) }.size == 0) || (library.frameworks.size == 0 && static_framework_exists(library)))
179
+
180
+ UI.message(SKIP_FETCH_FRAMEWORK + "Valid cache found for " + library.name)
181
+ next
182
+ end
183
+
184
+ target_zip_file = CACHE_PATH + '/' + library.name + '/' + library.version + '/' + library.name + SUFFIX_ZIP
185
+ local_zip_file_path = RECEIVE_TMP_PATH + '/' + library.name + '/' + library.version
186
+ local_zip_file = local_zip_file_path + '/' + library.name + SUFFIX_ZIP
187
+
188
+ UI.message('Start fetch ' + library.name + SUFFIX_ZIP)
189
+ execute_cmd("mkdir -p #{local_zip_file_path};scp -p #{ssh_path}:#{target_zip_file} #{local_zip_file}")
190
+
191
+ UI.message('Start Unzip ' + library.name + SUFFIX_ZIP)
192
+ execute_cmd("unzip -o #{local_zip_file} -d . >> /dev/null 2>&1")
193
+ end
194
+ end
195
+
196
+ private
197
+ def self.target_library_list(ssh_path)
198
+ return `ssh #{ssh_path} 'mkdir -p #{CACHE_PATH};find #{CACHE_PATH} -name *.zip'`.to_s.split("\n").map do |path|
199
+ library = Library.new
200
+ library.name = path.split("/").reverse[2]
201
+ library.version = path.split("/").reverse[1]
202
+ library
203
+ end
204
+ end
205
+
206
+ private
207
+ def self.static_framework_exists(library)
208
+
209
+ static_framework_file_path = CARTHAGE_BUILD_IOS_STATIC_PATH + '/' + library.name + SUFFIX_FRAMEWORK + '/' + library.name
210
+ if File::exists?(static_framework_file_path) then return true end
211
+
212
+ return false
213
+ end
214
+
215
+ # validate framework exists and with the right shasum
216
+ private
217
+ def self.framework_validation(framework)
218
+ framework_path = CARTHAGE_BUILD_IOS_PATH + '/' + framework.name + SUFFIX_FRAMEWORK
219
+ framework_file_path = framework_path + '/' + framework.name
220
+ dsym_file_path = CARTHAGE_BUILD_IOS_PATH + '/' + framework.name + SUFFIX_FRAMEWORK + SUFFIX_DSYM
221
+
222
+ if !File::exists?(framework_file_path)
223
+ UI.message(CAN_NOT_FIND_FILE + framework_file_path)
224
+ return false
225
+ end
226
+
227
+ if !File::exists?(dsym_file_path)
228
+ UI.message(CAN_NOT_FIND_FILE + framework_file_path)
229
+ return false
230
+ end
231
+
232
+ framework_shasum = Digest::SHA256.file framework_file_path
233
+ if framework_shasum.to_s != framework.hash
234
+ UI.message('The hash of ' + framework_file_path + ' is [' + framework_shasum.to_s + '] which is not match the value [' + framework.hash + '] in .version file')
235
+ return false
236
+ end
237
+
238
+ return true
239
+ end
240
+
241
+ private
242
+ def self.ssh_connection_check(ssh_path)
243
+ if !system("ssh -o BatchMode=yes -o ConnectTimeout=5 #{ssh_path} echo 0 2>&1")
244
+ UI.user_error!("Can not open a ssh connection to #{ssh_path} please make sure you have the right premission and try to execute \n'ssh-copy-id -i ~/.ssh/id_rsa.pub #{ssh_path}' before you run moss")
245
+ end
246
+ end
247
+
248
+ private
249
+ def self.execute_cmd(cmd)
250
+ if !system(cmd) then UI.user_error!(cmd + ' failed ') end
251
+ end
252
+
253
+ private
254
+ def self.file_exist_validation(path)
255
+ if !File::exists?(path) then UI.user_error!(CAN_NOT_FIND_FILE + path) end
256
+ end
257
+
258
+ private
259
+ def self.library_list()
260
+ return IO.readlines(CARTFILE_RESOLVED_PATH).map{ |line|
261
+
262
+ begin
263
+ type = line.split[0]
264
+ library_name = line.split[1].delete('"').split('/').last.split('.').first
265
+ library_version = line.split[2].delete('"')
266
+ rescue
267
+ UI.user_error!('[File read file] ' + CARTFILE_RESOLVED_PATH + ' Please make sure the resolved file is genereted by cathage.')
268
+ end
269
+
270
+ library_commitish = nil
271
+ library_frameworks = nil
272
+
273
+ version_file_path = CARTHAGE_BUILD_PATH + '/.' + library_name + SUFFIX_VERSION
274
+
275
+ # TODO
276
+ # Need to support binary type cache
277
+ if type == BINARY
278
+ UI.important("[No support for Binary type] " + library_name)
279
+
280
+ next
281
+ end
282
+
283
+ if File::exists?(version_file_path)
284
+
285
+ json = File.read(version_file_path)
286
+ obj = JSON.parse(json)
287
+
288
+ library_commitish = obj['commitish']
289
+ node_iOS = obj['iOS']
290
+
291
+ if library_commitish.nil? then UI.important('[No commitish node found] ' + version_file_path) end
292
+ if node_iOS.nil? then UI.important('[No iOS node found] ' + version_file_path)
293
+ elsif node_iOS.size == 0
294
+ UI.important('[No frameworks found] ' + version_file_path)
295
+ # TODO
296
+ # Need to support static Library
297
+ # library_frameworks = []
298
+ else
299
+ library_frameworks = node_iOS.map{ |node|
300
+
301
+ node_iOS_name = node['name']
302
+ if node_iOS_name.nil?
303
+ UI.important('[No name node found] ' + version_file_path)
304
+ next
305
+ end
306
+ node_iOS_hash = node['hash']
307
+ if node_iOS_hash.nil?
308
+ UI.important('[No hash node found] ' + version_file_path)
309
+ next
310
+ end
311
+
312
+ framework = Framework.new
313
+ framework.name = node_iOS_name
314
+ framework.hash = node_iOS_hash
315
+ framework
316
+ }.compact
317
+ end
318
+ end
319
+
320
+ library = Library.new
321
+ library.name = library_name
322
+ library.version = library_version
323
+ library.commitish = library_commitish
324
+ library.frameworks = library_frameworks
325
+
326
+ library
327
+ }.compact
328
+ end
329
+
330
+ def self.description
331
+ "moss is a tool that allows developers on Apple platforms to use any frameworks as a shared cache for frameworks built with Carthage."
332
+ end
333
+
334
+ def self.authors
335
+ ["Shaggon du"]
336
+ end
337
+
338
+ def self.return_value
339
+ nil
340
+ end
341
+
342
+ def self.details
343
+ # Optional:
344
+ "moss is a tool that allows developers on Apple platforms to use any frameworks as a shared cache for frameworks built with Carthage."
345
+ end
346
+
347
+ def self.available_options
348
+ [
349
+ FastlaneCore::ConfigItem.new(key: :server,
350
+ env_name: 'MOSS_SERVER',
351
+ optional: false,
352
+ description: 'The Server Name or the ip address which store the cache of the frameworks'),
353
+ FastlaneCore::ConfigItem.new(key: :username,
354
+ env_name: 'MOSS_USERNAME',
355
+ optional: false,
356
+ description: 'The username use to use scp command'),
357
+ FastlaneCore::ConfigItem.new(key: :producer,
358
+ is_string: false,
359
+ env_name: 'MOSS_PRODUCER',
360
+ optional: true,
361
+ description: 'If true, the executor will act as a producer, not only use the cached frameworks but also produce it',
362
+ default_value: false)
363
+ ]
364
+ end
365
+
366
+ def self.is_supported?(platform)
367
+ [:ios].include?(platform)
368
+ end
369
+
370
+ def self.example_code
371
+ [
372
+ 'moss'
373
+ ]
374
+ end
375
+ end
376
+ end
377
+ end
378
+
379
+ class Library
380
+ attr_accessor:name, :frameworks, :commitish, :version
381
+ end
382
+
383
+ class Framework
384
+ attr_accessor:name, :hash
385
+ end
@@ -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 MossHelper
8
+ # class methods that you define here become available in your action
9
+ # as `Helper::MossHelper.your_method`
10
+ #
11
+ def self.show_message
12
+ UI.message("Hello from the moss plugin helper!")
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,5 @@
1
+ module Fastlane
2
+ module Moss
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,176 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fastlane-plugin-moss
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Shaggon du
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-03-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pry
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: bundler
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: rspec
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_junit_formatter
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.49.1
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '='
95
+ - !ruby/object:Gem::Version
96
+ version: 0.49.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop-require_tools
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: simplecov
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: fastlane
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: 2.112.0
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: 2.112.0
139
+ description:
140
+ email: shaggon.du@farfetch.com
141
+ executables: []
142
+ extensions: []
143
+ extra_rdoc_files: []
144
+ files:
145
+ - LICENSE
146
+ - README.md
147
+ - lib/fastlane/plugin/moss.rb
148
+ - lib/fastlane/plugin/moss/actions/moss_action.rb
149
+ - lib/fastlane/plugin/moss/helper/moss_helper.rb
150
+ - lib/fastlane/plugin/moss/version.rb
151
+ homepage: https://github.com/jyo2206208/moss
152
+ licenses:
153
+ - MIT
154
+ metadata: {}
155
+ post_install_message:
156
+ rdoc_options: []
157
+ require_paths:
158
+ - lib
159
+ required_ruby_version: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - ">="
162
+ - !ruby/object:Gem::Version
163
+ version: '0'
164
+ required_rubygems_version: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - ">="
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
169
+ requirements: []
170
+ rubyforge_project:
171
+ rubygems_version: 2.6.13
172
+ signing_key:
173
+ specification_version: 4
174
+ summary: Moss is a tool that allows developers on Apple platforms to use any frameworks
175
+ as a shared cache for frameworks built with Carthage.
176
+ test_files: []