spaceship

deliversnapshotframeitPEMsighproducecertcodes

-------

spaceship ============ [![Twitter: @KauseFx](https://img.shields.io/badge/contact-@KrauseFx-blue.svg?style=flat)](https://twitter.com/KrauseFx) [![License](http://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://github.com/KrauseFx/spaceship/blob/master/LICENSE) [![Coverage Status](https://coveralls.io/repos/KrauseFx/spaceship/badge.svg?branch=master&t=ldL8gg)](https://coveralls.io/r/KrauseFx/spaceship?branch=master) [![Gem](https://img.shields.io/gem/v/spaceship.svg?style=flat)](http://rubygems.org/gems/spaceship) [![Codeship Status for KrauseFx/spaceship](https://img.shields.io/codeship/96bb1040-c2b6-0132-4c5b-22f8b41c2618/master.svg)](https://codeship.com/projects/73801) Get in contact with the developers on Twitter: [@snatchev](https://twitter.com/snatchev/) and [@KrauseFx](https://twitter.com/KrauseFx) -------

Why?UsageInstallationTechnical DetailsNeed help?

-------
spaceship is part of fastlane: connect all deployment tools into one streamlined workflow.
##### [Like this tool? Be the first to know about updates and new fastlane tools](https://tinyletter.com/krausefx) # What's Spaceship? > `spaceship` is named after the new Apple HQ in Cupertino. It allows you to seamlessly interact with the Apple Developer Portal using very simple Ruby code. `spaceship` uses simple HTTPs requests without any sort of web scraping. Using `spaceship`, the execution time of [sigh](https://github.com/KrauseFx/sigh) was reduced from over 1 minute to less than 5 seconds :rocket: `spaceship` uses a combination of 3 different API endpoints, used by the Apple Developer Portal and Xcode. As no API offers everything we need, `spaceship` combines all APIs for you. [More details about the APIs](#technical-details). Up until now, the [fastlane tools](https://fastlane.tools) used web scraping to interact with Apple's web services. By upgrading them to use `spaceship` all [fastlane tools](https://fastlane.tools) will be even faster and much more stable. > No matter how many apps or profiles you have, `spaceship` **can** handle your scale. Enough words, here is some code: ```ruby Spaceship.login # Create a new app app = Spaceship.app.create!(bundle_id: "com.krausefx.app", name: "Spaceship App") # Use an existing certificate cert = Spaceship.certificate.production.all.first # Create a new provisioning profile profile = Spaceship.provisioning_profile.app_store.create!(bundle_id: app.bundle_id, certificate: cert) # Print the name and download the new profile puts "Created Profile " + profile.name profile.download ``` ## Speed How fast are tools using `spaceship` compared to web scraping? ![assets/SpaceshipRecording.gif](assets/SpaceshipRecording.gif) # Installation sudo gem install spaceship # Usage To quickly play around with `spaceship` launch `irb` in your terminal and execute `require "spaceship"`. ## Login ```ruby Spaceship.login("felix@krausefx.com", "password") Spaceship.select_team # call this method to let the user select a team ``` ## Apps ```ruby # Fetch all available apps all_apps = Spaceship.app.all # Find a specific app based on the bundle identifier app = Spaceship.app.find("com.krausefx.app") # Show the names of all your apps Spaceship.app.all.each do |app| puts app.name end # Create a new app app = Spaceship.app.create!(bundle_id: "com.krausefx.app_name", name: "fastlane App") ``` ## Certificates ```ruby # Fetch all available certificates (includes signing and push profiles) certificates = Spaceship.certificate.all ``` ### Code Signing Certificates ```ruby # Production identities prod_certs = Spaceship.certificate.production.all # Development identities dev_certs = Spaceship.certificate.development.all # Download a certificate cert_content = prod_certs.first.download ``` ### Push Certificates ```ruby # Production push profiles prod_push_certs = Spaceship.certificate.production_push.all # Development push profiles dev_push_certs = Spaceship.certificate.development_push.all # Download a push profile cert_content = dev_push_certs.first.download ``` ### Create a Certificate ```ruby # Create a new certificate signing request csr, pkey = Spaceship.certificate.create_certificate_signing_request # Use the signing request to create a new distribution certificate Spaceship.certificate.production.create!(csr: csr) # Use the signing request to create a new push certificate Spaceship.certificate.production_push.create!(csr: csr, bundle_id: "com.krausefx.app") ``` ## Provisioning Profiles ### Receiving profiles ```ruby ##### Finding ##### # Get all available provisioning profiles profiles = Spaceship.provisioning_profile.all # Get all App Store profiles profiles_appstore = Spaceship.provisioning_profile.app_store.all # Get all AdHoc profiles profiles_adhoc = Spaceship.provisioning_profile.ad_hoc.all # Get all Development profiles profiles_dev = Spaceship.provisioning_profile.development.all # Fetch all profiles for a specific app identifier for the App Store filtered_profiles = Spaceship.provisioning_profile.app_store.find_by_bundle_id("com.krausefx.app") ##### Downloading ##### # Download a profile profile_content = profiles.first.download # Download a specific profile as file my_profile = Spaceship.provisioning_profile.app_store.find_by_bundle_id("com.krausefx.app") File.write("output.mobileprovision", my_profile.download) ``` ### Create a Provisioning Profile ```ruby # Choose the certificate to use cert = Spaceship.certificate.production.all.first # Create a new provisioning profile with a default name # The name of the new profile is "com.krausefx.app AppStore" profile = Spaceship.provisioning_profile.app_store.create!(bundle_id: "com.krausefx.app", certificate: cert) # AdHoc Profiles will add all devices by default profile = Spaceship.provisioning_profile.ad_hoc.create!(bundle_id: "com.krausefx.app", certificate: cert, name: "Profile Name") # Store the new profile on the filesystem File.write("NewProfile.mobileprovision", profile.download) ``` ### Repair a broken provisioning profile ```ruby # Select all 'Invalid' or 'Expired' provisioning profiles broken_profiles = Spaceship.provisioning_profile.all.find_all do |profile| (profile.status == "Invalid" or profile.status == "Expired") end # Iterate over all broken profiles and repair them broken_profiles.each do |profile| profile.repair! # yes, that's all you need to repair a profile end # or to make the same thing, just more Ruby like: Spaceship.provisioning_profile.all.find_all { |p| %w[Invalid Expired].include?p.status}.map(&:repair!) ``` ## Devices ```ruby all_devices = Spaceship.device.all # Register a new device Spaceship.device.create!(name: "Private iPhone 6", udid: "5814abb3...") ``` ## Enterprise ```ruby # Use the InHouse class to get all enterprise certificates cert = Spaceship.certificate.in_house.all.first # Create a new InHouse Enterprise distribution profile profile = Spaceship.provisioning_profile.app_store.create!(bundle_id: "com.krausefx.*", certificate: cert) ``` ## Multiple Spaceships Sometimes one `spaceship` just isn't enough. That's why this library has its own Spaceship Launcher to launch and use multiple `spaceships` at the same time :rocket: ```ruby # Launch 2 spaceships spaceship1 = Spaceship::Launcher.new("felix@krausefx.com", "password") spaceship2 = Spaceship::Launcher.new("stefan@spaceship.airforce", "password") # Fetch all registered devices from spaceship1 devices = spaceship1.device.all # Iterate over the list of available devices # and register each device from the first account also on the second one devices.each do |device| spaceship2.device.create!(name: device.name, udid: device.udid) end ``` ## More cool things you can do ```ruby # Find a profile with a specific name profile = Spaceship.provisioning_profile.development.all.find { |p| p.name == "Name" } # Add all available devices to the profile profile.devices = Spaceship.device.all # Push the changes back to the Apple Developer Portal profile.update! # Get the currently used team_id Spaceship.client.team_id # We generally don't want to be destructive, but you can also delete things # This method might fail for various reasons, e.g. app is already in the store app = Spaceship.app.find("com.krausefx.app") app.delete! ``` ## Spaceship in use The beta version of [sigh](https://github.com/KrauseFx/sigh) is already using `spaceship` to communicate with Apple's web services. You can see all relevant source code in [runner.rb](https://github.com/KrauseFx/sigh/blob/feature/spaceship/lib/sigh/spaceship/runner.rb). ## Full Documentation The detailed documentation of all available classes is available on [RubyDoc](http://www.rubydoc.info/github/fastlane/spaceship/frames). ## Example Data Some unnecessary information was removed, check out [provisioning_profile.rb](https://github.com/KrauseFx/spaceship/blob/master/lib/spaceship/provisioning_profile.rb) for all available attributes. The example data below is a provisioning profile, containing a device, certificate and app. ``` #, ...], @certificates=[ # ], @id="72SRVUNAAA", @uuid="43cda0d6-04a5-4964-89c0-a24b5f258aaa", @expires=#, @distribution_method="adhoc", @name="com.krausefx.app AppStore", @status="Active", @platform="ios", @app=# > > ``` # Technical Details ## HTTP Client Up until now all [fastlane tools](https://fastlane.tools) used web scraping to interact with Apple's web services. `spaceship` uses a simple HTTP client only, resulting in much less overhead and extremely improved speed. Advantages of `spaceship` (HTTP client) over web scraping: - Blazing fast :rocket: 90% faster than previous methods - No more overhead by loading images, HTML, JS and CSS files on each page load - Great test coverage by stubbing server responses - Resistant against design changes of the Apple Developer Portal - Automatic re-trying of requests in case a timeout occurs - By stubbing the `spaceship` objects it is possible to also implement tests for tools like [sigh](https://github.com/KrauseFx/sigh) ## API Endpoints I won't go into too much technical details about the various API endpoints, but just to give you an idea: - `https://idmsa.apple.com`: Used to authenticate to get a valid session - `https://developerservices2.apple.com`: - Get a detailed list of all available provisioning profiles - This API returns the devices, certificates and app for each of the profiles - Register new devices - `https://developer.apple.com`: - List all devices, certificates and apps - Create new certificates, provisioning profiles and apps - Delete certificates and apps - Repair provisioning profiles - Download provisioning profiles - Team selection `spaceship` uses all those API points to offer this seamless experience. ## Magic involved `spaceship` does a lot of magic to get everything working so neatly: - **Sensible Defaults**: You only have to provide the mandatory information (e.g. new provisioning profiles contain all devices by default) - **Local Validation**: When pushing changes back to the Apple Dev Portal `spaceship` will make sure only valid data is sent to Apple (e.g. automatic repairing of provisioning profiles) - **Various request/response types**: When working with the different API endpoints, `spaceship` has to deal with `JSON`, `XML`, `txt`, `plist` and sometimes even `HTML` responses and requests. - **Automatic Pagination**: Even if you have thousands of apps, profiles or certificates, `spaceship` **can** handle your scale. It was heavily tested by first using `spaceship` to create hundreds of profiles and then accessing them using `spaceship`. - **Session, Cookie and CSRF token**: All the security aspects are handled by `spaceship`. - **Profile Magic**: Create and upload code signing requests, all managed by `spaceship` - **Multiple Spaceship**: You can launch multiple `spaceships` with different Apple accounts to do things like syncing the registered devices. # Credits This project has been sponsored by [ZeroPush](https://zeropush.com). `spaceship` was developed by [@snatchev](https://twitter.com/snatchev/) and [@KrauseFx](https://twitter.com/KrauseFx). # License This project is licensed under the terms of the MIT license. See the LICENSE file. # Contributing 1. Create an issue to start a discussion about your idea 2. Fork it (https://github.com/KrauseFx/fastlane/fork) 3. Create your feature branch (`git checkout -b my-new-feature`) 4. Commit your changes (`git commit -am 'Add some feature'`) 5. Push to the branch (`git push origin my-new-feature`) 6. Create a new Pull Request