Deliver • Snapshot • FrameIt • PEM • Sigh
-------Updating your iOS app should not be painful and time consuming.
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.
Follow the developer on Twitter: @KrauseFx
Features • Installation • Quick Start • Usage • Credentials • Can I trust Deliver? • Tips • Need help?
- Upload hundreds of screenshots with different languages from different devices
- Upload a new ipa file to iTunes Connect without Xcode from any computer
- Update app metadata
- Easily implement a real Continuous Deployment process
- Store the configuration in git to easily deploy from any computer, including your Continuous Integration server (e.g. Jenkins)
- Get a PDF preview of the fetched metadata before uploading the app metadata and screenshots to Apple: Example Preview (Yes, those are screenshots taken for all screen sizes)
- Automatically create new screenshots with Snapshot
Install the gem
sudo gem install deliver
Make sure, you have the latest version of the Xcode command line tools installed:
xcode-select --install
Install phantomjs (this is needed to control the iTunes Connect frontend)
brew update && brew install phantomjs
If you don't already have homebrew installed, install it here.
To create new screenshots automatically, check out my other open source project Snapshot.
The guide will create all the necessary files for you, using the existing app metadata from iTunes Connect.
cd [your_project_folder]
deliver init
- When your app is already in the App Store:
y
- Enter your iTunes Connect credentials
- Enter your app identifier
- Enjoy a good drink, while the computer does all the work for you
- When it's a new app:
n
Copy your screenshots into the deliver/screenshots/[language]
folders (see Available language codes)
From now on, you can run deliver
to deploy a new update, or just upload new app metadata and screenshots.
Open the Deliverfile
using a text editor and customize it even further. Take a look at the following settings:
ipa
: You can either pass a static path to an ipa file, or add your custom build script.unit_tests
: Uncomment the code to run tests. (e.g. using xctool)
Why should you have to remember complicated commands and parameters?
Store your configuration in a text file to easily deploy from any computer.
Run deliver init
to create a new Deliverfile
. You can either let the wizard generate a file based on the metadata from iTunes Connect or create one from a template.
Once you created your configuration, just run deliver
.
Here are a few example files:
app_identifier "net.sunapps.1"
version "1.1"
screenshots_path "./screenshots"
The screenshots folder must include one subfolder per language (see Available language codes).
The screenshots are ordered alphabetically. The best way to sort them is to prepend a number before the actual screenshot name.
To let the computer create the screenshots for you, checkout this section of the README.
If you want to have the screenshots inside a device frame, with a background and a fancy label on top, you can use Sketch to App Store.
This will submit a new update to Apple
ipa do
system("ipa build")
"./name.ipa"
end
changelog({
"en-US" => "This update adds cool new features",
"de-DE" => "Dieses Update ist super"
})
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.
The changelog is only used for App Store submission, not for TestFlight builds.
In order to upload an .ipa
file for Apple TestFlight you need to specify beta_ipa
path in your Deliverfile
beta_ipa do
system("ipa build")
"./name.ipa"
end
and provide --beta
option when calling deliver
.
unit_tests do
system("xctool test")
end
success do
notifier = Slack::Notifier.new("SlackTeam", "SlackToken")
notifier.ping "Successfully deployed new version"
end
error do |exception|
# custom exception handling here
raise "Something went wrong: #{exception}"
end
For this example I used slack-notifier.
default_language "en-US"
version "1.2"
title "Only English Title"
If you do not pass an ipa file, you have to specify the app version you want to edit.
default_language "de-DE"
version "1.2"
keywords ["keyword1", "something", "else"]
description({
"en-US" => File.read("description-en.txt")
"de-DE" => open("http://example.com/app_description.txt").read
})
I'm using Shenzhen, but you can use any build tool or custom scripts.
ipa do
# Add any code you want, like incrementing the build
# number or changing the app identifier
system("ipa build") # build your project using Shenzhen
"./AppName.ipa" # Tell 'Deliver' where it can find the finished ipa file
end
By default, the transporter log is shown, to be fully transparent. If you prefer to hide it, you can use the following option in your Deliverfile
to disable it for both the upload and the download of metadata:
hide_transporter_output
As you can see, the Deliverfile
is a normal Ruby file, which is executed when
running a deployment. Therefore it's possible to fully customise the behaviour
on a deployment.
All available commands with a short description can be found in the wiki.
Some examples:
- Run your own unit tests or integration tests before a deploy (recommended)
- Ask the script user for a changelog
- Deploy a new version just by starting a Jenkins job
- Post the deployment status on Slack
- Upload the latest screenshots on your server
- Many more things, be creative and let me know :)
Some examples:
require 'deliver'
app = Deliver::App.new(app_identifier: 'at.felixkrause.app')
app.get_app_status # => Waiting for Review
app.create_new_version!("1.4")
app.metadata.update_title({ "en-US" => "iPhone App Title" })
app.metadata.set_all_screenshots_from_path("./screenshots")
app.upload_metadata!
app.itc.submit_for_review!(app)
Deliver::ItunesSearchApi.fetch_by_identifier("net.sunapps.15") # => Fetches public metadata
This project is well documented, check it out on Rubydoc.
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.
Therefore it is easy to switch between projects, without needing to logout and login again.
The first time you use Deliver you have to enter your iTunes Connect credentials. They will be stored in the Keychain.
If you decide to remove your credentials from the Keychain, just open the Keychain Access, select All Items and search for 'deliver'.
You can use the following environment variables to use a specific account instead of the one stored in the keychain. This is especially important if you have more than one iTunes Connect account in your keychain:
DELIVER_USER
DELIVER_PASSWORD
Take a look at Using the exposed Ruby classes.
###How does this thing even work? Is magic involved? 🎩###
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.
Before actually uploading anything to iTunes, Deliver
will generate a PDF summary of the collected data.
Deliver
uses the following techniques under the hood:
- 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.
- 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 and Poltergeist.
- The iTunes search API to find missing information about a certain app, like the apple_id when you only pass the bundle_identifier.
Check out other tools in this collection to speed up your deployment process:
snapshot
: Create hundreds of screenshots of your iPhone app... while doing something else.frameit
: Want a device frame around your screenshot? Do it in an instant!PEM
: Tired of manually creating and maintaining your push certification profiles?sigh
: Because you would rather spend your time building stuff than fighting provisioning.
["da-DK", "de-DE", "el-GR", "en-AU", "en-CA", "en-GB", "en-US", "es-ES", "es-MX", "fi-FI", "fr-CA", "fr-FR", "id-ID", "it-IT", "ja-JP", "ko-KR", "ms-MY", "nl-NL", "no-NO", "pt-BR", "pt-PT", "ru-RU", "sv-SE", "th-TH", "tr-TR", "vi-VI", "cmn-Hans", "zh_CN", "cmn-Hant"]
You can use SimulatorStatusMagic to clean up the status bar.
You can easily create screenshots completely automatically in the background using snapshot
, the little brother of deliver
.
Getting started:
- Run
snapshot init
in your project folder - You can edit the new
snapshot.js
file with your UI Automation code - Run
snapshot
to test if the screenshots work as expected - Remove the line
screenshots_path
from yourDeliverfile
to automatically create new screenshots for each deployment.
From now on, when you start deliver
, it will first create the new screenshots for you, which then will be uploaded to iTunes Connect.
More information about snapshot
can be found on the Snapshot GitHub page.
Depending on how you set up your Jenkins instance, there might be problems with the phantomjs
dependency.
I've been using Jenkins App for a long time, where Deliver
works just fine.
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.
Change syntax highlighting to Ruby.
- If there is a technical problem with
Deliver
, submit an issue. Rundeliver --trace
to get the stacktrace. - I'm available for contract work - drop me an email: deliver@krausefx.com
This project is licensed under the terms of the MIT license. See the LICENSE file.
- Create an issue to discuss about your idea
- Fork it (https://github.com/KrauseFx/deliver/fork)
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request