fastlane-plugin-apprepo 0.5.4 → 0.5.5

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.
@@ -1,15 +0,0 @@
1
- require 'fastlane_core/languages'
2
-
3
- module Fastlane
4
- module Apprepo
5
- # Responsible for loading language folders
6
- module Loader
7
- def self.language_folders(root)
8
- Dir.glob(File.join(root, '*')).select do |path|
9
- all = ALL_LANGUAGES.include?(File.basename(path).downcase)
10
- File.directory?(path) && all
11
- end.sort
12
- end
13
- end
14
- end
15
- end
@@ -1,44 +0,0 @@
1
- require 'json'
2
-
3
- module Fastlane
4
- module Apprepo
5
- # Responsible for parsing and providing manifest.json
6
- class Manifest
7
- #
8
- # Translated internal key names from Fastlane to Apprepo
9
- #
10
-
11
- attr_accessor :appcode # Apprepo Internal Code
12
- attr_accessor :filename # IPA file name
13
- attr_accessor :bundle_identifier # app_identifier
14
- attr_accessor :bundle_version # app_version
15
- attr_accessor :title # app_name
16
- attr_accessor :subtitle # app_description
17
- attr_accessor :notify # will send push notification / slack
18
-
19
- def initialize(appcode)
20
- self.appcode = appcode
21
- UI.message('Initializing requires APPCODE. ' + self.appcode)
22
- end
23
-
24
- def parse_json(json)
25
- # TODO: load values from JSON
26
- end
27
-
28
- # Provide JSON serialized data
29
- def manifest_as_json
30
- structure = {
31
- appcode: appcode,
32
- filename: filename,
33
- bundle_identifier: bundle_identifier,
34
- bundle_version: bundle_version,
35
- title: title,
36
- subtitle: subtitle,
37
- notify: notify
38
- }
39
-
40
- fputs structure
41
- end
42
- end
43
- end
44
- end
@@ -1,120 +0,0 @@
1
- require 'fastlane_core'
2
-
3
- module Fastlane
4
- module Apprepo
5
- # Provides available options for the commands generator
6
- class Options
7
- # rubocop:disable Metrics/AbcSize
8
- def self.available_options
9
- [
10
- FastlaneCore::ConfigItem.new(key: :ipa,
11
- short_option: '-i',
12
- optional: true,
13
- env_name: 'Apprepo_IPA_PATH',
14
- description: 'Path to your ipa file',
15
- default_value: Dir['*.ipa'].first,
16
- verify_block: proc do |value|
17
- UI.user_error!("Could not find ipa file at path '#{value}'") unless File.exist?(value)
18
- UI.user_error!("'#{value}' doesn't seem to be an ipa file") unless value.end_with?('.ipa')
19
- end),
20
- FastlaneCore::ConfigItem.new(key: :app_identifier,
21
- short_option: '-b',
22
- optional: false,
23
- env_name: 'Apprepo_APP_ID',
24
- description: 'Your bundle identifier',
25
- default_value: ''),
26
- FastlaneCore::ConfigItem.new(key: :app_code,
27
- short_option: '-c',
28
- optional: true,
29
- env_name: 'Apprepo_APPCODE',
30
- description: 'APPCODE value for Apprepo'),
31
- FastlaneCore::ConfigItem.new(key: :repo_url,
32
- short_option: '-r',
33
- optional: false,
34
- env_name: 'Apprepo_URL',
35
- description: 'URL of your Apprepo server'),
36
- FastlaneCore::ConfigItem.new(key: :repo_user,
37
- short_option: '-u',
38
- optional: false,
39
- env_name: 'Apprepo_USER',
40
- description: 'USER of your Apprepo server'),
41
- FastlaneCore::ConfigItem.new(key: :repo_password,
42
- short_option: '-p',
43
- optional: true,
44
- env_name: 'Apprepo_PASSWORD',
45
- description: 'PASSWORD for your Apprepo server (not for production)',
46
- conflicting_options: [:repo_key],
47
- conflict_block: proc do |value|
48
- UI.user_error!("You can't use 'password' and '#{value.key}' options in one run.")
49
- end),
50
- FastlaneCore::ConfigItem.new(key: :repo_key,
51
- short_option: '-k',
52
- optional: false,
53
- env_name: 'Apprepo_KEY',
54
- description: 'RSA key for your Apprepo server',
55
- conflicting_options: [:repo_password],
56
- conflict_block: proc do |value|
57
- UI.user_error!("You can't use 'repo_key' and '#{value.key}' options in one run.")
58
- end),
59
- FastlaneCore::ConfigItem.new(key: :repo_description,
60
- short_option: '-d',
61
- optional: true,
62
- description: 'Long detailed description for your Apprepo server',
63
- default_value: ''),
64
- FastlaneCore::ConfigItem.new(key: :repo_summary,
65
- short_option: '-s',
66
- optional: true,
67
- description: 'Short description for your Apprepo server',
68
- default_value: ''),
69
- FastlaneCore::ConfigItem.new(key: :manifest_path,
70
- short_option: '-m',
71
- description: 'Path to the folder containing the metadata files',
72
- optional: true),
73
- FastlaneCore::ConfigItem.new(key: :repo_title,
74
- short_option: '-a',
75
- description: 'Title of the app',
76
- optional: false),
77
- FastlaneCore::ConfigItem.new(key: :appcode,
78
- short_option: '-o',
79
- description: 'Name of the app on Apprepo',
80
- optional: false),
81
- FastlaneCore::ConfigItem.new(key: :skip_binary_upload,
82
- description: 'Skip uploading an ipa or to Apprepo',
83
- is_string: false,
84
- default_value: false),
85
- FastlaneCore::ConfigItem.new(key: :app_version,
86
- short_option: '-z',
87
- description: 'The version that should be edited or created',
88
- optional: true),
89
- FastlaneCore::ConfigItem.new(key: :skip_manifest,
90
- description: "Don't upload the metadata (e.g. title, description), this will still upload screenshots",
91
- is_string: false,
92
- default_value: false),
93
- FastlaneCore::ConfigItem.new(key: :notify,
94
- description: 'Notify Apprepo users on update',
95
- is_string: false,
96
- default_value: false),
97
- FastlaneCore::ConfigItem.new(key: :build_number,
98
- short_option: '-n',
99
- description: 'If set the given build number (already uploaded to iTC) will be used instead of the current built one',
100
- optional: true,
101
- conflicting_options: [:ipa],
102
- conflict_block: proc do |value|
103
- UI.user_error!("You can't use 'build_number' and '#{value.key}' options in one run.")
104
- end),
105
-
106
- # App Metadata
107
- # Non Localised
108
- FastlaneCore::ConfigItem.new(key: :app_icon,
109
- description: 'Metadata: The path to the app icon',
110
- optional: true,
111
- short_option: '-l',
112
- verify_block: proc do |value|
113
- UI.user_error!("Could not find png file at path '#{value}'") unless File.exist?(value)
114
- UI.user_error!("'#{value}' doesn't seem to be a png file") unless value.end_with?('.png')
115
- end)
116
- ]
117
- end
118
- end
119
- end
120
- end
@@ -1,71 +0,0 @@
1
- require_relative 'uploader'
2
-
3
- module Fastlane
4
- module Apprepo
5
- # Responsible for running
6
- class Runner
7
- attr_accessor :options
8
-
9
- def initialize(options)
10
- self.options = options
11
- Apprepo::DetectValues.new.run!(self.options)
12
- FastlaneCore::PrintTable.print_values(config: options, hide_keys: [:repo_password], mask_keys: [:repo_key], title: "Apprepo-sftp #{Apprepo::VERSION} Summary")
13
- end
14
-
15
- # rubocop:disable Metrics/AbcSize
16
- # rubocop:disable Metrics/CyclomaticComplexity
17
- def run
18
- UI.success('Apprepo SFTP Uploader running...')
19
- verify_version unless options[:app_version].to_s.empty?
20
- has_binary = options[:ipa]
21
- if !options[:skip_binary_upload] && !options[:build_number] && has_binary
22
- upload_binary
23
- UI.success('Finished the upload to Apprepo.')
24
- else
25
- UI.success('Binary upload skipped or no binary available.')
26
- end
27
-
28
- notify unless options[:notify].nil?
29
- end
30
-
31
- # Make sure the version on Apprepo matches the one in the ipa
32
- # If not, the new version will automatically be created
33
- def verify_version
34
- app_version = options[:app_version]
35
- msg = "TODO: Test if Apprepo matches '#{app_version}' from the IPA..."
36
- UI.message(msg)
37
-
38
- # changed = options[:app].ensure_version!(app_version)
39
- # if changed
40
- # UI.success("Successfully set the version to '#{app_version}'")
41
- # else
42
- # UI.success("'#{app_version}' is the latest version on Apprepo")
43
- # end
44
- end
45
-
46
- def download_manifest
47
- if options[:manifest_path]
48
- uploader = Apprepo::Uploader.new(options)
49
- result = uploader.download_manifest_only
50
- msg = 'Metadata download failed. Check out the error above.'
51
- UI.user_error!(msg) unless result
52
- end
53
- end
54
-
55
- # Upload the binary to Apprepo
56
- def upload_binary
57
- if options[:ipa]
58
- uploader = Apprepo::Uploader.new(options)
59
- result = uploader.upload
60
- msg = 'Binary upload failed. Check out the error above.'
61
- UI.user_error!(msg) unless result
62
- end
63
- end
64
-
65
- def notify
66
- # should be in metadata
67
- # UI.command_output('TODO: Missing implementation for Apprepo Push Notifier')
68
- end
69
- end
70
- end
71
- end
@@ -1,49 +0,0 @@
1
- module Fastlane
2
- module Apprepo
3
- # Responsible for setting up the Repofile configuration
4
- class Setup
5
- def setup_Apprepo(file_path, data, _Apprepo_path, _options)
6
- UI.message('[Apprepo:Setup] Setting up...')
7
- File.write(file_path, data)
8
-
9
- # TODO: implement later
10
- download_manifest(Apprepo_path, options)
11
-
12
- UI.success("NOT! created new Repofile at path '#{file_path}'")
13
- end
14
-
15
- # This method takes care of creating a new 'Apprepo' folder with metadata
16
- # and screenshots folders
17
- def generate_Apprepo_file(_Apprepo_path, options)
18
- # v = options[:app].latest_version
19
- # generate_Apprepo_file(v, File.join(Apprepo_path, 'manifest.json'))
20
-
21
- # Generate the final Repofile here
22
- gem_path = Helper.gem_path('Apprepo')
23
- Apprepo = File.read("#{gem_path}/../assets/RepofileDefault")
24
- Apprepo.gsub!('[[APP_IDENTIFIER]]', options[:app].bundle_id)
25
- Apprepo.gsub!('[[Apprepo_IPA_PATH]]', options[:app].file_path)
26
- Apprepo.gsub!('[[APP_VERSION]]', options[:app].version)
27
- Apprepo.gsub!('[[APP_NAME]]', options[:app].name)
28
- # Apprepo (was deliver)
29
- end
30
-
31
- def download_manifest(Apprepo_path, _options)
32
- path = File.join(Apprepo_path, 'metadata')
33
- FileUtils.mkdir_p(path)
34
- UI.success("TODO: DOWNLOAD MANIFEST'")
35
- Apprepo::Uploader.new(options).download_manifest_only
36
- end
37
-
38
- def run(options)
39
- UI.message('[Apprepo:Setup] Running...')
40
- containing = (File.directory?('fastlane') ? 'fastlane' : '.')
41
- file_path = File.join(containing, 'Repofile')
42
- data = generate_Apprepo_file(containing, options)
43
- setup_Apprepo(file_path, data, containing, options)
44
- end
45
- end
46
- end
47
-
48
- # @setup = new Apprepo::Setup
49
- end
@@ -1,306 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'rubygems'
4
- require 'json'
5
- require 'net/ssh'
6
- require 'net/sftp'
7
- require 'fastlane_core'
8
- require 'fastlane_core/languages'
9
-
10
- require_relative 'options'
11
-
12
- module Fastlane
13
- module Apprepo
14
- # rubocop:disable Metrics/ClassLength
15
-
16
- # Responsible for performing the SFTP operation
17
- class Uploader
18
- attr_accessor :options
19
-
20
- #
21
- # These want to be an input parameters:
22
- #
23
-
24
- attr_accessor :host
25
- attr_accessor :port
26
- attr_accessor :user
27
- attr_accessor :password
28
- attr_accessor :rsa_keypath
29
- attr_accessor :ipa_path
30
- attr_accessor :manifest_path
31
- attr_accessor :appcode
32
-
33
- # rubocop:disable Metrics/AbcSize
34
- # rubocop:disable Metrics/MethodLength
35
- def initialize(options)
36
- self.options = options unless options.nil?
37
- self.host = options[:repo_url]
38
- self.port = options[:repo_port]
39
- self.user = options[:repo_user]
40
- self.password = options[:repo_password]
41
- self.rsa_keypath = options[:repo_key] # '../assets/circle.key'
42
- self.ipa_path = options[:ipa] # '../sampleapp.ipa'
43
- self.manifest_path = options[:manifest_path] # '../assets/example_manifest.json'
44
- self.appcode = options[:appcode]
45
-
46
- # Apprepo::Uploader.new.run!
47
- # FastlaneCore::PrintTable.print_values(config: nil , hide_keys: [:app],
48
- # mask_keys: ['app_review_information.demo_password'],
49
- # title: "deliver #{Apprepo::VERSION} Summary") # options
50
- end
51
-
52
- #
53
- # Upload IPA & manifest
54
- #
55
-
56
- # rubocop:disable Metrics/AbcSize
57
- # rubocop:disable Metrics/MethodLength
58
- def upload
59
- # Login & Upload IPA with metadata using RSA key or username/password
60
- FastlaneCore::UI.message('upload...')
61
-
62
- if host.nil? || user.nil?
63
- FastlaneCore::UI.user_error('repo_url, repo_port, repo_user and repo_password or repo_key must be set on upload')
64
- return false
65
- end
66
-
67
- if rsa_keypath
68
- rsa_key = load_rsa_key(rsa_keypath)
69
- if rsa_key.nil?
70
- FastlaneCore::UI.user_error('Failed to load RSA key... ' + options[:rsa_keypath])
71
- end
72
- end
73
-
74
- success = false
75
- if !rsa_key.nil?
76
- FastlaneCore::UI.message('Logging in with RSA key...')
77
- Net::SSH.start(host, user, port: port, key_data: rsa_key, keys_only: true) do |ssh|
78
- FastlaneCore::UI.message('Uploading IPA & Manifest...')
79
- success = ssh_sftp_upload(ssh, ipa_path, manifest_path)
80
- end
81
- else
82
- FastlaneCore::UI.message('Logging in with username/password...')
83
- Net::SSH.start(host, user, port: port, password: password) do |ssh|
84
- FastlaneCore::UI.message('Uploading IPA & Manifest...')
85
- success = ssh_sftp_upload(ssh, ipa_path, manifest_path)
86
- end
87
- end
88
- success
89
- end
90
-
91
- #
92
- # Download metadata only
93
- #
94
-
95
- # rubocop:disable Metrics/AbcSize
96
- # rubocop:disable Metrics/MethodLength
97
- def download_manifest_only
98
- FastlaneCore::UI.message('download_manifest_only...')
99
- rsa_key = load_rsa_key(rsa_keypath)
100
- success = true
101
- if !rsa_key.nil?
102
- FastlaneCore::UI.message('Logging in with RSA key for download...')
103
- Net::SSH.start(host, user, port: port, key_data: rsa_key, keys_only: true) do |ssh|
104
- FastlaneCore::UI.message('Uploading UPA & Manifest...')
105
- success = ssh_sftp_download(ssh, manifest_path)
106
- end
107
- else
108
- FastlaneCore::UI.message('Logging in for download...')
109
- Net::SSH.start(host, user, port: port, password: password) do |ssh|
110
- FastlaneCore::UI.message('Uploading UPA & Manifest...')
111
- success = ssh_sftp_download(ssh, manifest_path)
112
- end
113
- end
114
- success
115
- end
116
-
117
- private
118
-
119
- def ssh_sftp_download(ssh, _manifest_path)
120
- ssh.sftp.connect do |sftp|
121
- FastlaneCore::UI.message('Fetching remote manifest...')
122
- manifest = download_manifest(sftp)
123
- puts '********************************************************'
124
- puts JSON.pretty_generate(manifest)
125
- puts '********************************************************'
126
- FastlaneCore::UI.success('Successfully fetched manifest')
127
- FastlaneCore::UI.command_output('TODO: Processing manifest not implemented.')
128
- end
129
- end
130
-
131
- def ssh_sftp_upload(ssh, local_ipa_path, manifest_path)
132
- ssh.sftp.connect do |sftp|
133
- break unless check_ipa(local_ipa_path)
134
- check_appcode(sftp, appcode)
135
- path = remote_path(appcode)
136
- manifest = download_manifest(sftp)
137
- puts JSON.pretty_generate(manifest) unless manifest.nil?
138
- bump_ipa(sftp, local_ipa_path, appcode)
139
- remote_ipa_path = get_remote_ipa_path(local_ipa_path, appcode)
140
- FastlaneCore::UI.command_output('Uploading IPA...')
141
- upload_ipa(sftp, local_ipa_path, remote_ipa_path)
142
- FastlaneCore::UI.command_output('Uploading manifest...')
143
- upload_manifest(sftp, manifest_path, remote_manifest_path(appcode))
144
- FastlaneCore::UI.command_output('Verification...')
145
- # Lists the entries in a directory for verification
146
- sftp.dir.foreach(path) do |entry|
147
- FastlaneCore::UI.message(entry.longname)
148
- end
149
- end
150
- end
151
-
152
- # Check IPA existence locally
153
- #
154
- # @param local_ipa_path
155
- def check_ipa(local_ipa_path)
156
- if File.exist?(local_ipa_path)
157
- FastlaneCore::UI.important('IPA found at ' + local_ipa_path)
158
- return true
159
- else
160
- FastlaneCore::UI.verbose('IPA at given path does not exist yet.')
161
- return false
162
- end
163
- end
164
-
165
- # Private methods - Remote Operations
166
-
167
- # Checks/creates remote APPCODE directory
168
- # @param sftp
169
- # @param [String] appcode
170
- def check_appcode(sftp, appcode)
171
- path = remote_path(appcode)
172
- FastlaneCore::UI.message('Checking APPCODE')
173
- remote_mkdir(sftp, path)
174
- end
175
-
176
- # Checks/renames remote IPA
177
- #
178
- # @params sftp
179
- # @params [String] local_ipa_path
180
- def bump_ipa(sftp, local, appcode)
181
- remote = get_remote_ipa_path(local, appcode)
182
- FastlaneCore::UI.message('Checking remote IPA')
183
- begin
184
- sftp.stat!(remote) do |response|
185
- if response.ok?
186
- begin
187
- sftp.rename!(remote, remote + '.bak')
188
- rescue
189
- begin
190
- sftp.remove(remote + '.bak') # may fail if not existent
191
- FastlaneCore::UI.message('Removed ' + remote + '.bak')
192
- rescue
193
- sftp.rename!(remote, remote + '.bak')
194
- FastlaneCore::UI.message('Bumped to ' + remote + '.bak')
195
- end
196
- end
197
- end
198
- end
199
- rescue
200
- FastlaneCore::UI.message('No previous IPA found.')
201
- end
202
- end
203
-
204
- # Downloads remote manifest, self.appcode required by options.
205
- #
206
- # @param sftp
207
- # @param [String] remote_path
208
- # @returns [JSON] json or nil
209
- def download_manifest(sftp)
210
- FastlaneCore::UI.message('Checking remote Manifest')
211
- json = nil
212
- remote_manifest_path = remote_manifest_path(appcode)
213
- begin
214
- sftp.stat!(remote_manifest_path) do |response|
215
- if response.ok?
216
- FastlaneCore::UI.success('Loading remote manifest:')
217
- manifest = sftp.download!(remote_manifest_path)
218
- json = JSON.parse(manifest)
219
- end
220
- end
221
- rescue
222
- FastlaneCore::UI.message('No previous Manifest found')
223
- end
224
- json
225
- end
226
-
227
- # Upload current IPA
228
- #
229
- # @param sftp
230
- # @param [String] local_ipa_path
231
- # @param [String] remote_ipa_path
232
- def upload_ipa(sftp, local_ipa_path, remote_ipa_path)
233
- msg = "[Uploading IPA] #{local_ipa_path} to #{remote_ipa_path}"
234
- FastlaneCore::UI.message(msg)
235
- result = sftp.upload!(local_ipa_path, remote_ipa_path) do |event, _uploader, *_args|
236
- case event
237
- when :open then
238
- putc '.'
239
- when :put then
240
- putc '.'
241
- $stdout.flush
242
- when :close then
243
- puts "\n"
244
- when :finish then
245
- FastlaneCore::UI.success('IPA upload successful')
246
- end
247
- end
248
- end
249
-
250
- # Upload current manifest.json
251
- #
252
- # @param sftp
253
- # @param [String] manifest_path
254
- # @param [String] remote_manifest_path
255
- def upload_manifest(sftp, local_path, remote_path)
256
- msg = '[Uploading Manifest] ' + local_path + ' to ' + remote_path
257
- FastlaneCore::UI.message(msg)
258
- result = sftp.upload!(local_path, remote_path) do |event, _uploader, *_args|
259
- case event
260
- when :finish then
261
- FastlaneCore::UI.success('Manifest upload successful')
262
- end
263
- end
264
- end
265
-
266
- def get_remote_ipa_path(local_ipa_path, appcode)
267
- remote_path(appcode) + File.basename(local_ipa_path)
268
- end
269
-
270
- def remote_path(appcode)
271
- generate_remote_path + appcode + '/'
272
- end
273
-
274
- def remote_manifest_path(appcode)
275
- remote_path(appcode) + 'manifest.json'
276
- end
277
-
278
- def generate_remote_path
279
- '/home/' + user + '/repo/apps/'
280
- end
281
-
282
- def remote_mkdir(sftp, remote_path)
283
- sftp.mkdir remote_path
284
- rescue Net::SFTP::StatusException => e
285
- raise if e.code != 11
286
- msg = "Remote dir #{remote_path} exists."
287
- FastlaneCore::UI.message(msg)
288
- end
289
-
290
- # Private methods - Local Operations
291
-
292
- def load_rsa_key(rsa_keypath)
293
- File.open(rsa_keypath, 'r') do |file|
294
- rsa_key = nil
295
- rsa_key = [file.read]
296
- if !rsa_key.nil?
297
- FastlaneCore::UI.success('Successfully loaded RSA key...')
298
- else
299
- FastlaneCore::UI.user_error!('Failed to load RSA key...')
300
- end
301
- rsa_key
302
- end
303
- end
304
- end
305
- end
306
- end