├── bot-scripts ├── slack.rb ├── hockey.rb └── testflight.rb ├── LICENSE └── Readme.markdown /bot-scripts/slack.rb: -------------------------------------------------------------------------------- 1 | require 'rest-client' 2 | 3 | def message 4 | ENV['CMD_SLACK_MESSAGE'] 5 | end 6 | 7 | def icon 8 | ENV['CMD_SLACK_ICON'] 9 | end 10 | 11 | def url 12 | ENV['CMD_SLACK_URL'] 13 | end 14 | 15 | def send_message 16 | parameters = { 17 | text: message, 18 | icon_emoji: icon 19 | }.to_json 20 | RestClient.post(url, parameters) 21 | end 22 | 23 | raise 'Unable to send Slack message.' unless send_message 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Caleb Davenport 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /bot-scripts/hockey.rb: -------------------------------------------------------------------------------- 1 | require 'fileutils' 2 | 3 | def ipa_path 4 | File.join(ENV['XCS_OUTPUT_DIR'], ENV['XCS_PRODUCT']) 5 | end 6 | 7 | def bot_name 8 | ENV['XCS_BOT_NAME'] 9 | end 10 | 11 | def product_name 12 | ENV['CMD_PRODUCT_NAME'] 13 | end 14 | 15 | def hockey_token 16 | ENV['CMD_HOCKEY_TOKEN'] 17 | end 18 | 19 | def dsym_path_before_zip 20 | File.join(ENV['XCS_ARCHIVE'], 'dSYMs', "#{product_name}.app.dSYM") 21 | end 22 | 23 | def dsym_path_after_zip 24 | File.join('/tmp', "#{bot_name}.dsym.zip") 25 | end 26 | 27 | def zip_dsym 28 | FileUtils.rm_f(dsym_path_after_zip) 29 | system("/usr/bin/zip -r \"#{dsym_path_after_zip}\" \"#{dsym_path_before_zip}\"") 30 | end 31 | 32 | def curl_command 33 | command = [ 34 | '/usr/bin/curl', 35 | '-F status=2', 36 | '-F notify=0', 37 | "-F ipa=@\"#{ipa_path}\"", 38 | "-F dsym=@\"#{dsym_path_after_zip}\"", 39 | "-H \"X-HockeyAppToken: #{hockey_token}\"", 40 | 'https://rink.hockeyapp.net/api/2/apps/upload' 41 | ] 42 | command.join(" ") 43 | end 44 | 45 | def upload 46 | system(curl_command) 47 | end 48 | 49 | raise 'Unable to create dsym.zip.' unless zip_dsym 50 | raise 'Upload failed.' unless upload 51 | -------------------------------------------------------------------------------- /bot-scripts/testflight.rb: -------------------------------------------------------------------------------- 1 | require 'fileutils' 2 | 3 | def ipa_path 4 | File.join(ENV['XCS_OUTPUT_DIR'], ENV['XCS_PRODUCT']) 5 | end 6 | 7 | def bot_name 8 | ENV['XCS_BOT_NAME'] 9 | end 10 | 11 | def product_name 12 | ENV['XCS_PRODUCT'] 13 | end 14 | 15 | def api_token 16 | ENV['CMD_API_TOKEN'] 17 | end 18 | 19 | def team_token 20 | ENV['CMD_TEAM_TOKEN'] 21 | end 22 | 23 | def distribution_lists 24 | ENV['CMD_DISTRIBUTION_LISTS'] 25 | end 26 | 27 | def dsym_path_before_zip 28 | File.join(ENV['XCS_ARCHIVE'], 'dSYMs', "#{product_name}.app.dSYM") 29 | end 30 | 31 | def dsym_path_after_zip 32 | File.join('/tmp', "#{bot_name}.dsym.zip") 33 | end 34 | 35 | def zip_dsym 36 | FileUtils.rm_f(dsym_path_after_zip) 37 | system("/usr/bin/zip -r \"#{dsym_path_after_zip}\" \"#{dsym_path_before_zip}\"") 38 | end 39 | 40 | def curl_command 41 | command = [ 42 | '/usr/bin/curl', 43 | '-F notes="Build uploaded automatically from Xcode."', 44 | '-F notify=False', 45 | "-F file=@\"#{ipa_path}\"", 46 | "-F dsym=@\"#{dsym_path_after_zip}\"", 47 | "-F api_token=\"#{api_token}\"", 48 | "-F team_token=\"#{team_token}\"", 49 | "-F distribution_lists=\"#{distribution_lists}\"", 50 | 'http://testflightapp.com/api/builds.json' 51 | ] 52 | command.join(" ") 53 | end 54 | 55 | def upload 56 | system(curl_command) 57 | end 58 | 59 | raise 'Unable to create dsym.zip.' unless zip_dsym 60 | raise 'Upload failed.' unless upload 61 | -------------------------------------------------------------------------------- /Readme.markdown: -------------------------------------------------------------------------------- 1 | # Xcode Scripts 2 | 3 | Helpful scripts for Xcode. 4 | 5 | # Bot Environment Variables 6 | 7 | Here are some useful Xcode bot environment variables: 8 | 9 | - `XCS_OUTPUT_DIR`: Where the Xcode bot stores the current integration. All output files can be found here. 10 | - `XCS_BOT_NAME`: The name of the bot. 11 | - `XCS_ARCHIVE`: This is the *full path* to the `.xcarchive` file. You do not need to construct this path relative to the output directory. 12 | - `XCS_PRODUCT`: For iOS apps, this is the path to the resulting `.ipa` file. You should construct a full path to this file relative to the output directory. 13 | 14 | # CocoaPods 15 | 16 | Running CocoaPods in Xcode bots is easy. My `pod install` script looks like this: 17 | 18 | ```sh 19 | export LC_ALL=en_US.UTF-8 20 | cd ios 21 | pod install 22 | ``` 23 | 24 | Note that the `cd` is environment specific. When you configure an Xcode bot, it tries to match your local environment as much as possible. In this case my code is located in `~/Documents/Code/north/tiiny/ios`. So when the bot clones the git repository, it will put it in a folder called `ios`. 25 | 26 | # Deployment Scripts 27 | 28 | I use the deployment scripts like this: 29 | 30 | ```sh 31 | export LC_ALL=en_US.UTF-8 32 | export CMD_HOCKEY_TOKEN=abcd1234 33 | export CMD_PRODUCT_NAME=App 34 | ruby -e "$(curl -fsSL https://raw.githubusercontent.com/calebd/xcode-scripts/master/bot-scripts/hockey.rb)" 35 | ``` 36 | 37 | # Contributions 38 | 39 | I welcome pull requests with any scripts you’d like to share with anyone! I’d like to make the process of setting up Xcode bots as easy as possible :) 40 | 41 | Send any feedback to [@calebd](https://twitter.com/calebd). 42 | --------------------------------------------------------------------------------