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.
- checksums.yaml +4 -4
- data/README.md +11 -9
- data/lib/apprepo.rb +12 -25
- data/lib/apprepo/analyser.rb +26 -0
- data/lib/apprepo/commands_generator.rb +50 -39
- data/lib/apprepo/detect_values.rb +8 -20
- data/lib/apprepo/loader.rb +4 -2
- data/lib/apprepo/manifest.rb +9 -2
- data/lib/apprepo/options.rb +34 -14
- data/lib/apprepo/runner.rb +20 -19
- data/lib/apprepo/setup.rb +8 -9
- data/lib/apprepo/uploader.rb +208 -124
- data/lib/apprepo/version.rb +3 -3
- metadata +5 -28
- data/lib/apprepo/download_metadata.rb +0 -44
- data/lib/apprepo/upload_assets.rb +0 -22
- data/lib/apprepo/upload_descriptor.rb +0 -12
- data/lib/apprepo/upload_metadata.rb +0 -192
data/lib/apprepo/runner.rb
CHANGED
@@ -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,
|
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('
|
16
|
-
verify_version
|
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
|
-
|
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
|
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
|
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
|
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
|
-
|
54
|
-
|
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
|
data/lib/apprepo/setup.rb
CHANGED
@@ -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
|
-
|
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
|
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
|
-
#
|
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
|
-
|
28
|
-
# deliver => apprepo??
|
27
|
+
# apprepo (was deliver)
|
29
28
|
end
|
30
29
|
|
31
|
-
def
|
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
|
35
|
-
|
33
|
+
UI.success("TODO: DOWNLOAD MANIFEST'")
|
34
|
+
AppRepo::Uploader.download_metadata(options, path)
|
36
35
|
end
|
37
36
|
|
38
37
|
def run(options)
|
data/lib/apprepo/uploader.rb
CHANGED
@@ -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
|
-
|
32
|
-
|
33
|
-
|
34
|
-
self.
|
35
|
-
self.
|
36
|
-
self.
|
37
|
-
self.
|
38
|
-
self.
|
39
|
-
self.
|
40
|
-
|
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],
|
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
|
-
#
|
52
|
+
# Upload IPA & manifest
|
47
53
|
#
|
48
54
|
|
49
|
-
|
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(
|
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
|
-
|
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
|
-
|
57
|
-
|
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
|
-
|
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
|
-
|
64
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
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
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
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
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
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
|
-
|
163
|
-
|
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
|
-
|
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
|
171
|
-
|
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
|
177
|
-
|
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
|
-
|
264
|
+
def remote_mkdir(sftp, remote_path)
|
183
265
|
sftp.mkdir remote_path
|
184
266
|
rescue Net::SFTP::StatusException => e
|
185
|
-
if e.code
|
186
|
-
|
187
|
-
|
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
|
272
|
+
# Private methods - Local Operations
|
193
273
|
|
194
274
|
def load_rsa_key(rsa_keypath)
|
195
|
-
File.open(
|
275
|
+
File.open(rsa_keypath, 'r') do |file|
|
276
|
+
rsa_key = nil
|
196
277
|
rsa_key = [file.read]
|
197
|
-
|
198
|
-
|
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
|