fastlane-plugin-apprepo 0.5.4 → 0.5.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,29 +0,0 @@
1
-
2
- module Fastlane
3
- module Apprepo
4
- # This class is responsible for detecting values from IPA.
5
- class DetectValues
6
- def run!(options)
7
- find_app_identifier(options)
8
- find_version(options)
9
- end
10
-
11
- def find_app_identifier(options)
12
- return if options[:app_identifier]
13
- if options[:ipa]
14
- # identifier = Apprepo::Analyser.fetch_app_identifier(options[:ipa])
15
- end
16
- options[:app_identifier] = identifier unless identifier.to_s.empty?
17
- input_message = 'The Bundle Identifier of your App: '
18
- options[:app_identifier] ||= UI.input(input_message)
19
- end
20
-
21
- def find_version(options)
22
- unless options[:ipa].nil?
23
- opt = Apprepo::Analyser.new(options)
24
- options[:app_version] ||= opt.fetch_app_version(options[:ipa])
25
- end
26
- end
27
- end
28
- end
29
- end
@@ -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,125 +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 server'),
36
- FastlaneCore::ConfigItem.new(key: :repo_port,
37
- short_option: '-P',
38
- optional: false,
39
- env_name: 'APPREPO_PORT',
40
- description: 'SSH port of your server'),
41
- FastlaneCore::ConfigItem.new(key: :repo_user,
42
- short_option: '-u',
43
- optional: false,
44
- env_name: 'APPREPO_USER',
45
- description: 'USER of your server'),
46
- FastlaneCore::ConfigItem.new(key: :repo_password,
47
- short_option: '-p',
48
- optional: true,
49
- env_name: 'APPREPO_PASSWORD',
50
- description: 'PASSWORD for your server (not for production)',
51
- conflicting_options: [:repo_key],
52
- conflict_block: proc do |value|
53
- UI.user_error!("You can't use 'password' and '#{value.key}' options in one run.")
54
- end),
55
- FastlaneCore::ConfigItem.new(key: :repo_key,
56
- short_option: '-k',
57
- optional: false,
58
- env_name: 'APPREPO_KEY',
59
- description: 'RSA key for your Apprepo server',
60
- conflicting_options: [:repo_password],
61
- conflict_block: proc do |value|
62
- UI.user_error!("You can't use 'repo_key' and '#{value.key}' options in one run.")
63
- end),
64
- FastlaneCore::ConfigItem.new(key: :repo_description,
65
- short_option: '-d',
66
- optional: true,
67
- description: 'Long detailed description for your Apprepo server',
68
- default_value: ''),
69
- FastlaneCore::ConfigItem.new(key: :repo_summary,
70
- short_option: '-s',
71
- optional: true,
72
- description: 'Short description for your Apprepo server',
73
- default_value: ''),
74
- FastlaneCore::ConfigItem.new(key: :manifest_path,
75
- short_option: '-m',
76
- description: 'Path to the folder containing the metadata files',
77
- optional: true),
78
- FastlaneCore::ConfigItem.new(key: :repo_title,
79
- short_option: '-a',
80
- description: 'Title of the app',
81
- optional: false),
82
- FastlaneCore::ConfigItem.new(key: :appcode,
83
- short_option: '-o',
84
- description: 'Name of the app on Apprepo',
85
- optional: false),
86
- FastlaneCore::ConfigItem.new(key: :skip_binary_upload,
87
- description: 'Skip uploading an ipa or to Apprepo',
88
- is_string: false,
89
- default_value: false),
90
- FastlaneCore::ConfigItem.new(key: :app_version,
91
- short_option: '-z',
92
- description: 'The version that should be edited or created',
93
- optional: true),
94
- FastlaneCore::ConfigItem.new(key: :skip_manifest,
95
- description: "Don't upload the metadata (e.g. title, description), this will still upload screenshots",
96
- is_string: false,
97
- default_value: false),
98
- FastlaneCore::ConfigItem.new(key: :notify,
99
- description: 'Notify Apprepo users on update',
100
- is_string: false,
101
- default_value: false),
102
- FastlaneCore::ConfigItem.new(key: :build_number,
103
- short_option: '-n',
104
- description: 'If set the given build number (already uploaded to iTC) will be used instead of the current built one',
105
- optional: true,
106
- conflicting_options: [:ipa],
107
- conflict_block: proc do |value|
108
- UI.user_error!("You can't use 'build_number' and '#{value.key}' options in one run.")
109
- end),
110
-
111
- # App Metadata
112
- # Non Localised
113
- FastlaneCore::ConfigItem.new(key: :app_icon,
114
- description: 'Metadata: The path to the app icon',
115
- optional: true,
116
- short_option: '-l',
117
- verify_block: proc do |value|
118
- UI.user_error!("Could not find png file at path '#{value}'") unless File.exist?(value)
119
- UI.user_error!("'#{value}' doesn't seem to be a png file") unless value.end_with?('.png')
120
- end)
121
- ]
122
- end
123
- end
124
- end
125
- end
@@ -1,68 +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
- end
24
- UI.success('Finished the upload to Apprepo.')
25
- notify unless options[:notify].nil?
26
- end
27
-
28
- # Make sure the version on Apprepo matches the one in the ipa
29
- # If not, the new version will automatically be created
30
- def verify_version
31
- app_version = options[:app_version]
32
- msg = "TODO: Test if Apprepo matches '#{app_version}' from the IPA..."
33
- UI.message(msg)
34
-
35
- # changed = options[:app].ensure_version!(app_version)
36
- # if changed
37
- # UI.success("Successfully set the version to '#{app_version}'")
38
- # else
39
- # UI.success("'#{app_version}' is the latest version on Apprepo")
40
- # end
41
- end
42
-
43
- def download_manifest
44
- if options[:manifest_path]
45
- uploader = Apprepo::Uploader.new(options)
46
- result = uploader.download_manifest_only
47
- msg = 'Metadata download failed. Check out the error above.'
48
- UI.user_error!(msg) unless result
49
- end
50
- end
51
-
52
- # Upload the binary to Apprepo
53
- def upload_binary
54
- if options[:ipa]
55
- uploader = Apprepo::Uploader.new(options)
56
- result = uploader.upload
57
- msg = 'Binary upload failed. Check out the error above.'
58
- UI.user_error!(msg) unless result
59
- end
60
- end
61
-
62
- def notify
63
- # should be in metadata
64
- # UI.command_output('TODO: Missing implementation for Apprepo Push Notifier')
65
- end
66
- end
67
- end
68
- 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 :user
26
- attr_accessor :port
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] # 'repo.teacloud.net'
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_user and repo_pasdword 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