deliver 0.4.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e92daeb5d5f0058937a3e2b177303f2fdcfc001f
4
- data.tar.gz: 8dd64896cae88f3da1e2a7d74ea25bb6791557e9
3
+ metadata.gz: 221e6f16252aa538e403f17cdf318edb2dd6ea20
4
+ data.tar.gz: fb4058c128cc42e5f871714c41c23b521949557e
5
5
  SHA512:
6
- metadata.gz: 1989b0ba55fe2fa98287575d73b08c4d49f492d0cb882dc5c99cefbf9272106c2af02fd1a0ffd83a34bf194dd03a17a12286696ab362bbb19d3c48f9cba24594
7
- data.tar.gz: cb746319220f76fd3b4c09926850c89161ec3e2c9268359cbc3120f5629f6cb2bf25daaae40cb60f64b5dfd3f03e73153e40124adf20904f000e0396aeb34e0f
6
+ metadata.gz: 860cdd383422e8e531c73db2bc549d2a56d8db91465275b3c4266746fad5cb2dd7e65b870adf71f81aac5abfe18c387ec76b6905362b697cf725bb3dab8beb6e
7
+ data.tar.gz: a76927b8bbbcf2b4f63b1a10410f0b55d82c96d6a130d8eb124ed7a345b1ae462d0f6753e4cb0357ef001752c67b56761cd8e68f812d340e6b492d5729d37620
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2014 Felix Krause
3
+ Copyright (c) 2015 Felix Krause
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,9 +1,16 @@
1
+ <h3 align="center">
2
+ <a href="https://github.com/KrauseFx/fastlane">
3
+ <img src="assets/fastlane.png" width="150" />
4
+ <br />
5
+ fastlane
6
+ </a>
7
+ </h3>
1
8
  <p align="center">
2
- <b>Deliver</b> &bull;
3
- <a href="https://github.com/KrauseFx/snapshot">Snapshot</a> &bull;
4
- <a href="https://github.com/KrauseFx/frameit">FrameIt</a> &bull;
5
- <a href="https://github.com/KrauseFx/PEM">PEM</a> &bull;
6
- <a href="https://github.com/KrauseFx/sigh">Sigh</a>
9
+ <b>deliver</b> &bull;
10
+ <a href="https://github.com/KrauseFx/snapshot">snapshot</a> &bull;
11
+ <a href="https://github.com/KrauseFx/frameit">frameit</a> &bull;
12
+ <a href="https://github.com/KrauseFx/PEM">PEM</a> &bull;
13
+ <a href="https://github.com/KrauseFx/sigh">sigh</a>
7
14
  </p>
8
15
  -------
9
16
 
@@ -11,7 +18,7 @@
11
18
  <img src="assets/deliver.png">
12
19
  </p>
13
20
 
14
- Deliver - Continuous Deployment for iOS
21
+ deliver
15
22
  ============
16
23
 
17
24
  [![Twitter: @KauseFx](https://img.shields.io/badge/contact-@KrauseFx-blue.svg?style=flat)](https://twitter.com/KrauseFx)
@@ -19,13 +26,11 @@ Deliver - Continuous Deployment for iOS
19
26
  [![Gem](https://img.shields.io/gem/v/deliver.svg?style=flat)](http://rubygems.org/gems/deliver)
20
27
  [![Build Status](https://img.shields.io/travis/KrauseFx/deliver/master.svg?style=flat)](https://travis-ci.org/KrauseFx/deliver)
21
28
 
29
+ ###### Upload screenshots, metadata and your app to the App Store using a single command
22
30
 
23
- Updating your iOS app should not be painful and time consuming. Automate the
24
- whole process to start with Continuous Deployment.
31
+ `deliver` **can upload ipa files, app screenshots and more to the iTunes Connect backend**, which means, you can deploy new iPhone app updates using the command line.
25
32
 
26
- ```Deliver``` **can upload ipa files, app screenshots and more to the iTunes Connect backend**, which means, you can deploy new iPhone app updates just by using one command.
27
-
28
- Follow the developer on Twitter: [@KrauseFx](https://twitter.com/KrauseFx)
33
+ Get in contact with the developer on Twitter: [@KrauseFx](https://twitter.com/KrauseFx)
29
34
 
30
35
 
31
36
  -------
@@ -34,22 +39,22 @@ Follow the developer on Twitter: [@KrauseFx](https://twitter.com/KrauseFx)
34
39
  <a href="#installation">Installation</a> &bull;
35
40
  <a href="#quick-start">Quick Start</a> &bull;
36
41
  <a href="#usage">Usage</a> &bull;
37
- <a href="#credentials">Credentials</a> &bull;
38
- <a href="#can-i-trust-deliver">Can I trust Deliver?</a> &bull;
42
+ <a href="#can-i-trust-deliver">Can I trust deliver?</a> &bull;
39
43
  <a href="#tips">Tips</a> &bull;
40
44
  <a href="#need-help">Need help?</a>
41
45
  </p>
42
46
 
43
47
  -------
44
48
 
49
+ <h5 align="center"><code>deliver</code> is part of <a href="http://fastlane.tools">fastlane</a>: connect all deployment tools into one streamlined workflow.</h5>
45
50
 
46
51
  # Features
47
52
  - Upload hundreds of screenshots with different languages from different devices
48
53
  - Upload a new ipa file to iTunes Connect without Xcode from any computer
49
54
  - Update app metadata
50
- - Easily implement a real Continuous Deployment process
55
+ - Easily implement a real Continuous Deployment process using [fastlane](https://github.com/KrauseFx/fastlane)
51
56
  - Store the configuration in git to easily deploy from **any** computer, including your Continuous Integration server (e.g. Jenkins)
52
- - Get a PDF preview of the fetched metadata before uploading the app metadata and screenshots to Apple: [Example Preview](https://github.com/krausefx/deliver/blob/master/assets/PDFExample.png?raw=1) (Yes, those are screenshots taken for all screen sizes)
57
+ - Get a PDF preview of the fetched metadata before uploading the app metadata and screenshots to Apple: [Example Preview](https://github.com/krausefx/deliver/blob/master/assets/PDFExample.png?raw=1)
53
58
  - Automatically create new screenshots with [Snapshot](https://github.com/KrauseFx/snapshot)
54
59
 
55
60
  # Installation
@@ -122,7 +127,11 @@ If you want to have the screenshots inside a device frame, with a background and
122
127
  #### Upload a new ipa file with a changelog to the App Store
123
128
  This will submit a new update to Apple
124
129
  ```ruby
125
- ipa "./latest.ipa"
130
+ ipa do
131
+ system("ipa build")
132
+ "./name.ipa"
133
+ end
134
+
126
135
  changelog({
127
136
  "en-US" => "This update adds cool new features",
128
137
  "de-DE" => "Dieses Update ist super"
@@ -130,25 +139,33 @@ changelog({
130
139
  ```
131
140
  If you wish to skip automated submission to review you can provide `--skip-deploy` option when calling `deliver`. This will upload the ipa file and app metadata, but will not submit the app for review.
132
141
 
142
+ The changelog is only used for App Store submission, not for TestFlight builds.
143
+
133
144
  #### Upload a new ipa for TestFlight beta testers
134
145
 
135
146
  In order to upload an `.ipa` file for Apple TestFlight you need to specify `beta_ipa` path in your `Deliverfile`
136
147
 
137
148
  ```ruby
138
- beta_ipa "./latest.ipa"
149
+ beta_ipa do
150
+ system("ipa build")
151
+ "./name.ipa"
152
+ end
139
153
  ```
140
154
 
141
155
  and provide `--beta` option when calling `deliver`.
142
156
 
143
157
  #### Implement blocks to run unit tests
158
+ If you're using [fastlane](http://github.com/krausefx/fastlane), run tests and error blocks there.
159
+
160
+ If you only use `deliver`, you can use the following blocks:
161
+
144
162
  ```ruby
145
163
  unit_tests do
146
164
  system("xctool test")
147
165
  end
148
166
 
149
167
  success do
150
- notifier = Slack::Notifier.new("SlackTeam", "SlackToken")
151
- notifier.ping "Successfully deployed new version"
168
+ system("Say 'success'")
152
169
  end
153
170
 
154
171
  error do |exception|
@@ -156,7 +173,6 @@ error do |exception|
156
173
  raise "Something went wrong: #{exception}"
157
174
  end
158
175
  ```
159
- For this example I used [slack-notifier](https://github.com/stevenosloan/slack-notifier).
160
176
 
161
177
 
162
178
  #### Set a default language if you are lucky enough to only maintain one language
@@ -191,8 +207,8 @@ ipa do
191
207
  # Add any code you want, like incrementing the build
192
208
  # number or changing the app identifier
193
209
 
194
- system("ipa build") # build your project using Shenzhen
195
- "./AppName.ipa" # Tell 'Deliver' where it can find the finished ipa file
210
+ system("ipa build --verbose") # build your project using Shenzhen
211
+ "./AppName.ipa" # Tell 'deliver' where it can find the finished ipa file
196
212
  end
197
213
  ```
198
214
 
@@ -238,36 +254,18 @@ This project is well documented, check it out on [Rubydoc](http://www.rubydoc.in
238
254
 
239
255
 
240
256
  # Credentials
241
- The used username (Apple ID) will be stored in the ```Deliverfile``` by default. When you run ```deliver``` for the first time on another computer, you will only be asked for the password.
242
-
243
- Therefore it is easy to switch between projects, without needing to logout and login again.
244
257
 
245
- ## Use the Keychain
246
- The first time you use *Deliver* you have to enter your iTunes Connect
247
- credentials. They will be stored in the Keychain.
258
+ A detailed description about your credentials is available on a [seperate repo](https://github.com/KrauseFx/CredentialsManager).
248
259
 
249
- If you decide to remove your
250
- credentials from the Keychain, just open the *Keychain Access*, select
251
- *All Items* and search for 'deliver'.
252
260
 
253
- ## Use environment variables
254
- You can use the following environment variables to use a specific account instead of the one stored in the keychain.
255
- This is especially important if you have more than one iTunes Connect account in your keychain:
256
-
257
- DELIVER_USER
258
- DELIVER_PASSWORD
259
-
260
- ## Implement your custom solution
261
- Take a look at [Using the exposed Ruby classes](#use-the-exposed-ruby-classes).
262
-
263
- # Can I trust *Deliver*?
261
+ # Can I trust `deliver`?
264
262
  ###How does this thing even work? Is magic involved? 🎩###
265
263
 
266
- ```Deliver``` is fully open source, you can take a look at it. It will only modify the content you want to modify using the ```Deliverfile```. Your password will be stored in the Mac OS X keychain, but can also be passed using environment variables.
264
+ `deliver` is fully open source, you can take a look at its source files. It will only modify the content you want to modify using the ```Deliverfile```. Your password will be stored in the Mac OS X keychain, but can also be passed using environment variables.
267
265
 
268
266
  Before actually uploading anything to iTunes, ```Deliver``` will generate a [PDF summary](https://github.com/krausefx/deliver/blob/master/assets/PDFExample.png?raw=1) of the collected data.
269
267
 
270
- ```Deliver``` uses the following techniques under the hood:
268
+ ```deliver``` uses the following techniques under the hood:
271
269
 
272
270
  - The iTMSTransporter tool is used to fetch the latest app metadata from iTunes Connect and upload the updated app metadata back to Apple. It is also used to upload the ipa file. iTMSTransporter is a command line tool provided by Apple.
273
271
  - With the iTMSTransporter you cannot create new version on iTunes Connect or actually publish the newly uploaded ipa file. This is why there is some browser scripting involved, using [Capybara](https://github.com/jnicklas/capybara) and [Poltergeist](https://github.com/teampoltergeist/poltergeist).
@@ -275,13 +273,13 @@ Before actually uploading anything to iTunes, ```Deliver``` will generate a [PDF
275
273
 
276
274
  # Tips
277
275
 
278
- ## Other helpful tools
279
- Check out other tools in this collection to speed up your deployment process:
280
- - [```snapshot```](https://github.com/KrauseFx/snapshot): Create hundreds of screenshots of your iPhone app... while doing something else.
281
- - [```frameit```](https://github.com/KrauseFx/frameit): Want a device frame around your screenshot? Do it in an instant!
282
- - [```PEM```](https://github.com/KrauseFx/pem): Tired of manually creating and maintaining your push certification profiles?
283
- - [```sigh```](https://github.com/KrauseFx/sigh): Because you would rather spend your time building stuff than fighting provisioning.
276
+ ## [`fastlane`](http://fastlane.tools) Toolchain
284
277
 
278
+ - [`fastlane`](http://fastlane.tools): Connect all deployment tools into one streamlined workflow
279
+ - [`snapshot`](https://github.com/KrauseFx/snapshot): Automate taking localized screenshots of your iOS app on every device
280
+ - [`frameit`](https://github.com/KrauseFx/frameit): Quickly put your screenshots into the right device frames
281
+ - [`PEM`](https://github.com/KrauseFx/pem): Automatically generate and renew your push notification profiles
282
+ - [`sigh`](https://github.com/KrauseFx/sigh): Because you would rather spend your time building stuff than fighting provisioning
285
283
 
286
284
  ## Available language codes
287
285
  ```ruby
@@ -293,31 +291,18 @@ You can use [SimulatorStatusMagic](https://github.com/shinydevelopment/Simulator
293
291
 
294
292
  ## Automatically create screenshots
295
293
 
296
- You can easily create screenshots completely automatically in the background using [```snapshot```](https://github.com/KrauseFx/snapshot), the little brother of ```deliver```.
297
-
298
- **Getting started:**
299
-
300
- - Run ```snapshot init``` in your project folder
301
- - You can edit the new ```snapshot.js``` file with your UI Automation code
302
- - Run ```snapshot``` to test if the screenshots work as expected
303
- - Remove the line ```screenshots_path``` from your ```Deliverfile``` to automatically create new screenshots for each deployment.
304
-
305
- From now on, when you start ```deliver```, it will first create the new screenshots for you, which then will be uploaded to iTunes Connect.
294
+ If you want to integrate ```deliver``` with ```snapshot```, check out [fastlane](https://github.com/KrauseFx/fastlane)!
306
295
 
307
296
  More information about ```snapshot``` can be found on the [Snapshot GitHub page](https://github.com/KrauseFx/snapshot).
308
297
 
309
298
  ## Jenkins integration
310
- Depending on how you set up your Jenkins instance, there might be problems with the ```phantomjs``` dependency.
311
-
312
- I've been using [Jenkins App](https://github.com/stisti/jenkins-app) for a long time, where ```Deliver``` works just fine.
313
-
314
- You should not deploy a new App Store update after every commit, since you still have to wait for your review. Instead I recommend using Git Tags, or custom triggers to deploy a new update.
299
+ Detailed instructions about how to set up `deliver` and `fastlane` in `Jenkins` can be found in the [fastlane README](https://github.com/KrauseFx/fastlane#jenkins-integration).
315
300
 
316
301
  ## Editing the ```Deliverfile```
317
302
  Change syntax highlighting to *Ruby*.
318
303
 
319
304
  # Need help?
320
- - If there is a technical problem with ```Deliver```, submit an issue. Run ```deliver --trace``` to get the stacktrace.
305
+ - If there is a technical problem with ```deliver```, submit an issue. Run ```deliver --trace``` to get the stack trace.
321
306
  - I'm available for contract work - drop me an email: deliver@krausefx.com
322
307
 
323
308
  # License
@@ -4,25 +4,21 @@ $:.push File.expand_path("../../lib", __FILE__)
4
4
 
5
5
  require 'deliver'
6
6
  require 'commander/import'
7
- require 'deliver/update_checker'
8
7
 
9
8
  HighLine.track_eof = false
10
9
 
11
10
 
12
11
  # Commander
13
12
  program :version, Deliver::VERSION
14
- program :description, 'CLI for \'Deliver\' - Automate uploading of app metadata, screenshots and app updates to Apple'
13
+ program :description, 'CLI for \'Deliver\' - Upload screenshots, metadata and your app to the App Store using a single command'
15
14
  program :help, 'Author', 'Felix Krause <deliver@krausefx.com>'
16
- program :help, 'Website', 'http://krausefx.com'
15
+ program :help, 'Website', 'http://fastlane.tools'
17
16
  program :help, 'GitHub', 'https://github.com/krausefx/deliver'
18
17
  program :help_formatter, :compact
19
18
 
20
19
  global_option('--verbose') { $verbose = true }
21
20
 
22
21
 
23
- Deliver::UpdateChecker.verify_latest_version
24
-
25
-
26
22
  default_command :run
27
23
 
28
24
  require 'deliver/commands'
@@ -1,7 +1,6 @@
1
1
  # For more information about each property, visit the GitHub documentation: https://github.com/krausefx/deliver
2
2
  # Everything next to a # is a comment and will be ignored
3
3
 
4
- email '[[EMAIL]]'
5
4
  # hide_transporter_output # remove the '#' in the beginning of the line, to hide the output while uploading
6
5
 
7
6
 
@@ -16,6 +15,7 @@ apple_id "[[APPLE_ID]]"
16
15
 
17
16
  # This folder has to include one folder for each language
18
17
  # More information about automatic screenshot upload:
18
+ # https://github.com/KrauseFx/deliver#upload-screenshots-to-itunes-connect
19
19
  screenshots_path "./deliver/screenshots/"
20
20
 
21
21
 
@@ -38,18 +38,22 @@ ipa do
38
38
  # Attention: When you return a valid ipa file, this file will get uploaded and released
39
39
  # If you only want to upload app metadata, remove the complete ipa block.
40
40
 
41
- # system("ipa build") # build your project using Shenzhen
41
+ # system("ipa build --verbose") # build your project using Shenzhen
42
42
  "./[[APP_NAME]].ipa" # Tell 'Deliver' where it can find the finished ipa file
43
43
  end
44
44
 
45
- # ipa "./latest.ipa" # this can be used, if you prefer manually building the ipa file
45
+ # ipa "./latest.ipa" # this can be used instead of the `do` block, if you prefer manually building the ipa file
46
46
 
47
- # beta_ipa "./ad_hoc_build.ipa" # upload ipa file using `deliver --beta`
47
+ # beta_ipa do
48
+ # system("ipa build --verbose") # customize this to build beta version
49
+ # "./ad_hoc_build.ipa" # upload ipa file using `deliver --beta`
50
+ # end
48
51
 
49
52
  # unit_tests do
53
+ # If you use fastlane (http://github.com/krausefx/fastlane), run the tests there
50
54
  # system("xctool test")
51
55
  # end
52
56
 
53
57
  success do
54
- system("say 'Successfully deployed a new version.'")
58
+ # system("say 'Successfully deployed a new version.'")
55
59
  end
@@ -7,7 +7,6 @@
7
7
  #
8
8
  # Everything next to a # is a comment and will be ignored
9
9
 
10
- email "yourappleid@company.com"
11
10
  # hide_transporter_output # remove the '#' in the beginning of the line, to hide the output while uploading
12
11
 
13
12
  ########################################
@@ -15,13 +14,9 @@ email "yourappleid@company.com"
15
14
  ########################################
16
15
 
17
16
 
18
-
19
- # The app identifier is required
20
- app_identifier "[Your App Identifier, e.g. at.felixkrause.app_name]"
21
-
22
-
23
17
  # This folder has to include one folder for each language
24
18
  # More information about automatic screenshot upload:
19
+ # https://github.com/KrauseFx/deliver#upload-screenshots-to-itunes-connect
25
20
  screenshots_path "./screenshots"
26
21
 
27
22
 
@@ -51,18 +46,22 @@ ipa do
51
46
  # Attention: When you return a valid ipa file, this file will get uploaded and released
52
47
  # If you only want to upload app metadata, remove the complete ipa block.
53
48
 
54
- # system("ipa build") # build your project using Shenzhen
49
+ # system("ipa build --verbose") # build your project using Shenzhen
55
50
  "./[[APP_NAME]].ipa" # Tell 'Deliver' where it can find the finished ipa file
56
51
  end
57
52
 
58
- # ipa "./latest.ipa" # this can be used, if you prefer manually building the ipa file
53
+ # ipa "./latest.ipa" # this can be used instead of the `do` block, if you prefer manually building the ipa file
59
54
 
60
- # beta_ipa "./ad_hoc_build.ipa" # upload ipa file using `deliver --beta`
55
+ # beta_ipa do
56
+ # system("ipa build --verbose") # customize this to build beta version
57
+ # "./ad_hoc_build.ipa" # upload ipa file using `deliver --beta`
58
+ # end
61
59
 
62
60
  # unit_tests do
61
+ # If you use fastlane (http://github.com/krausefx/fastlane), run the tests there
63
62
  # system("xctool test")
64
63
  # end
65
64
 
66
65
  success do
67
- system("say 'Successfully deployed a new version.'")
68
- end
66
+ # system("say 'Successfully deployed a new version.'")
67
+ end
@@ -14,12 +14,14 @@ require 'deliver/deliverer'
14
14
  require 'deliver/ipa_uploader'
15
15
  require 'deliver/languages'
16
16
  require 'deliver/pdf_generator'
17
- require 'deliver/dependency_checker'
18
17
  require 'deliver/deliver_process'
18
+ require 'deliver/dependency_checker'
19
+ require 'deliver/update_checker'
19
20
 
20
21
  # Third Party code
21
22
  require 'colored'
22
23
 
23
24
  module Deliver
24
- # Your code goes here...
25
+ Deliver::UpdateChecker.verify_latest_version
26
+ Deliver::DependencyChecker.check_dependencies
25
27
  end
@@ -5,6 +5,8 @@ module Deliver
5
5
  end
6
6
  class AppMetadataParameterError < StandardError
7
7
  end
8
+ class AppMetadataTooManyScreenshotsError < StandardError
9
+ end
8
10
 
9
11
  class AppMetadata
10
12
  ITUNES_NAMESPACE = "http://apple.com/itunes/importer"
@@ -214,7 +216,7 @@ module Deliver
214
216
  # Appends another screenshot to the already existing ones
215
217
  # @param (String) language The language, which has to be in this list: {Deliver::Languages}.
216
218
  # @param (Deliver::AppScreenshot) app_screenshot The screenshot you want to add to the app metadata.
217
- # @raise (AppMetadataParameterError) When there are already 5 screenshots (MAXIMUM_NUMBER_OF_SCREENSHOTS).
219
+ # @raise (AppMetadataTooManyScreenshotsError) When there are already 5 screenshots (MAXIMUM_NUMBER_OF_SCREENSHOTS).
218
220
 
219
221
  def add_screenshot(language, app_screenshot)
220
222
  raise AppMetadataParameterError.new(INVALID_LANGUAGE_ERROR) unless Languages::ALL_LANGUAGES.include?language
@@ -246,7 +248,7 @@ module Deliver
246
248
  end
247
249
 
248
250
  if next_index > MAXIMUM_NUMBER_OF_SCREENSHOTS
249
- raise AppMetadataParameterError.new("Only #{MAXIMUM_NUMBER_OF_SCREENSHOTS} screenshots are allowed per language per device type (#{app_screenshot.screen_size})")
251
+ raise AppMetadataTooManyScreenshotsError.new("Only #{MAXIMUM_NUMBER_OF_SCREENSHOTS} screenshots are allowed per language per device type (#{app_screenshot.screen_size})")
250
252
  end
251
253
 
252
254
  # Ready for storing the screenshot into the metadata.xml now
@@ -312,7 +314,13 @@ module Deliver
312
314
  self.clear_all_screenshots(language)
313
315
 
314
316
  Dir.glob(resulting_path, File::FNM_CASEFOLD).sort.each do |path|
315
- add_screenshot(language, Deliver::AppScreenshot.new(path))
317
+ next if path.include?"_framed."
318
+
319
+ begin
320
+ add_screenshot(language, Deliver::AppScreenshot.new(path))
321
+ rescue AppMetadataTooManyScreenshotsError => ex
322
+ # We just use the first 5 ones
323
+ end
316
324
  end
317
325
  end
318
326
  end
@@ -5,8 +5,6 @@ command :init do |c|
5
5
  c.description = "Creates a new Deliverfile in the current directory"
6
6
 
7
7
  c.action do |args, options|
8
- Deliver::DependencyChecker.check_dependencies
9
-
10
8
  Deliver::DeliverfileCreator.create(enclosed_directory)
11
9
  end
12
10
  end
@@ -7,16 +7,17 @@ command :run do |c|
7
7
  c.option '--beta', 'Runs a deployment to beta build on iTunes Connect'
8
8
  c.option '--skip-deploy', 'Skips deployment on iTunes Connect'
9
9
  c.action do |args, options|
10
- Deliver::DependencyChecker.check_dependencies
11
-
12
- if File.exists?(deliver_path)
13
- # Everything looks alright, use the given Deliverfile
14
- options.default :beta => false, :skip_deploy => false
15
- Deliver::Deliverer.new(deliver_path, force: options.force, is_beta_ipa: options.beta, skip_deploy: options.skip_deploy)
16
- else
17
- Deliver::Helper.log.warn("No Deliverfile found at path '#{deliver_path}'.")
18
- if agree("Do you want to create a new Deliverfile at the current directory? (y/n)", true)
19
- Deliver::DeliverfileCreator.create(enclosed_directory)
10
+ path = (Deliver::Helper.fastlane_enabled?? './fastlane' : '.')
11
+ Dir.chdir(path) do # switch the context
12
+ if File.exists?(deliver_path)
13
+ # Everything looks alright, use the given Deliverfile
14
+ options.default :beta => false, :skip_deploy => false
15
+ Deliver::Deliverer.new(deliver_path, force: options.force, is_beta_ipa: options.beta, skip_deploy: options.skip_deploy)
16
+ else
17
+ Deliver::Helper.log.warn("No Deliverfile found at path '#{deliver_path}'.")
18
+ if agree("Do you want to create a new Deliverfile at the current directory? (y/n)", true)
19
+ Deliver::DeliverfileCreator.create(enclosed_directory)
20
+ end
20
21
  end
21
22
  end
22
23
  end
@@ -1,5 +1,3 @@
1
- require 'snapshot'
2
-
3
1
  module Deliver
4
2
  # This class takes care of verifying all inputs and triggering the upload process
5
3
  class DeliverProcess
@@ -8,10 +6,6 @@ module Deliver
8
6
  class DeliverUnitTestsError < StandardError
9
7
  end
10
8
 
11
- # DeliverUnitTestsError is triggered, when the unit tests of the given block failed.
12
- class DeliverUIAutomationError < StandardError
13
- end
14
-
15
9
  # @return (Deliver::App) The App that is currently being edited.
16
10
  attr_accessor :app
17
11
 
@@ -22,6 +16,9 @@ module Deliver
22
16
  # is used to store the deploy information until the Deliverfile finished running.
23
17
  attr_accessor :deploy_information
24
18
 
19
+ # @return (String): The app identifier of the currently used app (e.g. com.krausefx.app)
20
+ attr_accessor :app_identifier
21
+
25
22
  def initialize(deploy_information = nil)
26
23
  @deploy_information = deploy_information || {}
27
24
  @deploy_information[:blocks] ||= {}
@@ -49,7 +46,7 @@ module Deliver
49
46
  trigger_ipa_upload
50
47
 
51
48
  call_success_block
52
- rescue Exception => ex
49
+ rescue => ex
53
50
  call_error_block(ex)
54
51
  end
55
52
  end
@@ -91,6 +88,8 @@ module Deliver
91
88
  raise "Could not find an ipa file for 'beta' mode. Provide one using `beta_ipa do ... end` in your Deliverfile.".red
92
89
  end
93
90
 
91
+ ENV["DELIVER_IPA_PATH"] = used_ipa_file
92
+
94
93
  if used_ipa_file
95
94
  upload_strategy = Deliver::IPA_UPLOAD_STRATEGY_APP_STORE
96
95
  if is_beta_build?
@@ -109,7 +108,12 @@ module Deliver
109
108
  end
110
109
  end
111
110
 
111
+ def fetch_app_identifier_from_app_file
112
+ @app_identifier = (CredentialsManager::AppfileConfig.try_fetch_value(:app_identifier) rescue nil)
113
+ end
114
+
112
115
  def verify_ipa_file
116
+ fetch_app_identifier_from_app_file unless @app_identifier
113
117
  raise Deliverfile::Deliverfile::DeliverfileDSLError.new(Deliverfile::Deliverfile::MISSING_APP_IDENTIFIER_MESSAGE.red) unless @app_identifier
114
118
  raise Deliverfile::Deliverfile::DeliverfileDSLError.new(Deliverfile::Deliverfile::MISSING_VERSION_NUMBER_MESSAGE.red) unless @app_version
115
119
  end
@@ -174,23 +178,12 @@ module Deliver
174
178
  def set_screenshots
175
179
  screens_path = @deploy_information[Deliverer::ValKey::SCREENSHOTS_PATH]
176
180
 
177
- # Check if there is a Snapfile
178
- if File.exists?('./Snapfile') and not screens_path
179
-
180
- Helper.log.info("Found a Snapfile, using it to create new screenshots.".green)
181
- begin
182
- Snapshot::Runner.new.work
183
- Helper.log.info("Looking for screenshots in './screenshots'.".yellow)
184
- @app.metadata.set_all_screenshots_from_path('./screenshots')
185
- rescue Exception => ex
186
- # There were some UI Automation errors
187
- raise DeliverUIAutomationError.new(ex)
188
- end
189
-
190
- elsif screens_path
191
- if File.exists?('./Snapfile')
192
- Helper.log.info("Found a Snapfile. Ignoring it. If you want 'deliver' to automatically take new screenshots for you, remove 'screenshots_path' from your 'Deliverfile'.".yellow)
193
- end
181
+ if (ENV["DELIVER_SCREENSHOTS_PATH"] || '').length > 0
182
+ Helper.log.warn "Overwriting screenshots path from config (#{screens_path}) with (#{ENV["DELIVER_SCREENSHOTS_PATH"]})".yellow
183
+ screens_path = ENV["DELIVER_SCREENSHOTS_PATH"]
184
+ end
185
+
186
+ if screens_path
194
187
  # Not using Snapfile. Not a good user.
195
188
  if not @app.metadata.set_all_screenshots_from_path(screens_path)
196
189
  # This path does not contain folders for each language
@@ -19,7 +19,7 @@ module Deliver
19
19
  # filename itself.
20
20
  def initialize(deliver_data, path = nil)
21
21
  path ||= "./#{FILE_NAME}"
22
- raise "#{FILE_NAME} not found at path '#{path}'".red unless File.exists?(path.to_s)
22
+ raise "#{FILE_NAME} not found at path '#{File.expand_path(path)}'".red unless File.exists?(path.to_s)
23
23
 
24
24
  self.path = path
25
25
  @deliver_data = deliver_data
@@ -1,3 +1,6 @@
1
+ require 'credentials_manager/password_manager'
2
+ require 'credentials_manager/appfile_config'
3
+
1
4
  module Deliver
2
5
  # Helps new user quickly adopt Deliver
3
6
  class DeliverfileCreator
@@ -12,14 +15,14 @@ module Deliver
12
15
  project_name ||= Dir.pwd.split("/").last
13
16
 
14
17
  if agree("Do you want Deliver to automatically create the Deliverfile for you based " +
15
- "on your current app? (y/n)", true)
18
+ "on your current app? The app has to be in the App Store to use this feature. (y/n)", true)
16
19
 
17
20
  puts "\n\nFirst, you need to login with your iTunesConnect credentials. ".yellow +
18
21
  "\nThis is necessary to fetch the latest metadata from your app and use it to create a Deliverfile for you." +
19
22
  "\nIf you have previously entered your credentials already, you will not be asked again."
20
23
 
21
- if Deliver::PasswordManager.shared_manager.username and Deliver::PasswordManager.shared_manager.password
22
- identifier = ''
24
+ if CredentialsManager::PasswordManager.shared_manager.username and CredentialsManager::PasswordManager.shared_manager.password
25
+ identifier = ((CredentialsManager::AppfileConfig.try_fetch_value(:app_identifier) rescue '') || '')
23
26
  while identifier.length < 3
24
27
  identifier = ask("\nApp Identifier of your app (e.g. at.felixkrause.app_name): ")
25
28
  end
@@ -91,7 +94,7 @@ module Deliver
91
94
  deliver.gsub!("[[APP_IDENTIFIER]]", app.app_identifier)
92
95
  deliver.gsub!("[[APP_NAME]]", project_name)
93
96
  deliver.gsub!("[[APPLE_ID]]", app.apple_id.to_s)
94
- deliver.gsub!("[[EMAIL]]", PasswordManager.shared_manager.username)
97
+ deliver.gsub!("[[EMAIL]]", CredentialsManager::PasswordManager.shared_manager.username)
95
98
 
96
99
  return deliver
97
100
  end
@@ -1,4 +1,5 @@
1
1
  # Inspired by https://github.com/CocoaPods/Core/blob/master/lib/cocoapods-core/podfile/dsl.rb
2
+ require 'credentials_manager/password_manager'
2
3
 
3
4
  module Deliver
4
5
  module Deliverfile
@@ -102,7 +103,7 @@ module Deliver
102
103
  # This will set the email address of the Apple ID to be used
103
104
  def email(value)
104
105
  value ||= yield if block_given?
105
- PasswordManager.shared_manager(value)
106
+ CredentialsManager::PasswordManager.shared_manager(value)
106
107
  end
107
108
 
108
109
  # This will hide the output of the iTunes Connect transporter while uploading/downloading
@@ -1,6 +1,7 @@
1
1
  module Deliver
2
2
  class DependencyChecker
3
3
  def self.check_dependencies
4
+ return if Helper.is_test?
4
5
  self.check_phantom_js
5
6
  self.check_xcode_select
6
7
  end
@@ -50,6 +50,11 @@ module Deliver
50
50
  def self.transporter_path
51
51
  self.xcode_path + '../Applications/Application\ Loader.app/Contents/MacOS/itms/bin/iTMSTransporter'
52
52
  end
53
+
54
+ def self.fastlane_enabled?
55
+ # This is called from the root context on the first start
56
+ @@enabled ||= File.directory?"./fastlane"
57
+ end
53
58
 
54
59
  end
55
60
  end
@@ -71,15 +71,13 @@ module Deliver
71
71
  is_okay = true
72
72
  begin
73
73
  transporter.upload(@app, @metadata_dir)
74
- rescue Exception => ex
74
+ rescue => ex
75
75
  Helper.log.debug ex
76
76
  is_okay = ex.to_s.include?"ready exists a binary upload with build" # this just means, the ipa is already online
77
77
  end
78
78
 
79
79
  if is_okay
80
80
  unless Helper.is_test?
81
- `rm -rf ./#{@app.apple_id}.itmsp` # we don't need this file any more
82
-
83
81
  return publish_on_itunes_connect(submit_information)
84
82
  end
85
83
  end
@@ -1,9 +1,7 @@
1
- require 'deliver/password_manager'
2
-
3
1
  require 'capybara'
4
2
  require 'capybara/poltergeist'
5
- require 'security'
6
3
  require 'fastimage'
4
+ require 'credentials_manager/password_manager'
7
5
 
8
6
 
9
7
  module Deliver
@@ -62,7 +60,7 @@ module Deliver
62
60
 
63
61
  # Loggs in a user with the given login data on the iTC Frontend.
64
62
  # You don't need to pass a username and password. It will
65
- # Automatically be fetched using the {Deliver::PasswordManager}.
63
+ # Automatically be fetched using the {CredentialsManager::PasswordManager}.
66
64
  # This method will also automatically be called when triggering other
67
65
  # actions like {#open_app_page}
68
66
  # @param user (String) (optional) The username/email address
@@ -75,8 +73,8 @@ module Deliver
75
73
  begin
76
74
  Helper.log.info "Logging into iTunesConnect"
77
75
 
78
- user ||= PasswordManager.shared_manager.username
79
- password ||= PasswordManager.shared_manager.password
76
+ user ||= CredentialsManager::PasswordManager.shared_manager.username
77
+ password ||= CredentialsManager::PasswordManager.shared_manager.password
80
78
 
81
79
  result = visit ITUNESCONNECT_URL
82
80
  raise "Could not open iTunesConnect" unless result['status'] == 'success'
@@ -100,7 +98,7 @@ module Deliver
100
98
  else
101
99
  raise ItunesConnectLoginError.new("Looks like your login data was correct, but you do not have access to the apps.")
102
100
  end
103
- rescue Exception => ex
101
+ rescue => ex
104
102
  Helper.log.debug(ex)
105
103
  raise ItunesConnectLoginError.new("Error logging in user #{user} with the given password. Make sure you entered them correctly.")
106
104
  end
@@ -108,7 +106,7 @@ module Deliver
108
106
  Helper.log.info "Successfully logged into iTunesConnect"
109
107
 
110
108
  true
111
- rescue Exception => ex
109
+ rescue => ex
112
110
  error_occured(ex)
113
111
  end
114
112
  end
@@ -131,11 +129,11 @@ module Deliver
131
129
  sleep 3
132
130
 
133
131
  if current_url.include?"wa/defaultError" # app could not be found
134
- raise "Could not open app details for app '#{app}'. Make sure you're using the correct Apple ID and the correct Apple developer account (#{PasswordManager.shared_manager.username}).".red
132
+ raise "Could not open app details for app '#{app}'. Make sure you're using the correct Apple ID and the correct Apple developer account (#{CredentialsManager::PasswordManager.shared_manager.username}).".red
135
133
  end
136
134
 
137
135
  true
138
- rescue Exception => ex
136
+ rescue => ex
139
137
  error_occured(ex)
140
138
  end
141
139
  end
@@ -191,7 +189,7 @@ module Deliver
191
189
  Helper.log.debug "Could not fetch version number of the live version for app #{app}."
192
190
  return nil
193
191
  end
194
- rescue Exception => ex
192
+ rescue => ex
195
193
  error_occured(ex)
196
194
  end
197
195
  end
@@ -242,7 +240,7 @@ module Deliver
242
240
  if created_version != version_number
243
241
  raise "Some other version ('#{created_version}') was created instead of the one you defined ('#{version_number}')"
244
242
  end
245
- rescue Exception => ex
243
+ rescue => ex
246
244
  # Can not fetch the version number of the new version (this happens, when it's e.g. 'Developer Rejected')
247
245
  unless page.has_content?version_number
248
246
  raise "Some other version was created instead of the one you defined ('#{version_number}')."
@@ -251,7 +249,7 @@ module Deliver
251
249
  end
252
250
 
253
251
  true
254
- rescue Exception => ex
252
+ rescue => ex
255
253
  error_occured(ex)
256
254
  end
257
255
  end
@@ -275,7 +273,7 @@ module Deliver
275
273
  # Capybara.ignore_hidden_elements = true
276
274
  # first(:button, "Save").click
277
275
 
278
- # rescue Exception => ex
276
+ # rescue => ex
279
277
  # error_occured(ex)
280
278
  # end
281
279
  # end
@@ -309,7 +307,7 @@ module Deliver
309
307
 
310
308
 
311
309
  return true
312
- rescue Exception => ex
310
+ rescue => ex
313
311
  error_occured(ex)
314
312
  end
315
313
  end
@@ -338,7 +336,7 @@ module Deliver
338
336
  begin
339
337
  first('a', :text => BUTTON_ADD_NEW_BUILD).click
340
338
  wait_for_elements(".buildModalList")
341
- sleep 1
339
+ sleep 5
342
340
  rescue
343
341
  if page.has_content?"Upload Date"
344
342
  # That's fine, the ipa was already selected
@@ -360,7 +358,7 @@ module Deliver
360
358
  raise "Could not put build itself onto production. Try opening '#{current_url}'" if error
361
359
 
362
360
  return true
363
- rescue Exception => ex
361
+ rescue => ex
364
362
  error_occured(ex)
365
363
  end
366
364
  end
@@ -408,10 +406,17 @@ module Deliver
408
406
  contains_third_party_content: false,
409
407
  has_rights: false
410
408
  },
411
- advertising_identifier: false
409
+ advertising_identifier: {
410
+ use_idfa: false,
411
+ serve_advertisement: false,
412
+ attribute_advertisement: false,
413
+ attribute_actions: false,
414
+ limit_ad_tracking: false
415
+ }
412
416
  }
413
417
 
414
418
  basic = "//*[@itc-radio='submitForReviewAnswers"
419
+ checkbox = "//*[@itc-checkbox='submitForReviewAnswers"
415
420
 
416
421
  #####################
417
422
  # Export Compliance #
@@ -450,10 +455,21 @@ module Deliver
450
455
  # Advertising Identifier #
451
456
  ##########################
452
457
  if page.has_content?"Advertising Identifier"
453
- first(:xpath, "#{basic}.adIdInfo.usesIdfa.value' and @radio-value='#{perms[:advertising_identifier]}']//input").trigger('click') rescue nil
454
-
455
- if perms[:advertising_identifier]
456
- raise "Sorry, the advertising_identifier menu is not yet supported. Open '#{current_url}' in your browser and manally submit the app".red
458
+ first(:xpath, "#{basic}.adIdInfo.usesIdfa.value' and @radio-value='#{perms[:advertising_identifier][:use_idfa]}']//a").click rescue nil
459
+
460
+ if perms[:advertising_identifier][:use_idfa]
461
+ if perms[:advertising_identifier][:serve_advertisement]
462
+ first(:xpath, "#{checkbox}.adIdInfo.servesAds.value']//a").click
463
+ end
464
+ if perms[:advertising_identifier][:attribute_advertisement]
465
+ first(:xpath, "#{checkbox}.adIdInfo.tracksInstall.value']//a").click
466
+ end
467
+ if perms[:advertising_identifier][:attribute_actions]
468
+ first(:xpath, "#{checkbox}.adIdInfo.tracksAction.value']//a").click
469
+ end
470
+ if perms[:advertising_identifier][:limit_ad_tracking]
471
+ first(:xpath, "#{checkbox}.adIdInfo.limitsTracking.value']//a").click
472
+ end
457
473
  end
458
474
  end
459
475
 
@@ -474,7 +490,7 @@ module Deliver
474
490
  raise "Something is missing here.".red
475
491
  end
476
492
  return false
477
- rescue Exception => ex
493
+ rescue => ex
478
494
  error_occured(ex)
479
495
  end
480
496
  end
@@ -533,4 +549,4 @@ module Deliver
533
549
  return results
534
550
  end
535
551
  end
536
- end
552
+ end
@@ -1,6 +1,6 @@
1
1
  require 'pty'
2
2
  require 'shellwords'
3
- require 'deliver/password_manager'
3
+ require 'credentials_manager/password_manager'
4
4
 
5
5
 
6
6
  module Deliver
@@ -27,10 +27,10 @@ module Deliver
27
27
 
28
28
  # Returns a new instance of the iTunesTransporter.
29
29
  # If no username or password given, it will be taken from
30
- # the #{Deliver::PasswordManager}
30
+ # the #{CredentialsManager::PasswordManager}
31
31
  def initialize(user = nil, password = nil)
32
- @user = (user || PasswordManager.shared_manager.username)
33
- @password = (password || PasswordManager.shared_manager.password)
32
+ @user = (user || CredentialsManager::PasswordManager.shared_manager.username)
33
+ @password = (password || CredentialsManager::PasswordManager.shared_manager.password)
34
34
  end
35
35
 
36
36
  # Downloads the latest version of the app metadata package from iTC.
@@ -80,6 +80,8 @@ module Deliver
80
80
 
81
81
  if result
82
82
  Helper.log.info "Successfully uploaded package to iTunesConnect. It might take a few minutes until it's visible online.".green
83
+
84
+ FileUtils.rm_rf(dir) unless Helper.is_test? # we don't need the package any more, since the upload was successful
83
85
  end
84
86
 
85
87
  result
@@ -103,7 +105,7 @@ module Deliver
103
105
  parse_line(line) # this is where the parsing happens
104
106
  end
105
107
  end
106
- rescue Exception => ex
108
+ rescue => ex
107
109
  Helper.log.fatal(ex.to_s)
108
110
  @errors << ex.to_s
109
111
  end
@@ -114,6 +116,7 @@ module Deliver
114
116
 
115
117
  if @errors.count > 0
116
118
  Helper.log.error(@errors.join("\n"))
119
+ return false
117
120
  end
118
121
 
119
122
  true
@@ -131,7 +134,7 @@ module Deliver
131
134
  if $1.include?"Your Apple ID or password was entered incorrectly" or
132
135
  $1.include?"This Apple ID has been locked for security reasons"
133
136
 
134
- Deliver::PasswordManager.shared_manager.password_seems_wrong
137
+ CredentialsManager::PasswordManager.shared_manager.password_seems_wrong unless Helper.is_test?
135
138
  elsif $1.include?"Redundant Binary Upload. There already exists a binary upload with build"
136
139
  Helper.log.fatal $1
137
140
  Helper.log.fatal "You have to change the build number of your app to upload your ipa file"
@@ -25,7 +25,7 @@ module Deliver
25
25
  if latest and Gem::Version.new(latest) > Gem::Version.new(current_version)
26
26
  return true
27
27
  end
28
- rescue Exception => ex
28
+ rescue => ex
29
29
  Helper.log.error("Could not check if 'deliver' is up to date.")
30
30
  end
31
31
  return false
@@ -1,3 +1,3 @@
1
1
  module Deliver
2
- VERSION = "0.4.2"
2
+ VERSION = "0.5.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deliver
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Felix Krause
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-04 00:00:00.000000000 Z
11
+ date: 2015-01-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: security
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ~>
32
- - !ruby/object:Gem::Version
33
- version: 0.1.3
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ~>
39
- - !ruby/object:Gem::Version
40
- version: 0.1.3
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: highline
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -151,7 +137,7 @@ dependencies:
151
137
  - !ruby/object:Gem::Version
152
138
  version: '0'
153
139
  - !ruby/object:Gem::Dependency
154
- name: snapshot
140
+ name: credentials_manager
155
141
  requirement: !ruby/object:Gem::Requirement
156
142
  requirements:
157
143
  - - '>='
@@ -290,12 +276,8 @@ dependencies:
290
276
  - - '>='
291
277
  - !ruby/object:Gem::Version
292
278
  version: '0'
293
- description: "Using Deliver you can easily integrate a real continuous delivery \n
294
- \ solution for iOS applications. You can update the app metadata, upload screenshots
295
- \n in all languages for different screensizes to iTunesConnect and even publish
296
- a new \n ipa file to iTunesConnect. You define your prefered deployment information
297
- once in a so called\n Deliverfile and store it in git, to easily deploy from
298
- every machine, even your Continuos Integration server"
279
+ description: Upload screenshots, metadata and your app to the App Store using a single
280
+ command
299
281
  email:
300
282
  - deliver@krausefx.com
301
283
  executables:
@@ -330,15 +312,14 @@ files:
330
312
  - lib/deliver/itunes_transporter.rb
331
313
  - lib/deliver/languages.rb
332
314
  - lib/deliver/metadata_item.rb
333
- - lib/deliver/password_manager.rb
334
315
  - lib/deliver/pdf_generator.rb
335
316
  - lib/deliver/update_checker.rb
336
317
  - lib/deliver/version.rb
337
- homepage: http://krausefx.com
318
+ homepage: http://fastlane.tools
338
319
  licenses:
339
320
  - MIT
340
321
  metadata: {}
341
- post_install_message: This gem requires phantomjs. Install it using 'brew update &&
322
+ post_install_message: deliver requires phantomjs. Install it using 'brew update &&
342
323
  brew install phantomjs'
343
324
  rdoc_options: []
344
325
  require_paths:
@@ -358,7 +339,7 @@ rubyforge_project:
358
339
  rubygems_version: 2.2.2
359
340
  signing_key:
360
341
  specification_version: 4
361
- summary: Deliver - Continuous Deployment for iOS - automatically publish new app updates
362
- and app screenshots to the AppStore
342
+ summary: Upload screenshots, metadata and your app to the App Store using a single
343
+ command
363
344
  test_files: []
364
345
  has_rdoc:
@@ -1,110 +0,0 @@
1
- require 'security'
2
- require 'highline/import' # to hide the entered password
3
-
4
- module Deliver
5
- # Handles reading out the password from the keychain or asking for login data
6
- class PasswordManager
7
- # @return [String] The username / email address of the currently logged in user
8
- attr_accessor :username
9
- # @return [String] The password of the currently logged in user
10
- attr_accessor :password
11
-
12
- HOST = "deliver" # there might be a string appended, if user has multiple accounts
13
- private_constant :HOST
14
-
15
- # A singleton object, which also makes sure, to use the correct Apple ID
16
- # @param id_to_use (String) The Apple ID email address which should be used
17
- def self.shared_manager(id_to_use = nil)
18
- @@instance ||= PasswordManager.new(id_to_use)
19
- end
20
-
21
- # A new instance of PasswordManager.
22
- #
23
- # This already check the Keychain if there is a username and password stored.
24
- # If that's not the case, it will ask for login data via stdin
25
- # @param id_to_use (String) Apple ID (e.g. steve@apple.com) which should be used for this upload.
26
- # if given, only the password will be asked/loaded.
27
- def initialize(id_to_use = nil)
28
- self.username ||= ENV["DELIVER_USER"] || id_to_use || load_from_keychain[0]
29
- self.password ||= ENV["DELIVER_PASSWORD"] || load_from_keychain[1]
30
-
31
- if (self.username || '').length == 0 or (self.password || '').length == 0
32
- puts "No username or password given. You can set environment variables:"
33
- puts "DELIVER_USER, DELIVER_PASSWORD"
34
-
35
- ask_for_login
36
- end
37
- end
38
-
39
- # This method is called, when the iTunes backend returns that the login data is wrong
40
- # This will ask the user, if he wants to re-enter the password
41
- def password_seems_wrong
42
- return false if Helper.is_test?
43
-
44
- puts "It seems like the username or password for the account '#{self.username}' is wrong."
45
- reenter = agree("Do you want to re-enter your username and password? (y/n)", true)
46
- if reenter
47
- remove_from_keychain
48
-
49
- @username = nil
50
- @password = nil
51
-
52
- puts "You will have to re-run the recent command to use the new username/password."
53
- return true
54
- else
55
- return false
56
- end
57
- end
58
-
59
- private
60
- def ask_for_login
61
- puts "--------------------------------------------------------------------------".green
62
- puts "The login information you enter now will be stored in your keychain ".green
63
- puts "More information about that on GitHub: https://github.com/krausefx/deliver".green
64
- puts "--------------------------------------------------------------------------".green
65
-
66
- username_was_there = self.username
67
-
68
- while (self.username || '').length == 0
69
- self.username = ask("Username: ")
70
- end
71
-
72
- self.password ||= load_from_keychain[1] # maybe there was already something stored in the keychain
73
-
74
- if (self.password || '').length > 0
75
- return true
76
- else
77
- while (self.password || '').length == 0
78
- text = "Password: "
79
- text = "Password (for #{self.username}): " if username_was_there
80
- self.password = ask(text) { |q| q.echo = "*" }
81
- end
82
-
83
- # Now we store this information in the keychain
84
- # Example usage taken from https://github.com/nomad/cupertino/blob/master/lib/cupertino/provisioning_portal/commands/login.rb
85
- if Security::InternetPassword.add(hostname, self.username, self.password)
86
- return true
87
- else
88
- Helper.log.error "Could not store password in keychain"
89
- return false
90
- end
91
- end
92
- end
93
-
94
- def remove_from_keychain
95
- puts "removing keychain item: #{hostname}"
96
- Security::InternetPassword.delete(:server => hostname)
97
- end
98
-
99
- def load_from_keychain
100
- pass = Security::InternetPassword.find(:server => hostname)
101
-
102
- return [pass.attributes['acct'], pass.password] if pass
103
- return [nil, nil]
104
- end
105
-
106
- def hostname
107
- [HOST, self.username].join('.')
108
- end
109
- end
110
- end