apprepo 0.0.6 → 0.0.8

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,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