deliver 0.13.5 → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +9 -208
  3. data/bin/deliver +1 -1
  4. data/lib/assets/DeliverfileDefault +2 -22
  5. data/lib/assets/summary.html.erb +27 -39
  6. data/lib/deliver.rb +16 -14
  7. data/lib/deliver/app_screenshot.rb +43 -33
  8. data/lib/deliver/commands_generator.rb +30 -108
  9. data/lib/deliver/detect_values.rb +23 -0
  10. data/lib/deliver/download_screenshots.rb +30 -9
  11. data/lib/deliver/html_generator.rb +7 -8
  12. data/lib/deliver/options.rb +126 -0
  13. data/lib/deliver/runner.rb +75 -0
  14. data/lib/deliver/setup.rb +84 -0
  15. data/lib/deliver/submit_for_review.rb +60 -0
  16. data/lib/deliver/upload_assets.rb +22 -0
  17. data/lib/deliver/upload_metadata.rb +100 -0
  18. data/lib/deliver/upload_price_tier.rb +21 -0
  19. data/lib/deliver/upload_screenshots.rb +63 -0
  20. data/lib/deliver/version.rb +2 -1
  21. metadata +37 -62
  22. data/lib/assets/DeliverLanguageMapping.json +0 -187
  23. data/lib/assets/DeliverfileExample +0 -38
  24. data/lib/deliver/app.rb +0 -167
  25. data/lib/deliver/app_metadata.rb +0 -419
  26. data/lib/deliver/app_metadata_screenshots.rb +0 -189
  27. data/lib/deliver/deliver_process.rb +0 -426
  28. data/lib/deliver/deliverer.rb +0 -138
  29. data/lib/deliver/deliverfile/deliverfile.rb +0 -35
  30. data/lib/deliver/deliverfile/deliverfile_creator.rb +0 -135
  31. data/lib/deliver/deliverfile/dsl.rb +0 -142
  32. data/lib/deliver/dependency_checker.rb +0 -19
  33. data/lib/deliver/ipa_file_analyser.rb +0 -44
  34. data/lib/deliver/ipa_uploader.rb +0 -148
  35. data/lib/deliver/itunes_connect/itunes_connect.rb +0 -12
  36. data/lib/deliver/itunes_connect/itunes_connect_additional.rb +0 -105
  37. data/lib/deliver/itunes_connect/itunes_connect_app_icon.rb +0 -41
  38. data/lib/deliver/itunes_connect/itunes_connect_app_rating.rb +0 -90
  39. data/lib/deliver/itunes_connect/itunes_connect_apple_watch_app_icon.rb +0 -42
  40. data/lib/deliver/itunes_connect/itunes_connect_information.rb +0 -34
  41. data/lib/deliver/itunes_connect/itunes_connect_new_version.rb +0 -67
  42. data/lib/deliver/itunes_connect/itunes_connect_reader.rb +0 -46
  43. data/lib/deliver/itunes_connect/itunes_connect_screenshot_fetcher.rb +0 -54
  44. data/lib/deliver/itunes_connect/itunes_connect_submission.rb +0 -282
  45. data/lib/deliver/itunes_transporter.rb +0 -221
  46. data/lib/deliver/metadata_item.rb +0 -94
  47. data/lib/deliver/testflight.rb +0 -27
@@ -1,138 +0,0 @@
1
- module Deliver
2
- # This class will collect the deploy data from different places
3
- # This will trigger:
4
- #
5
- # - Parsing the Deliverfile
6
- # - Temporary storing all the information got from the file, until the file finished executing
7
- # - Triggering the upload process itself using the DeliverProcess class
8
- class Deliverer
9
- # @return (Deliver::Deliverfile::Deliverfile) A reference
10
- # to the Deliverfile which is currently being used.
11
- attr_accessor :deliver_file
12
-
13
- # @return (Deliver::DeliverProcess) The class which handels the deployment process itself
14
- attr_accessor :deliver_process
15
-
16
- module ValKey
17
- APP_IDENTIFIER = :app_identifier
18
- APPLE_ID = :apple_id
19
- APP_VERSION = :version
20
- IPA = :ipa
21
- DESCRIPTION = :description
22
- TITLE = :title
23
- BETA_IPA = :beta_ipa
24
- IS_BETA_IPA = :is_beta_ipa
25
- SKIP_DEPLOY = :skip_deploy
26
- CHANGELOG = :changelog
27
- SUPPORT_URL = :support_url
28
- PRIVACY_URL = :privacy_url
29
- MARKETING_URL = :marketing_url
30
- KEYWORDS = :keywords
31
- SCREENSHOTS_PATH = :screenshots_path
32
- DEFAULT_LANGUAGE = :default_language
33
- CONFIG_JSON_FOLDER = :config_json_folder # Path to a folder containing a configuration file and including screenshots
34
- SKIP_PDF = :skip_pdf
35
- SUBMIT_FURTHER_INFORMATION = :submit_further_information # export compliance, content rights and advertising identifier
36
- PRICE_TIER = :price_tier
37
- APP_ICON = :app_icon
38
- APPLE_WATCH_APP_ICON = :apple_watch_app_icon
39
-
40
- COPYRIGHT = :copyright
41
- PRIMARY_CATEGORY = :primary_category
42
- SECONDARY_CATEGORY = :secondary_category
43
- PRIMARY_SUBCATEGORIES = :primary_subcategories
44
- SECONDARY_SUBCATEGORIES = :secondary_subcategories
45
-
46
- AUTOMATIC_RELEASE = :automatic_release # should the update go live after approval
47
- RATINGS_CONFIG_PATH = :ratings_config_path # a path to the configuration for the app's ratings
48
-
49
- APP_REVIEW_INFORMATION = :app_review_information
50
- # Supported
51
- # first_name
52
- # last_name
53
- # phone_number
54
- # email_address
55
- # demo_user
56
- # demo_password
57
- # notes
58
- end
59
-
60
- module AllBlocks
61
- UNIT_TESTS = :unit_tests
62
- SUCCESS = :success
63
- ERROR = :error
64
- end
65
-
66
-
67
- # Start a new deployment process based on the given Deliverfile
68
- # @param (String) path The path to the Deliverfile.
69
- # @param (Hash) hash You can pass a hash instead of a path to basically
70
- # give all the information required (see {Deliverer::ValKey} for available options)
71
- # @param (Bool) force Runs a deployment without verifying any information. This can be
72
- # used for build servers. If this is set to false a PDF summary will be generated and opened
73
- def initialize(path = nil, hash: nil, force: false, is_beta_ipa: false, skip_deploy: false)
74
- @deliver_process = DeliverProcess.new
75
- @deliver_process.deploy_information[ValKey::SKIP_PDF] = true if force
76
- @deliver_process.deploy_information[ValKey::IS_BETA_IPA] = is_beta_ipa
77
- @deliver_process.deploy_information[ValKey::SKIP_DEPLOY] = skip_deploy
78
-
79
- if hash
80
- hash.each do |key, value|
81
- # we still call this interface to verify the inputs correctly
82
- set_new_value(key, value)
83
- end
84
-
85
- finished_executing_deliver_file
86
- else
87
- @deliver_file = Deliver::Deliverfile::Deliverfile.new(self, path)
88
- end
89
-
90
- # Do not put code here...
91
- end
92
-
93
- # This method is internally called from the Deliverfile DSL
94
- # to set a value for a given key. This method will also verify if
95
- # the key is valid.
96
- def set_new_value(key, value)
97
- unless self.class.all_available_keys_to_set.include?key
98
- raise "Invalid key '#{key}', must be contained in Deliverer::ValKey.".red
99
- end
100
-
101
- if @deliver_process.deploy_information[key]
102
- Helper.log.warn("You already set a value for key '#{key}'. Overwriting with new value '#{value}'.")
103
- end
104
-
105
- @deliver_process.deploy_information[key] = value
106
- end
107
-
108
- # Sets a new block for a specific key
109
- def set_new_block(key, block)
110
- @deliver_process.deploy_information[:blocks][key] = block
111
- end
112
-
113
- # An array of all available options to be set a deployment_information.
114
- #
115
- # Is used to verify user inputs
116
- # @return (Hash) The array of symbols
117
- def self.all_available_keys_to_set
118
- Deliverer::ValKey.constants.collect { |a| Deliverer::ValKey.const_get(a) }
119
- end
120
-
121
- # An array of all available blocks to be set for a deployment
122
- #
123
- # Is used to verify user inputs
124
- # @return (Hash) The array of symbols
125
- def self.all_available_blocks_to_set
126
- Deliverer::AllBlocks.constants.collect { |a| Deliverer::AllBlocks.const_get(a) }
127
- end
128
-
129
- # This method will take care of the actual deployment process, after we
130
- # received all information from the Deliverfile.
131
- #
132
- # This method will be called from the {Deliver::Deliverfile} after
133
- # it is finished executing the Ruby script.
134
- def finished_executing_deliver_file
135
- deliver_process.run
136
- end
137
- end
138
- end
@@ -1,35 +0,0 @@
1
- require 'deliver/deliverfile/dsl'
2
-
3
- module Deliver
4
- module Deliverfile
5
- # Deliverfile represents a Deliverfile created by a user of this library
6
- class Deliverfile
7
-
8
- FILE_NAME = "Deliverfile"
9
-
10
- include Deliver::Deliverfile::Deliverfile::DSL
11
-
12
- # The path to the used Deliverfile.
13
- attr_accessor :path
14
-
15
- # Loads the Deliverfile from the given path
16
- # @param deliver_data (Deliver::Deliverer) The deliverer which handles the
17
- # results of running this deliverfile
18
- # @param (String) path (optional) to the file itself. This must also include the
19
- # filename itself.
20
- def initialize(deliver_data, path = nil)
21
- path ||= "./#{FILE_NAME}"
22
- raise "#{FILE_NAME} not found at path '#{File.expand_path(path)}'".red unless File.exists?(path.to_s)
23
-
24
- self.path = path
25
- @deliver_data = deliver_data
26
-
27
- content = File.read(path)
28
-
29
- eval(content) # this is okay in this case
30
-
31
- @deliver_data.finished_executing_deliver_file
32
- end
33
- end
34
- end
35
- end
@@ -1,135 +0,0 @@
1
- require 'credentials_manager/password_manager'
2
- require 'credentials_manager/appfile_config'
3
- require 'deliver/itunes_connect/itunes_connect'
4
-
5
- module Deliver
6
- # Helps new user quickly adopt Deliver
7
- class DeliverfileCreator
8
-
9
- # This method will ask the user what he wants to do
10
- # @param deliver_path (String) The path in which the Deliverfile should be created (this automatically takes care if it's in the fastlane folder)
11
- # @param project_name (String) The default name of the project, which is used in the generated Deliverfile
12
- def self.create(deliver_path, project_name = nil)
13
- deliver_file_path = File.join(deliver_path, Deliver::Deliverfile::Deliverfile::FILE_NAME)
14
- raise "Deliverfile already exists at path '#{deliver_file_path}'. Run 'deliver' to use Deliver.".red if File.exists?(deliver_file_path)
15
-
16
- project_name ||= Dir.pwd.split("/").last
17
-
18
- if agree("Do you want Deliver to automatically create the Deliverfile for you based " +
19
- "on your current app? The app has to be in the App Store to use this feature. (y/n)", true)
20
-
21
- puts "\n\nFirst, you need to login with your iTunesConnect credentials. ".yellow +
22
- "\nThis is necessary to fetch the latest metadata from your app and use it to create a Deliverfile for you." +
23
- "\nIf you have previously entered your credentials already, you will not be asked again."
24
-
25
- if CredentialsManager::PasswordManager.shared_manager.username and CredentialsManager::PasswordManager.shared_manager.password
26
- identifier = ((CredentialsManager::AppfileConfig.try_fetch_value(:app_identifier) rescue '') || '')
27
- while identifier.length < 3
28
- identifier = ask("\nApp Identifier of your app (e.g. com.krausefx.app_name): ")
29
- end
30
-
31
- self.create_based_on_identifier(deliver_path, identifier, project_name)
32
- else
33
- self.create_example_deliver_file(deliver_file_path, project_name)
34
- end
35
- else
36
- self.create_example_deliver_file(deliver_file_path, project_name)
37
- end
38
- end
39
-
40
- # This method is used, when the user does not want to automatically create the Deliverfile
41
- # @param path (String) The exact path (including the file name) in which the Deliverfile should be created
42
- # @param project_name (String) The default name of the project, which is used in the generated Deliverfile
43
- def self.create_example_deliver_file(path, project_name)
44
- gem_path = Helper.gem_path('deliver')
45
- example = File.read("#{gem_path}/lib/assets/DeliverfileExample")
46
- example.gsub!("[[APP_NAME]]", project_name)
47
- File.write(path, example)
48
-
49
- puts "Successfully created new Deliverfile at '#{path}'".green
50
- end
51
-
52
- # This will download all the app metadata and store its data into JSON files
53
- # @param deliver_path (String) The directory in which the Deliverfile should be created
54
- # @param identifier (String) The app identifier we want to create Deliverfile based on
55
- # @param project_name (String) The default name of the project, which is used in the generated Deliverfile
56
- def self.create_based_on_identifier(deliver_path, identifier, project_name)
57
- app = Deliver::App.new(app_identifier: identifier)
58
- app.set_metadata_directory("/tmp") # we don't want to pollute the current folder
59
- app.metadata # this will download the latest app metadata
60
-
61
- version_number = app.metadata.fetch_value("//x:version").first["string"] # fetch the latest app version
62
-
63
- file_path = File.join(deliver_path, Deliver::Deliverfile::Deliverfile::FILE_NAME)
64
- json = generate_deliver_file(app, deliver_path, project_name, version_number)
65
- File.write(file_path, json)
66
-
67
- FileUtils.mkdir_p File.join(deliver_path, 'screenshots')
68
- begin
69
- Helper.log.info "Downloading all previously used app screenshots.".green
70
- ItunesConnect.new.download_existing_screenshots(app, deliver_path)
71
- rescue Exception => ex
72
- Helper.log.error ex
73
- Helper.log.error "Couldn't download already existing screenshots from iTunesConnect. You have to add them manually!".red
74
- end
75
-
76
- # Add a README to the screenshots folder
77
- FileUtils.mkdir_p File.join(deliver_path, 'screenshots') # just in case the fetching didn't work
78
- File.write(File.join(deliver_path, 'screenshots', 'README.txt'), File.read("#{Helper.gem_path('deliver')}/lib/assets/ScreenshotsHelp"))
79
-
80
- Helper.log.info "Successfully created new Deliverfile".green
81
- end
82
-
83
- private
84
- # This method takes care of creating a new 'deliver' folder, containg the app metadata
85
- # and screenshots folders
86
- def self.generate_deliver_file(app, path, project_name, version_number)
87
- FileUtils.mkdir_p path rescue nil # never mind if it's already there
88
-
89
- json = create_json_based_on_xml(app, path)
90
-
91
- json.each do |language, value|
92
- folder = File.join(path, "metadata", language)
93
- FileUtils.mkdir_p(folder)
94
- value.each do |key, content|
95
- content = content.join("\n") if key == :keywords
96
- File.write(File.join(folder, "#{key}.txt"), content)
97
- end
98
- Helper.log.info "Successfully downloaded existing metadata for language #{language}"
99
- end
100
-
101
- puts "Successfully created new configuration files.".green
102
-
103
- gem_path = Helper.gem_path('deliver')
104
-
105
- # Generate the final Deliverfile here
106
- deliver = File.read("#{gem_path}/lib/assets/DeliverfileDefault")
107
- deliver.gsub!("[[APP_IDENTIFIER]]", app.app_identifier)
108
- deliver.gsub!("[[APP_NAME]]", project_name)
109
- deliver.gsub!("[[APPLE_ID]]", app.apple_id.to_s)
110
- deliver.gsub!("[[EMAIL]]", CredentialsManager::PasswordManager.shared_manager.username)
111
- deliver.gsub!("[[APP_VERSION]]", version_number)
112
-
113
- return deliver
114
- end
115
-
116
- # Access the app metadata and use them to create a finished Deliverfile
117
- def self.create_json_based_on_xml(app, path)
118
- json = {}
119
- # Access the app metadata and use them to create a finished Deliverfile
120
- app_name = app.metadata.information.each do |locale, current|
121
- current.each do |key, value|
122
- if value and value.kind_of?Hash # that does not apply for screenshots, which is an array
123
- current[key] = value[:value]
124
- else
125
- current.delete(key)
126
- end
127
- end
128
-
129
- json[locale] = current
130
- end
131
-
132
- return json
133
- end
134
- end
135
- end
@@ -1,142 +0,0 @@
1
- # Inspired by https://github.com/CocoaPods/Core/blob/master/lib/cocoapods-core/podfile/dsl.rb
2
- require 'credentials_manager/password_manager'
3
-
4
- module Deliver
5
- module Deliverfile
6
- class Deliverfile
7
- module DSL
8
- MISSING_VALUE_ERROR_MESSAGE = "You have to pass either a value or a block to the given method."
9
- SPECIFY_LANGUAGE_FOR_VALUE = "You have to specify the language of the given value. Either set a default language using 'default_language \"en-US\"' on the top of the file or pass a hash containing the language codes"
10
-
11
- MISSING_APP_IDENTIFIER_MESSAGE = "You have to pass a valid app identifier using the Deliver file. (e.g. 'app_identifier \"net.sunapps.app\"')"
12
- MISSING_VERSION_NUMBER_MESSAGE = "You have to pass a valid version number using the Deliver file. (e.g. 'version \"1.0\"')"
13
- INVALID_IPA_FILE_GIVEN = "The given ipa file seems to be wrong. Make sure it's a valid ipa file."
14
-
15
- class DeliverfileDSLError < StandardError
16
- end
17
-
18
- # Setting all the metadata
19
- def method_missing(method_sym, *arguments, &block)
20
- allowed = Deliver::Deliverer.all_available_keys_to_set
21
- not_translated = [:ipa, :app_identifier, :apple_id, :screenshots_path, :config_json_folder,
22
- :submit_further_information, :copyright, :primary_category, :secondary_category,
23
- :primary_subcategories, :secondary_subcategories,
24
- :automatic_release, :app_review_information, :ratings_config_path, :price_tier,
25
- :app_icon, :apple_watch_app_icon]
26
-
27
- if allowed.include?(method_sym)
28
- value = arguments.first
29
- value = block.call if (value == nil and block != nil)
30
-
31
- if value == nil
32
- Helper.log.error(caller)
33
- Helper.log.fatal("No value or block passed to method '#{method_sym}'")
34
- raise DeliverfileDSLError.new(MISSING_VALUE_ERROR_MESSAGE.red)
35
- end
36
-
37
- if (not value.kind_of?Hash) and (not not_translated.include?method_sym)
38
- # The user should pass a hash for multi-lang values
39
- # Maybe he at least set a default language
40
- if @default_language
41
- value = { @default_language => value }
42
- else
43
- raise DeliverfileDSLError.new(SPECIFY_LANGUAGE_FOR_VALUE.red)
44
- end
45
- end
46
-
47
- @deliver_data.set_new_value(method_sym, value)
48
- else
49
- # Check if it's a block (e.g. run tests)
50
- if Deliver::Deliverer.all_available_blocks_to_set.include?method_sym
51
- if block
52
- @deliver_data.set_new_block(method_sym, block)
53
- else
54
- raise DeliverfileDSLError.new("Value for #{method_sym} must be a Ruby block. Use '#{method_sym}' do ... end.".red)
55
- end
56
- else
57
- # Couldn't find this particular method
58
- Helper.log.error("Could not find method '#{method_sym}'. Available methods: #{allowed.collect { |a| a.to_s }}")
59
- end
60
- end
61
- end
62
-
63
- # This method can be used to set a default language, which is used
64
- # when passing a string to metadata changes, instead of a hash
65
- # containing multiple languages.
66
- #
67
- # This is approach only is recommend for deployments where you are only
68
- # supporting one language.
69
- #
70
- # The language itself must be included in {FastlaneCore::Languages::ALL_LANGUAGES}.
71
- # @example
72
- # default_language 'en-US'
73
- # @example
74
- # default_language 'de-DE'
75
- def default_language(value = nil)
76
- # Verify, default_language is on the top of the file
77
- already_set = @deliver_data.deliver_process.deploy_information
78
- minimum = (already_set[:skip_pdf] ? 4 : 3) # skip_pdf + blocks
79
- if already_set.count > minimum
80
- raise "'default_language' must be on the top of the Deliverfile.".red
81
- end
82
-
83
-
84
- @default_language = value
85
- @default_language ||= yield if block_given?
86
- Helper.log.debug("Set default language to #{@default_language}")
87
- @deliver_data.set_new_value(:default_language, @default_language)
88
- end
89
-
90
- # Pass the path to the ipa file which should be uploaded
91
- # @raise (DeliverfileDSLError) occurs when you pass an invalid path to the
92
- # IPA file.
93
- def ipa(value = nil, &block)
94
- DSL.validate_ipa!(value) if value # to catch errors early
95
-
96
- @deliver_data.set_new_value(Deliverer::ValKey::IPA, (value || block))
97
- end
98
-
99
- # Pass the path to the ipa file (beta version) which should be uploaded
100
- # @raise (DeliverfileDSLError) occurs when you pass an invalid path to the
101
- # IPA file.
102
- def beta_ipa(value = nil, &block)
103
- DSL.validate_ipa!(value) if value # to catch errors early
104
-
105
- @deliver_data.set_new_value(Deliverer::ValKey::BETA_IPA, (value || block))
106
- end
107
-
108
- # This will set the email address of the Apple ID to be used
109
- def email(value)
110
- value ||= yield if block_given?
111
- CredentialsManager::PasswordManager.logout # if it was logged in already (with fastlane)
112
- CredentialsManager::PasswordManager.shared_manager(value)
113
- end
114
-
115
- # This will hide the output of the iTunes Connect transporter while uploading/downloading
116
- def hide_transporter_output
117
- ItunesTransporter.hide_transporter_output
118
- end
119
-
120
- # Set the apps new version number.
121
- #
122
- # If you do not set this, it will automatically being fetched from the
123
- # IPA file.
124
- def version(value = nil)
125
- value ||= yield if block_given?
126
- raise DeliverfileDSLError.new(MISSING_VALUE_ERROR_MESSAGE.red) unless value
127
- raise DeliverfileDSLError.new("The app version should be a string".red) unless value.kind_of?(String)
128
-
129
- @deliver_data.set_new_value(Deliverer::ValKey::APP_VERSION, value)
130
- end
131
-
132
- # Only verifies the file type of the ipa path and if the file can be found. Is also called from deliver_process
133
- # This will raise a DeliverfileDSLError if something goes wrong
134
- def self.validate_ipa!(value)
135
- raise DeliverfileDSLError.new(INVALID_IPA_FILE_GIVEN.red) unless value
136
- raise DeliverfileDSLError.new(INVALID_IPA_FILE_GIVEN.red) unless value.kind_of?String
137
- raise DeliverfileDSLError.new(INVALID_IPA_FILE_GIVEN.red) unless value.include?".ipa"
138
- end
139
- end
140
- end
141
- end
142
- end