apprepo 0.0.6 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,64 +1,65 @@
1
1
  require_relative 'uploader'
2
2
 
3
3
  module AppRepo
4
+ # Responsible for running
4
5
  class Runner
5
6
  attr_accessor :options
6
7
 
7
8
  def initialize(options)
8
- UI.message('[AppRepo:Runner] Initializing...')
9
9
  self.options = options
10
10
  AppRepo::DetectValues.new.run!(self.options)
11
- # FastlaneCore::PrintTable.print_values(config: options, hide_keys: [:app], mask_keys: ['app_review_information.demo_password'], title: "deliver #{AppRepo::VERSION} Summary")
11
+ # FastlaneCore::PrintTable.print_values(config: options,
12
+ # hide_keys: [:app], mask_keys: [],
13
+ # title: "deliver #{AppRepo::VERSION} Summary")
12
14
  end
13
15
 
16
+ # rubocop:disable Metrics/AbcSize
17
+ # rubocop:disable Metrics/CyclomaticComplexity
14
18
  def run
15
- UI.success('[AppRepo:Runner] Running!')
16
- verify_version if options[:app_version].to_s.length > 0
19
+ UI.success('AppRepo SFTP Uploader running...')
20
+ verify_version unless options[:app_version].to_s.empty?
17
21
  upload_metadata
18
-
19
- has_binary = (options[:ipa] || options[:pkg])
22
+ has_binary = options[:ipa]
20
23
  if !options[:skip_binary_upload] && !options[:build_number] && has_binary
21
24
  upload_binary
22
25
  end
23
-
24
26
  UI.success('Finished the upload to AppRepo.')
25
-
26
- notify if options[:notify]
27
+ notify unless options[:notify].nil?
27
28
  end
28
29
 
29
30
  # Make sure the version on AppRepo matches the one in the ipa
30
31
  # If not, the new version will automatically be created
31
32
  def verify_version
32
33
  app_version = options[:app_version]
33
- UI.message("TODO: Make sure the latest version on AppRepo matches '#{app_version}' from the ipa file...")
34
+ msg = "TODO: Test if AppRepo matches '#{app_version}' from the IPA..."
35
+ UI.message(msg)
34
36
 
35
37
  # changed = options[:app].ensure_version!(app_version)
36
38
  # if changed
37
39
  # UI.success("Successfully set the version to '#{app_version}'")
38
40
  # else
39
- # UI.success("'#{app_version}' is the latest version on iTunes Connect")
41
+ # UI.success("'#{app_version}' is the latest version on AppRepo")
40
42
  # end
41
43
  end
42
44
 
43
- # Upload all metadata, screenshots, pricing information, etc. to iTunes Connect
45
+ # Upload all metadata, screenshots, pricing information, etc. to AppRepo
44
46
  def upload_metadata
45
47
  #
46
48
  end
47
49
 
48
- # Upload the binary to iTunes Connect
50
+ # Upload the binary to AppRepo
49
51
  def upload_binary
50
- UI.message('Uploading binary to AppRepo')
51
52
  if options[:ipa]
52
- AppRepo::Uploader.new(options)
53
- # result = transporter.upload(options[:app].apple_id, package_path)
54
- # UI.user_error!('Could not upload binary to iTunes Connect. Check out the error above') unless result
53
+ uploader = AppRepo::Uploader.new(options)
54
+ result = uploader.upload
55
+ msg = 'Binary upload failed. Check out the error above'
56
+ UI.user_error!(msg) unless result
55
57
  end
56
58
  end
57
59
 
58
60
  def notify
59
61
  # should be in metadata
62
+ UI.message('TODO: Missing implementation for AppRepo Push Notifier')
60
63
  end
61
-
62
- private
63
64
  end
64
65
  end
@@ -1,21 +1,21 @@
1
1
  module AppRepo
2
+ # Responsible for setting up the Repofile configuration
2
3
  class Setup
3
4
  def setup_apprepo(file_path, data, _apprepo_path, _options)
4
5
  UI.message('[AppRepo:Setup] Setting up...')
5
6
  File.write(file_path, data)
6
7
 
7
8
  # TODO: implement later
8
- # download_metadata(apprepo_path, options)
9
+ download_manifest(apprepo_path, options)
9
10
 
10
11
  UI.success("NOT! created new Repofile at path '#{file_path}'")
11
12
  end
12
13
 
13
- # This method takes care of creating a new 'apprepo' folder, containg the app metadata
14
+ # This method takes care of creating a new 'apprepo' folder with metadata
14
15
  # and screenshots folders
15
16
  def generate_apprepo_file(_apprepo_path, options)
16
- #
17
17
  # v = options[:app].latest_version
18
- # generate_metadata_files(v, File.join(apprepo_path, 'metadata'))
18
+ # generate_apprepo_file(v, File.join(apprepo_path, 'manifest.json'))
19
19
 
20
20
  # Generate the final Repofile here
21
21
  gem_path = Helper.gem_path('apprepo')
@@ -24,15 +24,14 @@ module AppRepo
24
24
  apprepo.gsub!('[[APPREPO_IPA_PATH]]', options[:app].file_path)
25
25
  apprepo.gsub!('[[APP_VERSION]]', options[:app].version)
26
26
  apprepo.gsub!('[[APP_NAME]]', options[:app].name)
27
- UI.user_error("TODO: ADJUST Repofile'")
28
- # deliver => apprepo??
27
+ # apprepo (was deliver)
29
28
  end
30
29
 
31
- def download_metadata(apprepo_path, _options)
30
+ def download_manifest(apprepo_path, _options)
32
31
  path = File.join(apprepo_path, 'metadata')
33
32
  FileUtils.mkdir_p(path)
34
- UI.success("TODO: DOWNLOAD METADATA'")
35
- # AppRepo::DownloadManifest.run(options, path)
33
+ UI.success("TODO: DOWNLOAD MANIFEST'")
34
+ AppRepo::Uploader.download_metadata(options, path)
36
35
  end
37
36
 
38
37
  def run(options)
@@ -10,9 +10,11 @@ require 'fastlane_core'
10
10
  require 'fastlane_core/languages'
11
11
 
12
12
  require_relative 'options'
13
- require_relative 'upload_descriptor' # will deprecate, should have contain Repofile data but it will be in options as expected
14
13
 
15
14
  module AppRepo
15
+ # rubocop:disable Metrics/ClassLength
16
+
17
+ # Responsible for performing the SFTP operation
16
18
  class Uploader
17
19
  attr_accessor :options
18
20
 
@@ -28,176 +30,258 @@ module AppRepo
28
30
  attr_accessor :manifest_path
29
31
  attr_accessor :appcode
30
32
 
31
- def initialize
32
- Fastlane::UI.message('[AppRepo:Uploader] Initializing...')
33
- self.host = 'repo.teacloud.net'
34
- self.user = 'circle'
35
- self.password = 'circle'
36
- self.rsa_keypath = '../assets/circle.key'
37
- self.ipa_path = '../sampleapp.ipa'
38
- self.manifest_path = '../assets/example_manifest.json'
39
- self.appcode = 'APPREPO'
40
- # self.options = options
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.user = options[:repo_user]
39
+ self.password = options[:repo_password]
40
+ self.rsa_keypath = options[:repo_key] # '../assets/circle.key'
41
+ self.ipa_path = options[:ipa] # '../sampleapp.ipa'
42
+ self.manifest_path = options[:manifest_path] # '../assets/example_manifest.json'
43
+ self.appcode = options[:appcode]
44
+
41
45
  # AppRepo::Uploader.new.run!
42
- # FastlaneCore::PrintTable.print_values(config: nil , hide_keys: [:app], mask_keys: ['app_review_information.demo_password'], title: "deliver #{AppRepo::VERSION} Summary") # options
46
+ # FastlaneCore::PrintTable.print_values(config: nil , hide_keys: [:app],
47
+ # mask_keys: ['app_review_information.demo_password'],
48
+ # title: "deliver #{AppRepo::VERSION} Summary") # options
43
49
  end
44
50
 
45
51
  #
46
- # Main
52
+ # Upload IPA & manifest
47
53
  #
48
54
 
49
- def run
55
+ # rubocop:disable Metrics/AbcSize
56
+ # rubocop:disable Metrics/MethodLength
57
+ def upload
50
58
  # Login & Upload IPA with metadata using RSA key or username/password
51
- rsa_key = load_rsa_key(self.rsa_keypath)
59
+ rsa_key = load_rsa_key(rsa_keypath)
60
+ success = false
61
+ if !rsa_key.nil?
62
+ FastlaneCore::UI.message('Logging in with RSA key...')
63
+ Net::SSH.start(host, user, key_data: rsa_key, keys_only: true) do |ssh|
64
+ FastlaneCore::UI.message('Uploading IPA & Manifest...')
65
+ success = ssh_sftp_upload(ssh, ipa_path, manifest_path)
66
+ end
67
+ else
68
+ FastlaneCore::UI.message('Logging in...')
69
+ Net::SSH.start(host, user, password: password) do |ssh|
70
+ self.ssh_session = ssh
71
+ FastlaneCore::UI.message('Logged in, uploading IPA & Manifest...')
72
+ success = ssh_sftp_upload(ssh, ipa_path, manifest_path)
73
+ end
74
+ end
75
+ success
76
+ end
77
+
78
+ #
79
+ # Download metadata only
80
+ #
81
+
82
+ # rubocop:disable Metrics/AbcSize
83
+ # rubocop:disable Metrics/MethodLength
84
+ def download_metadata
85
+ rsa_key = load_rsa_key(rsa_keypath)
52
86
  if rsa_key?
53
- #if !rsa_key.nil?
54
- Fastlane::UI.message('[AppRepo:Uploader] Logging in with RSA key ' + rsa_keypath)
87
+ FastlaneCore::UI.message('Logging in with RSA key...')
55
88
  Net::SSH.start(host, user, key_data: rsa_key, keys_only: true) do |ssh|
56
- Fastlane::UI.message('[AppRepo:Uploader] Logged in, uploading UPA & Manifest...')
57
- ssh_sftp_upload(ssh, ipa_path, manifest_path)
89
+ self.ssh_session = ssh
90
+ FastlaneCore::UI.message('Uploading UPA & Manifest...')
91
+ ssh_sftp_download(ssh, manifest_path)
58
92
  end
59
93
  else
60
- #  Login with
61
- Fastlane::UI.message('[AppRepo:Uploader] Logging in with username ' + user + ' and password *****...')
94
+ FastlaneCore::UI.message('Logging in...')
62
95
  Net::SSH.start(host, user, password: password) do |ssh|
63
- Fastlane::UI.message('Logged in, uploading UPA & Manifest...')
64
- ssh_sftp_upload(ssh, ipa_path, manifest_path)
96
+ self.ssh_session = ssh
97
+ FastlaneCore::UI.message('Logged in, uploading UPA & Manifest...')
98
+ ssh_sftp_download(ssh, manifest_path)
65
99
  end
66
100
  end
67
101
  end
68
102
 
103
+ private
104
+
105
+ def ssh_sftp_download(ssh, local_ipa_path, _manifest_path)
106
+ ssh.sftp.connect do |sftp|
107
+ break unless check_ipa(local_ipa_path)
108
+ FastlaneCore::UI.message('[Downloading] Will start...')
109
+ manifest = download_manifest(sftp)
110
+ puts '********************************************************'
111
+ puts JSON.pretty_generate(manifest)
112
+ puts '********************************************************'
113
+ end
114
+ end
115
+
69
116
  def ssh_sftp_upload(ssh, local_ipa_path, manifest_path)
70
117
  ssh.sftp.connect do |sftp|
118
+ break unless check_ipa(local_ipa_path)
119
+ check_appcode(sftp, appcode)
120
+ path = remote_path(appcode)
121
+ manifest = download_manifest(sftp)
122
+ puts JSON.pretty_generate(manifest) unless manifest.nil?
123
+ bump_ipa(sftp, local_ipa_path, appcode)
124
+ remote_ipa_path = get_remote_ipa_path(local_ipa_path, appcode)
125
+ upload_ipa(sftp, local_ipa_path, remote_ipa_path)
126
+ upload_manifest(sftp, manifest_path, remote_manifest_path(appcode))
127
+ # Lists the entries in a directory for verification
128
+ sftp.dir.foreach(path) do |entry|
129
+ FastlaneCore::UI.message(entry.longname)
130
+ end
131
+ end
132
+ end
71
133
 
72
- ipa_name = File.basename(local_ipa_path)
134
+ # Check IPA existence locally
135
+ #
136
+ # @param local_ipa_path
137
+ def check_ipa(local_ipa_path)
138
+ if File.exist?(local_ipa_path)
139
+ FastlaneCore::UI.important('IPA found at ' + local_ipa_path)
140
+ return true
141
+ else
142
+ FastlaneCore::UI.verbose('IPA at given path does not exist yet.')
143
+ return false
144
+ end
145
+ end
73
146
 
74
- if File.exist?(local_ipa_path)
75
- Fastlane::UI.message('[AppRepo:Uploader] Local IPA found at ' + local_ipa_path)
76
- else
77
- Fastlane::UI.message('[AppRepo:Uploader] IPA at given path does not exist!')
78
- return
79
- end
147
+ # Private methods - Remote Operations
80
148
 
81
- #
82
- # Check/create remote APPCODE directory
83
- # @params sftp, appcode;
84
- # @callees remote_path()
85
- #
86
-
87
- remote_path = get_remote_path + appcode
88
- Fastlane::UI.message('[AppRepo:Uploader] Checking APPCODE at: ' + remote_path)
89
- remote_mkdir(sftp, remote_path)
90
-
91
- #
92
- # Check/fetch remote MANIFEST
93
- # @params sftp, appcode;
94
- # @callees remote_path()
95
- #
96
-
97
- remote_manifest_path = remote_path + '/manifest.json'
98
-
99
- Fastlane::UI.message('[AppRepo:Uploader] Checking remote Manifest.')
100
- begin
101
- sftp.stat!(remote_manifest_path) do |response|
102
- if response.ok?
103
- Fastlane::UI.message('Reading existing Manifest.')
104
- sftp.file.open(remote_manifest_path, 'w') do |remote_manifest|
105
- manifest = remote_manifest.gets
106
- json = JSON.parse(manifest)
107
- UI.message('[AppRepo:Uploader] Opened file from sftp...')
108
- puts '****************************************************************'
109
- puts json
110
- puts '****************************************************************'
149
+ # Checks/creates remote APPCODE directory
150
+ # @param sftp
151
+ # @param [String] appcode
152
+ def check_appcode(sftp, appcode)
153
+ path = remote_path(appcode)
154
+ FastlaneCore::UI.message('Checking APPCODE')
155
+ remote_mkdir(sftp, path)
156
+ end
157
+
158
+ # Checks/renames remote IPA
159
+ #
160
+ # @params sftp
161
+ # @params [String] local_ipa_path
162
+ def bump_ipa(sftp, local, appcode)
163
+ remote = get_remote_ipa_path(local, appcode)
164
+ FastlaneCore::UI.message('Checking remote IPA')
165
+ begin
166
+ sftp.stat!(remote) do |response|
167
+ if response.ok?
168
+ begin
169
+ sftp.rename!(remote, remote + '.bak')
170
+ rescue
171
+ begin
172
+ sftp.remove(remote + '.bak') # may fail if not existent
173
+ FastlaneCore::UI.message('Removed ' + remote + '.bak')
174
+ rescue
175
+ sftp.rename!(remote, remote + '.bak')
176
+ FastlaneCore::UI.message('Bumped to ' + remote + '.bak')
111
177
  end
112
178
  end
113
179
  end
114
- rescue
115
- Fastlane::UI.message('[AppRepo:Uploader] No previous Manifest found.')
116
180
  end
181
+ rescue
182
+ FastlaneCore::UI.message('No previous IPA found.')
183
+ end
184
+ end
117
185
 
118
- #
119
- # Check/delete remote (rename from metadata later) IPA
120
- # @params sftp, appcode, local_ipa_path, ;
121
- # @callees get_remote_ipa_path()
122
- #
123
-
124
- remote_ipa_path = get_remote_ipa_path(local_ipa_path)
125
- Fastlane::UI.message('[AppRepo:Uploader] Checking remote IPA.')
126
- begin
127
- sftp.stat!(remote_ipa_path) do |response|
128
- if response.ok?
129
- Fastlane::UI.message('[AppRepo:Uploader] Removing existing IPA...')
130
- sftp.remove!(remote_ipa_path)
131
- end
186
+ # Downloads remote manifest, self.appcode required by options.
187
+ #
188
+ # @param sftp
189
+ # @param [String] remote_path
190
+ # @returns [JSON] json or nil
191
+ def download_manifest(sftp)
192
+ FastlaneCore::UI.message('Checking remote Manifest')
193
+ json = nil
194
+ remote_manifest_path = remote_manifest_path(appcode)
195
+ begin
196
+ sftp.stat!(remote_manifest_path) do |response|
197
+ if response.ok?
198
+ FastlaneCore::UI.success('Loading remote manifest:')
199
+ manifest = sftp.download!(remote_manifest_path)
200
+ json = JSON.parse(manifest)
132
201
  end
133
- rescue
134
- Fastlane::UI.message('[AppRepo:Uploader] No previous IPA found.')
135
202
  end
203
+ rescue
204
+ FastlaneCore::UI.message('No previous Manifest found')
205
+ end
206
+ json
207
+ end
136
208
 
137
- Fastlane::UI.message('[AppRepo:Uploader] Will upload IPA...')
138
-
139
- #
140
- # Upload current manifest.json
141
- # @params sftp, local_ipa_path, remote_ipa_path;
142
- # @callees get_remote_path()
143
- #
144
-
145
- path = File.dirname(__FILE__) + '/' + local_ipa_path
146
- Fastlane::UI.message('[AppRepo:Uploader] Uploading IPA: ' + path + ' to path ' + remote_ipa_path)
147
- sftp.upload!(path, remote_ipa_path)
148
-
149
- #
150
- # Upload current manifest.json
151
- # @params sftp, manifest_path, remote_manifest_path;
152
- # @callees get_remote_path()
153
- #
154
-
155
- Fastlane::UI.message('[AppRepo:Uploader] Uploading Manifest: ' + manifest_path + ' to path ' + remote_manifest_path)
156
- sftp.upload!(manifest_path, remote_manifest_path)
157
-
158
- #
159
- # Lists the entries in a directory for verification
160
- #
209
+ # Upload current IPA
210
+ #
211
+ # @param sftp
212
+ # @param [String] local_ipa_path
213
+ # @param [String] remote_ipa_path
214
+ def upload_ipa(sftp, local_ipa_path, remote_ipa_path)
215
+ msg = '[Uploading IPA] ' + local_ipa_path + ' to ' + remote_ipa_path
216
+ FastlaneCore::UI.message(msg)
217
+ result = sftp.upload!(local_ipa_path, remote_ipa_path) do |event, _uploader, *_args|
218
+ case event
219
+ when :open then
220
+ putc '.'
221
+ when :put then
222
+ putc '.'
223
+ $stdout.flush
224
+ when :close then
225
+ puts "\n"
226
+ when :finish then
227
+ FastlaneCore::UI.success('Upload successful!')
228
+ end
229
+ end
230
+ end
161
231
 
162
- sftp.dir.foreach(remote_path) do |entry|
163
- Fastlane::UI.message(entry.longname)
232
+ # Upload current manifest.json
233
+ #
234
+ # @param sftp
235
+ # @param [String] manifest_path
236
+ # @param [String] remote_manifest_path
237
+ def upload_manifest(sftp, local_path, remote_path)
238
+ msg = '[Uploading Manifest] ' + local_path + ' to ' + remote_path
239
+ FastlaneCore::UI.message(msg)
240
+ result = sftp.upload!(local_path, remote_path) do |event, _uploader, *_args|
241
+ case event
242
+ when :finish then
243
+ FastlaneCore::UI.success('Upload successful!')
164
244
  end
165
245
  end
166
246
  end
167
247
 
168
- # Private methods – Remote Operations
248
+ def get_remote_ipa_path(local_ipa_path, appcode)
249
+ remote_path(appcode) + File.basename(local_ipa_path)
250
+ end
251
+
252
+ def remote_path(appcode)
253
+ generate_remote_path + appcode + '/'
254
+ end
169
255
 
170
- def get_remote_ipa_path(ipa_path)
171
- path = get_remote_path + appcode + '/' + File.basename(ipa_path)
172
- Fastlane::UI.message('[AppRepo:Uploader] remote_ipa_path: ' + path)
173
- path
256
+ def remote_manifest_path(appcode)
257
+ remote_manifest_path = remote_path(appcode) + 'manifest.json'
174
258
  end
175
259
 
176
- def get_remote_path
177
- path = '/home/' + user + '/repo/apps/'
178
- Fastlane::UI.message('[AppRepo:Uploader] get_remote_path: ' + path)
179
- path
260
+ def generate_remote_path
261
+ '/home/' + user + '/repo/apps/'
180
262
  end
181
263
 
182
- def remote_mkdir(sftp, remote_path)
264
+ def remote_mkdir(sftp, remote_path)
183
265
  sftp.mkdir remote_path
184
266
  rescue Net::SFTP::StatusException => e
185
- if e.code == 11
186
- Fastlane::UI.message('[AppRepo:Uploader] Remote directory' + remote_path + ' already exists. OK...')
187
- else
188
- raise
189
- end
267
+ raise if e.code != 11
268
+ msg = 'Remote dir ' + remote_path + ' exists.'
269
+ FastlaneCore::UI.message(msg)
190
270
  end
191
271
 
192
- # Private methods Local Operations
272
+ # Private methods - Local Operations
193
273
 
194
274
  def load_rsa_key(rsa_keypath)
195
- File.open(File.dirname(__FILE__) + '/' + rsa_keypath, 'r') do |file|
275
+ File.open(rsa_keypath, 'r') do |file|
276
+ rsa_key = nil
196
277
  rsa_key = [file.read]
197
- Fastlane::UI.message('[AppRepo:Uploader] Successfully loaded RSA key...') unless rsa_key.nil?
198
- return rsa_key
278
+ if !rsa_key.nil?
279
+ FastlaneCore::UI.success('Successfully loaded RSA key...')
280
+ else
281
+ FastlaneCore::UI.user_error!('Failed to load RSA key...')
282
+ end
283
+ rsa_key
199
284
  end
200
285
  end
201
-
202
286
  end
203
287
  end