apprepo 0.0.2 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +26 -23
- data/lib/Repofile +40 -0
- data/lib/apprepo.rb +39 -11
- data/lib/apprepo/commands_generator.rb +108 -0
- data/lib/apprepo/detect_values.rb +38 -0
- data/lib/apprepo/download_metadata.rb +44 -0
- data/lib/apprepo/loader.rb +11 -0
- data/lib/apprepo/manifest.rb +26 -30
- data/lib/apprepo/options.rb +98 -0
- data/lib/apprepo/runner.rb +77 -0
- data/lib/apprepo/setup.rb +49 -0
- data/lib/apprepo/upload_assets.rb +22 -0
- data/lib/apprepo/upload_descriptor.rb +8 -9
- data/lib/apprepo/upload_metadata.rb +192 -0
- data/lib/apprepo/uploader.rb +80 -54
- data/lib/apprepo/version.rb +2 -2
- data/lib/test.rb +27 -26
- metadata +21 -31
data/lib/apprepo/manifest.rb
CHANGED
@@ -1,39 +1,35 @@
|
|
1
1
|
module AppRepo
|
2
|
+
class Manifest
|
3
|
+
#
|
4
|
+
# Translated internal key names from Fastlane to AppRepo
|
5
|
+
#
|
2
6
|
|
3
|
-
|
7
|
+
attr_accessor :appcode # AppRepo Internal Code
|
8
|
+
attr_accessor :filename # IPA file name
|
9
|
+
attr_accessor :bundle_identifier # app_identifier
|
10
|
+
attr_accessor :bundle_version # app_version
|
11
|
+
attr_accessor :title # app_name
|
12
|
+
attr_accessor :subtitle # app_description
|
13
|
+
attr_accessor :notify # will send push notification / slack
|
4
14
|
|
5
|
-
|
6
|
-
|
7
|
-
|
15
|
+
def initialize(appcode)
|
16
|
+
self.appcode = appcode
|
17
|
+
UI.message('Initializing "AppRepo:Manifest requies at least APPCODE :"' + self.appcode)
|
18
|
+
end
|
8
19
|
|
9
|
-
|
10
|
-
|
11
|
-
attr_accessor :bundle_identifier # app_identifier
|
12
|
-
attr_accessor :bundle_version # app_version
|
13
|
-
attr_accessor :title # app_name
|
14
|
-
attr_accessor :subtitle # app_description
|
15
|
-
attr_accessor :notify # will send push notification / slack
|
16
|
-
|
17
|
-
def initialize (appcode)
|
18
|
-
self.appcode = appcode
|
19
|
-
puts 'Initializing "AppRepo:Manifest requies at least APPCODE :"'+self.appcode
|
20
|
-
end
|
21
|
-
|
22
|
-
# Provide JSON serialized data
|
23
|
-
def getJSON
|
20
|
+
# Provide JSON serialized data
|
21
|
+
def getJSON
|
24
22
|
structure = {
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
23
|
+
appcode: appcode,
|
24
|
+
filename: filename,
|
25
|
+
bundle_identifier: bundle_identifier,
|
26
|
+
bundle_version: bundle_version,
|
27
|
+
title: title,
|
28
|
+
subtitle: subtitle,
|
29
|
+
notify: notify
|
32
30
|
}
|
33
|
-
|
31
|
+
|
34
32
|
fputs structure
|
33
|
+
end
|
35
34
|
end
|
36
|
-
|
37
|
-
end
|
38
35
|
end
|
39
|
-
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'fastlane_core'
|
2
|
+
|
3
|
+
module AppRepo
|
4
|
+
class Options
|
5
|
+
def self.available_options
|
6
|
+
[
|
7
|
+
FastlaneCore::ConfigItem.new(key: :ipa,
|
8
|
+
short_option: '-i',
|
9
|
+
optional: true,
|
10
|
+
env_name: 'APPREPO_IPA_PATH',
|
11
|
+
description: 'Path to your ipa file',
|
12
|
+
default_value: Dir['*.ipa'].first,
|
13
|
+
verify_block: proc do |value|
|
14
|
+
UI.user_error!("Could not find ipa file at path '#{value}'") unless File.exist?(value)
|
15
|
+
UI.user_error!("'#{value}' doesn't seem to be an ipa file") unless value.end_with?('.ipa')
|
16
|
+
end,
|
17
|
+
conflicting_options: [:pkg],
|
18
|
+
conflict_block: proc do |value|
|
19
|
+
UI.user_error!("You can't use 'ipa' and '#{value.key}' options in one run.")
|
20
|
+
end),
|
21
|
+
FastlaneCore::ConfigItem.new(key: :app_identifier,
|
22
|
+
short_option: '-b',
|
23
|
+
optional: false,
|
24
|
+
env_name: 'APPREPO_APP_ID',
|
25
|
+
description: 'Your bundle identifier',
|
26
|
+
default_value: ""),
|
27
|
+
FastlaneCore::ConfigItem.new(key: :app_code,
|
28
|
+
short_option: '-c',
|
29
|
+
optional: true,
|
30
|
+
env_name: 'APPREPO_APPCODE',
|
31
|
+
description: 'APPCODE value for apprepo'),
|
32
|
+
FastlaneCore::ConfigItem.new(key: :repo_url,
|
33
|
+
short_option: '-r',
|
34
|
+
optional: false,
|
35
|
+
env_name: 'APPREPO_URL',
|
36
|
+
description: 'URL of your Apprepo server'),
|
37
|
+
FastlaneCore::ConfigItem.new(key: :repo_user,
|
38
|
+
short_option: '-u',
|
39
|
+
optional: false,
|
40
|
+
env_name: 'APPREPO_USER',
|
41
|
+
description: 'USER of your Apprepo server'),
|
42
|
+
FastlaneCore::ConfigItem.new(key: :repo_key,
|
43
|
+
short_option: '-k',
|
44
|
+
optional: false,
|
45
|
+
env_name: 'APPREPO_KEY',
|
46
|
+
description: 'RSA key for your Apprepo server'),
|
47
|
+
FastlaneCore::ConfigItem.new(key: :repo_description,
|
48
|
+
short_option: '-d',
|
49
|
+
optional: true,
|
50
|
+
env_name: 'APPREPO_DESCRIPTION',
|
51
|
+
description: 'Long description for your Apprepo server'),
|
52
|
+
FastlaneCore::ConfigItem.new(key: :metadata_path,
|
53
|
+
short_option: '-m',
|
54
|
+
description: 'Path to the folder containing the metadata files',
|
55
|
+
optional: true),
|
56
|
+
FastlaneCore::ConfigItem.new(key: :meta_title,
|
57
|
+
short_option: '-a',
|
58
|
+
description: 'Name of the app',
|
59
|
+
optional: true),
|
60
|
+
FastlaneCore::ConfigItem.new(key: :skip_binary_upload,
|
61
|
+
description: 'Skip uploading an ipa or pkg to iTunes Connect',
|
62
|
+
is_string: false,
|
63
|
+
default_value: false),
|
64
|
+
FastlaneCore::ConfigItem.new(key: :app_version,
|
65
|
+
short_option: '-z',
|
66
|
+
description: 'The version that should be edited or created',
|
67
|
+
optional: true),
|
68
|
+
FastlaneCore::ConfigItem.new(key: :skip_metadata,
|
69
|
+
description: "Don't upload the metadata (e.g. title, description), this will still upload screenshots",
|
70
|
+
is_string: false,
|
71
|
+
default_value: false),
|
72
|
+
FastlaneCore::ConfigItem.new(key: :notify,
|
73
|
+
description: "Notify AppRepo users on update",
|
74
|
+
is_string: false,
|
75
|
+
default_value: false),
|
76
|
+
FastlaneCore::ConfigItem.new(key: :build_number,
|
77
|
+
short_option: '-n',
|
78
|
+
description: 'If set the given build number (already uploaded to iTC) will be used instead of the current built one',
|
79
|
+
optional: true,
|
80
|
+
conflicting_options: [:ipa, :pkg],
|
81
|
+
conflict_block: proc do |value|
|
82
|
+
UI.user_error!("You can't use 'build_number' and '#{value.key}' options in one run.")
|
83
|
+
end),
|
84
|
+
|
85
|
+
# App Metadata
|
86
|
+
# Non Localised
|
87
|
+
FastlaneCore::ConfigItem.new(key: :app_icon,
|
88
|
+
description: 'Metadata: The path to the app icon',
|
89
|
+
optional: true,
|
90
|
+
short_option: '-l',
|
91
|
+
verify_block: proc do |value|
|
92
|
+
UI.user_error!("Could not find png file at path '#{value}'") unless File.exist?(value)
|
93
|
+
UI.user_error!("'#{value}' doesn't seem to be a png file") unless value.end_with?('.png')
|
94
|
+
end)
|
95
|
+
]
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module AppRepo
|
2
|
+
class Runner
|
3
|
+
attr_accessor :options
|
4
|
+
|
5
|
+
def initialize(options)
|
6
|
+
UI.message('[AppRepo:Runner] Initializing...')
|
7
|
+
self.options = options
|
8
|
+
#login
|
9
|
+
AppRepo::DetectValues.new.run!(self.options)
|
10
|
+
#FastlaneCore::PrintTable.print_values(config: options, hide_keys: [:app], mask_keys: ['app_review_information.demo_password'], title: "deliver #{AppRepo::VERSION} Summary")
|
11
|
+
end
|
12
|
+
|
13
|
+
def login
|
14
|
+
#UI.message("Login to AppRepo (#{options[:username]})")
|
15
|
+
#AppRepo::Server.login(options[:username])
|
16
|
+
#AppRepo::Server.select_app
|
17
|
+
#UI.message('Login successful')
|
18
|
+
end
|
19
|
+
|
20
|
+
def run
|
21
|
+
verify_version if options[:app_version].to_s.length > 0
|
22
|
+
upload_metadata
|
23
|
+
|
24
|
+
has_binary = (options[:ipa] || options[:pkg])
|
25
|
+
if !options[:skip_binary_upload] && !options[:build_number] && has_binary
|
26
|
+
upload_binary
|
27
|
+
end
|
28
|
+
|
29
|
+
UI.success('Finished the upload to AppRepo')
|
30
|
+
|
31
|
+
notify if options[:notify]
|
32
|
+
end
|
33
|
+
|
34
|
+
# Make sure the version on AppRepo matches the one in the ipa
|
35
|
+
# If not, the new version will automatically be created
|
36
|
+
def verify_version
|
37
|
+
app_version = options[:app_version]
|
38
|
+
UI.message("TODO: Make sure the latest version on AppRepo matches '#{app_version}' from the ipa file...")
|
39
|
+
|
40
|
+
#changed = options[:app].ensure_version!(app_version)
|
41
|
+
#if changed
|
42
|
+
# UI.success("Successfully set the version to '#{app_version}'")
|
43
|
+
#else
|
44
|
+
# UI.success("'#{app_version}' is the latest version on iTunes Connect")
|
45
|
+
#end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Upload all metadata, screenshots, pricing information, etc. to iTunes Connect
|
49
|
+
def upload_metadata
|
50
|
+
#
|
51
|
+
end
|
52
|
+
|
53
|
+
# Upload the binary to iTunes Connect
|
54
|
+
def upload_binary
|
55
|
+
UI.message('Uploading binary to iTunes Connect')
|
56
|
+
if options[:ipa]
|
57
|
+
#package_path = FastlaneCore::IpaUploadPackageBuilder.new.generate(
|
58
|
+
# app_id: options[:app].apple_id,
|
59
|
+
# ipa_path: options[:ipa],
|
60
|
+
# package_path: '/tmp'
|
61
|
+
puts "TODO: Build package path without IpaUploadPackageBuilder"
|
62
|
+
|
63
|
+
end
|
64
|
+
|
65
|
+
#transporter = FastlaneCore::ItunesTransporter.new(options[:username])
|
66
|
+
#result = transporter.upload(options[:app].apple_id, package_path)
|
67
|
+
#UI.user_error!('Could not upload binary to iTunes Connect. Check out the error above') unless result
|
68
|
+
end
|
69
|
+
|
70
|
+
def notify
|
71
|
+
# should be in metadata
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module AppRepo
|
2
|
+
class Setup
|
3
|
+
|
4
|
+
def setup_apprepo(file_path, data, _apprepo_path, _options)
|
5
|
+
UI.message('[AppRepo:Setup] Setting up...')
|
6
|
+
File.write(file_path, data)
|
7
|
+
|
8
|
+
# TODO: implement later
|
9
|
+
# download_metadata(apprepo_path, options)
|
10
|
+
|
11
|
+
UI.success("NOT! created new Repofile at path '#{file_path}'")
|
12
|
+
end
|
13
|
+
|
14
|
+
# This method takes care of creating a new 'apprepo' folder, containg the app metadata
|
15
|
+
# and screenshots folders
|
16
|
+
def generate_apprepo_file(apprepo_path, options)
|
17
|
+
#
|
18
|
+
#v = options[:app].latest_version
|
19
|
+
#generate_metadata_files(v, File.join(apprepo_path, 'metadata'))
|
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
|
+
UI.user_error("TODO: ADJUST Repofile'")
|
29
|
+
# deliver => apprepo??
|
30
|
+
end
|
31
|
+
|
32
|
+
def download_metadata(apprepo_path, _options)
|
33
|
+
path = File.join(apprepo_path, 'metadata')
|
34
|
+
FileUtils.mkdir_p(path)
|
35
|
+
UI.success("TODO: DOWNLOAD METADATA'")
|
36
|
+
# AppRepo::DownloadManifest.run(options, path)
|
37
|
+
end
|
38
|
+
|
39
|
+
def run(options)
|
40
|
+
UI.message('[AppRepo:Setup] Running...')
|
41
|
+
containing = (File.directory?('fastlane') ? 'fastlane' : '.')
|
42
|
+
file_path = File.join(containing, 'Repofile')
|
43
|
+
data = generate_apprepo_file(containing, options)
|
44
|
+
setup_apprepo(file_path, data, containing, options)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# @setup = new AppRepo::Setup
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module AppRepo
|
2
|
+
class UploadAssets
|
3
|
+
def upload(options)
|
4
|
+
app = options[:app]
|
5
|
+
|
6
|
+
v = app.edit_version
|
7
|
+
UI.user_error!("Could not find a version to edit for app '#{app.name}'") unless v
|
8
|
+
|
9
|
+
if options[:app_icon]
|
10
|
+
UI.message('Uploading app icon...')
|
11
|
+
v.upload_large_icon!(options[:app_icon])
|
12
|
+
end
|
13
|
+
|
14
|
+
if options[:apple_watch_app_icon]
|
15
|
+
UI.message('Uploading apple watchapp icon...')
|
16
|
+
v.upload_watch_icon!(options[:apple_watch_app_icon])
|
17
|
+
end
|
18
|
+
|
19
|
+
v.save!
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -1,14 +1,13 @@
|
|
1
1
|
module AppRepo
|
2
|
+
class UploadDescriptor
|
2
3
|
|
3
|
-
|
4
|
+
attr_accessor :appcode # required
|
5
|
+
attr_accessor :ipa # can be inferred anyway (glob or metadata)
|
6
|
+
attr_accessor :metadata # optional, allows re-uploading same binary without metadata change
|
4
7
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
puts 'Initializing "AppRepo:UploadDescriptor with appcode "'+self.appcode
|
8
|
+
def initialize(appcode)
|
9
|
+
self.appcode = appcode
|
10
|
+
UI.message('Initializing "AppRepo:UploadDescriptor with appcode "' + self.appcode + '"')
|
11
|
+
end
|
10
12
|
end
|
11
13
|
end
|
12
|
-
|
13
|
-
end
|
14
|
-
|
@@ -0,0 +1,192 @@
|
|
1
|
+
module AppRepo
|
2
|
+
# upload description, rating, etc.
|
3
|
+
class UploadMetadata
|
4
|
+
# All the localised values attached to the version
|
5
|
+
LOCALISED_VERSION_VALUES = [:description, :keywords, :release_notes, :support_url, :marketing_url].freeze
|
6
|
+
|
7
|
+
# Everything attached to the version but not being localised
|
8
|
+
NON_LOCALISED_VERSION_VALUES = [:copyright].freeze
|
9
|
+
|
10
|
+
# Localised app details values
|
11
|
+
LOCALISED_APP_VALUES = [:name, :privacy_url].freeze
|
12
|
+
|
13
|
+
# Non localized app details values
|
14
|
+
NON_LOCALISED_APP_VALUES = [:primary_category, :secondary_category,
|
15
|
+
:primary_first_sub_category, :primary_second_sub_category,
|
16
|
+
:secondary_first_sub_category, :secondary_second_sub_category
|
17
|
+
].freeze
|
18
|
+
|
19
|
+
# Make sure to call `load_from_filesystem` before calling upload
|
20
|
+
def upload(options)
|
21
|
+
return if options[:skip_metadata]
|
22
|
+
verify_available_languages!(options)
|
23
|
+
|
24
|
+
app = options[:app]
|
25
|
+
|
26
|
+
details = app.details
|
27
|
+
v = app.edit_version
|
28
|
+
|
29
|
+
(LOCALISED_VERSION_VALUES + LOCALISED_APP_VALUES).each do |key|
|
30
|
+
current = options[key]
|
31
|
+
next unless current
|
32
|
+
|
33
|
+
unless current.is_a?(Hash)
|
34
|
+
UI.error("Error with provided '#{key}'. Must be a hash, the key being the language.")
|
35
|
+
next
|
36
|
+
end
|
37
|
+
|
38
|
+
current.each do |language, value|
|
39
|
+
next unless value.to_s.length > 0
|
40
|
+
strip_value = value.to_s.strip
|
41
|
+
v.send(key)[language] = strip_value if LOCALISED_VERSION_VALUES.include?(key)
|
42
|
+
details.send(key)[language] = strip_value if LOCALISED_APP_VALUES.include?(key)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
(NON_LOCALISED_VERSION_VALUES + NON_LOCALISED_APP_VALUES).each do |key|
|
47
|
+
current = options[key].to_s.strip
|
48
|
+
next unless current.to_s.length > 0
|
49
|
+
v.send("#{key}=", current) if NON_LOCALISED_VERSION_VALUES.include?(key)
|
50
|
+
details.send("#{key}=", current) if NON_LOCALISED_APP_VALUES.include?(key)
|
51
|
+
end
|
52
|
+
|
53
|
+
v.release_on_approval = options[:automatic_release]
|
54
|
+
|
55
|
+
set_review_information(v, options)
|
56
|
+
set_app_rating(v, options)
|
57
|
+
|
58
|
+
UI.message('Uploading metadata to iTunes Connect')
|
59
|
+
v.save!
|
60
|
+
details.save!
|
61
|
+
UI.success('Successfully uploaded initial set of metadata to iTunes Connect')
|
62
|
+
end
|
63
|
+
|
64
|
+
# If the user is using the 'default' language, then assign values where they are needed
|
65
|
+
def assign_defaults(options)
|
66
|
+
# Build a complete list of the required languages
|
67
|
+
enabled_languages = []
|
68
|
+
|
69
|
+
# Get all languages used in existing settings
|
70
|
+
(LOCALISED_VERSION_VALUES + LOCALISED_APP_VALUES).each do |key|
|
71
|
+
current = options[key]
|
72
|
+
next unless current && current.is_a?(Hash)
|
73
|
+
current.each do |language, _value|
|
74
|
+
enabled_languages << language unless enabled_languages.include?(language)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Check folder list (an empty folder signifies a language is required)
|
79
|
+
Dir.glob(File.join(options[:metadata_path], '*')).each do |lng_folder|
|
80
|
+
next unless File.directory?(lng_folder) # We don't want to read txt as they are non localised
|
81
|
+
|
82
|
+
language = File.basename(lng_folder)
|
83
|
+
enabled_languages << language unless enabled_languages.include?(language)
|
84
|
+
end
|
85
|
+
|
86
|
+
return unless enabled_languages.include?('default')
|
87
|
+
UI.message('Detected languages: ' + enabled_languages.to_s)
|
88
|
+
|
89
|
+
(LOCALISED_VERSION_VALUES + LOCALISED_APP_VALUES).each do |key|
|
90
|
+
current = options[key]
|
91
|
+
next unless current && current.is_a?(Hash)
|
92
|
+
|
93
|
+
default = current['default']
|
94
|
+
next if default.nil?
|
95
|
+
|
96
|
+
enabled_languages.each do |language|
|
97
|
+
value = current[language]
|
98
|
+
next unless value.nil?
|
99
|
+
|
100
|
+
current[language] = default
|
101
|
+
end
|
102
|
+
current.delete('default')
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Makes sure all languages we need are actually created
|
107
|
+
def verify_available_languages!(options)
|
108
|
+
return if options[:skip_metadata]
|
109
|
+
|
110
|
+
# Collect all languages we need
|
111
|
+
# We only care about languages from user provided values
|
112
|
+
# as the other languages are on iTC already anyway
|
113
|
+
v = options[:app].edit_version
|
114
|
+
UI.user_error!("Could not find a version to edit for app '#{options[:app].name}', the app metadata is read-only currently") unless v
|
115
|
+
|
116
|
+
enabled_languages = []
|
117
|
+
LOCALISED_VERSION_VALUES.each do |key|
|
118
|
+
current = options[key]
|
119
|
+
next unless current && current.is_a?(Hash)
|
120
|
+
current.each do |language, _value|
|
121
|
+
enabled_languages << language unless enabled_languages.include?(language)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
if enabled_languages.count > 0
|
126
|
+
v.create_languages(enabled_languages)
|
127
|
+
lng_text = 'language'
|
128
|
+
lng_text += 's' if enabled_languages.count != 1
|
129
|
+
UI.message("Activating #{lng_text} #{enabled_languages.join(', ')}...")
|
130
|
+
v.save!
|
131
|
+
end
|
132
|
+
true
|
133
|
+
end
|
134
|
+
|
135
|
+
# Loads the metadata files and stores them into the options object
|
136
|
+
def load_from_filesystem(options)
|
137
|
+
return if options[:skip_metadata]
|
138
|
+
|
139
|
+
# Load localised data
|
140
|
+
Loader.language_folders(options[:metadata_path]).each do |lng_folder|
|
141
|
+
language = File.basename(lng_folder)
|
142
|
+
(LOCALISED_VERSION_VALUES + LOCALISED_APP_VALUES).each do |key|
|
143
|
+
path = File.join(lng_folder, "#{key}.txt")
|
144
|
+
next unless File.exist?(path)
|
145
|
+
|
146
|
+
UI.message("Loading '#{path}'...")
|
147
|
+
options[key] ||= {}
|
148
|
+
options[key][language] ||= File.read(path)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
# Load non localised data
|
153
|
+
(NON_LOCALISED_VERSION_VALUES + NON_LOCALISED_APP_VALUES).each do |key|
|
154
|
+
path = File.join(options[:metadata_path], "#{key}.txt")
|
155
|
+
next unless File.exist?(path)
|
156
|
+
|
157
|
+
UI.message("Loading '#{path}'...")
|
158
|
+
options[key] ||= File.read(path)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
private
|
163
|
+
|
164
|
+
def set_review_information(v, options)
|
165
|
+
return unless options[:app_review_information]
|
166
|
+
info = options[:app_review_information]
|
167
|
+
UI.user_error!('`app_review_information` must be a hash') unless info.is_a?(Hash)
|
168
|
+
|
169
|
+
v.review_first_name = info[:first_name] if info[:first_name]
|
170
|
+
v.review_last_name = info[:last_name] if info[:last_name]
|
171
|
+
v.review_phone_number = info[:phone_number] if info[:phone_number]
|
172
|
+
v.review_email = info[:email_address] if info[:email_address]
|
173
|
+
v.review_demo_user = info[:demo_user] if info[:demo_user]
|
174
|
+
v.review_demo_password = info[:demo_password] if info[:demo_password]
|
175
|
+
v.review_user_needed = (v.review_demo_user.to_s + v.review_demo_password.to_s).length > 0
|
176
|
+
v.review_notes = info[:notes] if info[:notes]
|
177
|
+
end
|
178
|
+
|
179
|
+
def set_app_rating(v, options)
|
180
|
+
return unless options[:app_rating_config_path]
|
181
|
+
|
182
|
+
require 'json'
|
183
|
+
begin
|
184
|
+
json = JSON.parse(File.read(options[:app_rating_config_path]))
|
185
|
+
rescue => ex
|
186
|
+
UI.error(ex.to_s)
|
187
|
+
UI.user_error!("Error parsing JSON file at path '#{options[:app_rating_config_path]}'")
|
188
|
+
end
|
189
|
+
v.update_rating(json)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|