apprepo 0.0.2 → 0.0.4
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 +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
|