longbow-fdv 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 417412bce1a52378508d826af49063e766f809c5
4
+ data.tar.gz: 379a1450dcfff594bc7c004f79b93afacfcf468b
5
+ SHA512:
6
+ metadata.gz: 666b28e2b7c6b7bbf2f8a5f33e31758457e88cac998fba156573768f3347499669bcb301b4b715688e77e501177d9c8dbfa220c935ce2f5a0eada040d9c11f9c
7
+ data.tar.gz: 5cf73e6cd4de1b1fc11dabf24b41cfccba3e57279c670c1d12dd6433d0d90def13ed1e38919a315f675b54c9e191dcd72f70e334e43b2b9667aed25f3b2ec2cf
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in longbow.gemspec
4
+ gemspec
5
+
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Intermark Group
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,151 @@
1
+ ![banner](resources/banner.png)
2
+
3
+ **Problem**
4
+
5
+ One codebase. Multiple App Store submission targets with different icons, launch images, info.plist keys, screenshots, etc.
6
+
7
+ **Solution**
8
+
9
+ ```
10
+ $ longbow install
11
+ $ longbow shoot
12
+ $ longbow aim
13
+ ```
14
+
15
+ **About**
16
+
17
+ Longbow is a command-line run ruby gem that duplicates the main target in your `.xcworkspace` or `.xcodeproj` file, then reads from a JSON file to fill out the rest of your new target. It looks for certain keys and does things like taking an icon image and resizing it for the various icons you'll need, and adding keys to the info.plist file for that target. The goal was to be practically autonomous in creating new targets and apps.
18
+
19
+ Additionally, it can create screenshots for each target app store submission. You write a simple UIAutomation script (it's just JavaScript) and Longbow takes care of taking the screenshots for each combination of target, device, and language.
20
+
21
+ **Requirements**
22
+
23
+ Longbow requires Xcode 5+, and your app must use the new .xcassets paradigm for icons, launch screens, etc.
24
+
25
+ ## Table of Contents
26
+
27
+ * [Installation](#installation)
28
+ * [Set Up](#set-up)
29
+ * [Formatting longbow.json](#formatting-longbow-json)
30
+ * [Create a Target](#create-a-target)
31
+ * [Global Options](#global-options)
32
+ * [The Future](#the-future)
33
+ * [Contributing](#contributing)
34
+
35
+ ## Installation
36
+
37
+ Longbow is officially hosted on [RubyGems](http://rubygems.org/gems/longbow), so installation is a breeze:
38
+
39
+ $ gem install longbow
40
+
41
+ ## Set Up
42
+
43
+ Run `longbow install` in the directory where your `.xcworkspace` or `.xcodeproj` file lives. This will create a file, `longbow.json`, where they will be used to build out from here. You are almost ready to start creating new targets
44
+
45
+ ## Formatting longbow.json
46
+
47
+ Here's a basic gist of how to format your `longbow.json` file:
48
+
49
+ ```json
50
+ {
51
+ "targets":[
52
+ {
53
+ "name":"TargetName",
54
+ "icon_url":"https://somewhere.net/img.png",
55
+ "launch_phone_p_url":"https://somewhere.net/img2.png",
56
+ "info_plist": {
57
+ "CFBundleIdentifier":"com.company.target1",
58
+ "ProprietaryKey":"Value"
59
+ }
60
+ },
61
+ {
62
+ "name":"TargetName2",
63
+ "icon_path":"/relative/path/to/file.png",
64
+ "launch_phone_p_path":"/relative/path/to/file2.png",
65
+ "info_plist": {
66
+ "CFBundleIdentifier":"com.company.target2",
67
+ "ProprietaryKey":"Value2"
68
+ }
69
+ }
70
+ ],
71
+ "global_info_keys":{
72
+ "somekey":"somevalue"
73
+ },
74
+ "devices":["iPhone","iPad"]
75
+ }
76
+ ```
77
+
78
+ In the top-level of the JSON file, we have 3 key/value pairs:
79
+
80
+ * `targets`
81
+ * `devices`
82
+ * `global_info_keys`
83
+
84
+ The `targets` section contains nested key/value pairs for each specific target. Devices holds an array of "iPhone" and/or "iPad". "global_info_keys" contains key/value pairs that you'd like to add to the info.plist file for all targets in this JSON file. Each target can contain the following keys:
85
+
86
+ * `icon_url` or `icon_path`
87
+ * `launch_phone_p_url` or `launch_phone_p_path`
88
+ * `launch_phone_l_url` or `launch_phone_l_path`
89
+ * `launch_tablet_p_url` or `launch_tablet_p_path`
90
+ * `launch_tablet_l_url` or `launch_tablet_l_path`
91
+ * `info_plist`
92
+ * `name`
93
+
94
+ The `icon_url` and `icon_path` key corresponds to the location of the icon image. It will be downloaded from the web if necessary, then resized depending on your device setting and added to the Images.xcassets file for that target. The same goes for the launch image keys. The p and l parts correspond to portrait and landscape orientation. The `info_plist` key corresponds to another set of key/value pairs that will be added or updated in the info.plist file specifically for this target.
95
+
96
+ **Note:** `info_plist` takes precedence over `global_info_keys` for two of the same keys in both places.
97
+
98
+ ## Creating/Updating a Target
99
+
100
+ Now that you're set up - it's time to add a target. Make sure that you have updated your `longbow.json` file with the correct information for your target, and then run the following command inside the project directory.
101
+
102
+ `longbow shoot -n NameOfTarget`
103
+
104
+ What this does is goes to your `longbow.json` file and looks for the correct target dictionary, and tries to create a new Target in your app. It then handles the various icons/info_plist additions specifically for this target. If your target already exists, it will just update the icon images and plist settings.
105
+
106
+ If you leave off the `-n` option, it will run for all targets in the `longbow.json` file.
107
+
108
+ **Other Options**
109
+
110
+ * `-d, --directory` - if not in the current directory, specify a new path
111
+ * `-u, --url` - the url of a longbow formatted JSON file
112
+ * `-i, --images` - set this flag to not recreate images in the longbow file
113
+
114
+ `longbow shoot -n NameOfTarget -d ~/Path/To/App -u http://someurl.com/longbow.json`
115
+
116
+ ## Global Options
117
+
118
+ `--dontlog` will not log the status/operations to the console.
119
+
120
+ `--help` will fill you in on what you need to do for an action.
121
+
122
+ ## Taking Screenshots
123
+
124
+ So you've created all your targets and finished the first version of the app - now you need the screen shots to submit it to the App Store.
125
+
126
+ First you'll need to write a single UIAutomation script to take the screenshots. You can see [Apple's Documentation](https://developer.apple.com/library/ios/documentation/DeveloperTools/Reference/UIAutomationRef/_index.html) for more information on writing the script. The part we're primarily concerned with is the captureLocalizedScreenshot() method provided by Longbow. This method will take the screenshot with a consistent naming scheme and place it in a folder for each target.
127
+
128
+ `captureLocalizedScreenshot("homeScreen");` will create ~/Desktop/screenshots/TargetName/en-US/iOS-4-in\_\_\_portrait\_\_\_homeScreen.png
129
+
130
+ Once you've created your automation script, you can run it by calling `longbow aim`. This command will generate a variation of your UIAutomation script for each target, then handle running it for each target. Grab a drink, depending on your script and your number of targets, this may take a while.
131
+
132
+ **Options**
133
+
134
+ Similar to the `shoot` command, there are flags you can use with this feature.
135
+
136
+ * `-n` - name of the target to capture
137
+ * `-d` - directory the project lives in
138
+ * `-u` - url of the longbow.json file
139
+
140
+ ## The Future
141
+
142
+ * Unit Tests
143
+ * App Store deployment of Targets
144
+
145
+ ## Contributing
146
+
147
+ 1. Fork it
148
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
149
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
150
+ 4. Push to the branch (`git push origin my-new-feature`)
151
+ 5. Create new Pull Request
@@ -0,0 +1,9 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ gemspec = eval(File.read("longbow-fdv.gemspec"))
4
+
5
+ task :build => "#{gemspec.full_name}.gem"
6
+
7
+ file "#{gemspec.full_name}.gem" => gemspec.files + ["longbow-fdv.gemspec"] do
8
+ system "gem build longbow-fdv.gemspec"
9
+ end
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'dotenv'
4
+ Dotenv.load
5
+
6
+ require 'commander/import'
7
+
8
+ $:.push File.expand_path("../../lib", __FILE__)
9
+ require 'longbow'
10
+
11
+ HighLine.track_eof = false # Fix for built-in Ruby
12
+
13
+ program :version, Longbow::VERSION
14
+ program :description, 'One codebase. Multiple App Store submission targets with different icons, launch images, info.plist keys, etc.'
15
+
16
+ program :help, 'Author', 'Benjamin Gordon (@bennyguitar) for Intermark Group <interactive@intermarkgroup.com>'
17
+ program :help, 'Website', 'https://github.com/intermark'
18
+ program :help_formatter, :compact
19
+
20
+ global_option('--dontlog') { $nolog = true }
21
+
22
+ default_command :help
23
+
24
+ require 'longbow/commands'
@@ -0,0 +1,6 @@
1
+ # Library files
2
+ require 'longbow/colors'
3
+ require 'longbow/version'
4
+ require 'longbow/commands'
5
+ require 'longbow/images'
6
+ require 'longbow/targets'
@@ -0,0 +1,23 @@
1
+ module Longbow
2
+ # Main Colorize Functions
3
+ def self.colorize(text, color_code)
4
+ puts "\e[#{color_code}m#{text}\e[0m"
5
+ end
6
+
7
+ # Specific Colors
8
+ def self.red(text)
9
+ colorize(text, 31)
10
+ end
11
+
12
+ def self.green(text)
13
+ colorize(text, 32)
14
+ end
15
+
16
+ def self.blue(text)
17
+ colorize(text, 36)
18
+ end
19
+
20
+ def self.purple(text)
21
+ colorize(text, 35)
22
+ end
23
+ end
@@ -0,0 +1,5 @@
1
+ $:.push File.expand_path('../', __FILE__)
2
+
3
+ require 'commands/shoot'
4
+ require 'commands/install'
5
+ require 'commands/aim'
@@ -0,0 +1,71 @@
1
+ require 'fileutils'
2
+ require 'longbow/colors'
3
+ require 'longbow/targets'
4
+ require 'longbow/images'
5
+ require 'longbow/json'
6
+ require 'json'
7
+
8
+ command :aim do |c|
9
+ c.syntax = 'longbow aim'
10
+ c.syntax = 'Takes screenshots for each target in your workspace or project based on a UIAutomation script.'
11
+ c.description = ''
12
+ c.option '-s', '--script SCRIPT', 'Script used to get the app into the proper state for each screenshot'
13
+ c.option '-d', '--directory DIRECTORY', 'Path where the .xcodeproj or .xcworkspace file && the longbow.json file live.'
14
+ c.option '-u', '--url URL', 'URL of a longbow formatted JSON file.'
15
+ c.option '-n', '--name NAME', 'Name of the target to get a screenshot for.'
16
+ c.option '-v', '--verbose', 'Output all logs from UIAutomation/xcodebuild'
17
+
18
+ c.action do |args, options|
19
+ # Check for newer version
20
+ Longbow::check_for_newer_version unless $nolog
21
+
22
+ # Set Up
23
+ @script = options.script ? options.script : nil
24
+ @directory = options.directory ? options.directory : Dir.pwd
25
+ @url = options.url ? options.url : nil
26
+ @target_name = options.name
27
+ @targets = []
28
+
29
+ # Create JSON object
30
+ if @url
31
+ obj = Longbow::json_object_from_url @url
32
+ else
33
+ obj = Longbow::json_object_from_directory @directory
34
+ end
35
+
36
+ # Break if Bad
37
+ unless obj || Longbow::lint_json_object(obj)
38
+ Longbow::red "\n Invalid JSON. Please lint the file, and try again.\n"
39
+ next
40
+ end
41
+
42
+ # Check for Target Name
43
+ if @target_name
44
+ obj['targets'].each do |t|
45
+ @targets << t if t['name'] == @target_name
46
+ end
47
+
48
+ if @targets.length == 0
49
+ Longbow::red "\n Couldn't find a target named #{@target_name} in the longbow.json file.\n"
50
+ next
51
+ end
52
+ else
53
+ @targets = obj['targets']
54
+ end
55
+
56
+ resources_path = File.dirname(__FILE__) + '/../../../resources'
57
+
58
+ FileUtils.cp "#{resources_path}/capture.js", "capture.js"
59
+ FileUtils.cp "#{resources_path}/config-screenshots.sh", "config-screenshots.sh"
60
+ FileUtils.cp "#{resources_path}/ui-screen-shooter.sh", "ui-screen-shooter.sh"
61
+ FileUtils.cp "#{resources_path}/unix_instruments.sh", "unix_instruments.sh"
62
+ @target_names = []
63
+ @targets.each do |t|
64
+ @target_names << t['name']
65
+ end
66
+ target_string = @target_names.join(',')
67
+ Longbow::blue " Beginning screenshots..."
68
+ exec "#{resources_path}/aim.sh #{target_string} verbose" if options.verbose
69
+ exec "#{resources_path}/aim.sh #{target_string}" if !options.verbose
70
+ end
71
+ end
@@ -0,0 +1,54 @@
1
+ $:.push File.expand_path('../../', __FILE__)
2
+ require 'fileutils'
3
+ require 'longbow'
4
+
5
+ command :install do |c|
6
+ c.syntax = 'longbow install [options]'
7
+ c.summary = 'Creates the required files in your directory.'
8
+ c.description = ''
9
+ c.option '-d', '--directory DIRECTORY', 'Path where the .xcproj or .xcworkspace file && the longbow.json file live.'
10
+
11
+ c.action do |args, options|
12
+ # Check for newer version
13
+ Longbow::check_for_newer_version unless $nolog
14
+
15
+ # Set Up
16
+ @directory = options.directory ? options.directory : Dir.pwd
17
+ @json_path = @directory + '/longbow.json'
18
+
19
+ # Install
20
+ if File.exist?(@json_path)
21
+ Longbow::red ' longbow.json already exists at ' + @json_path
22
+ else
23
+ File.open(@json_path, 'w') do |f|
24
+ f.write('{
25
+ "targets":[
26
+ {
27
+ "name":"TargetName",
28
+ "icon_url":"https://somewhere.net/img.png",
29
+ "launch_phone_p_url":"https://somewhere.net/img2.png",
30
+ "info_plist": {
31
+ "CFBundleIdentifier":"com.company.target1",
32
+ "ProprietaryKey":"Value"
33
+ }
34
+ },
35
+ {
36
+ "name":"TargetName2",
37
+ "icon_path":"/relative/path/to/file.png",
38
+ "launch_phone_p_path":"/relative/path/to/file2.png",
39
+ "info_plist": {
40
+ "CFBundleIdentifier":"com.company.target2",
41
+ "ProprietaryKey":"Value2"
42
+ }
43
+ }
44
+ ],
45
+ "global_info_keys":{
46
+ "somekey":"somevalue"
47
+ },
48
+ "devices":["iPhone","iPad"]
49
+ }')
50
+ end
51
+ Longbow::green ' longbow.json created' unless $nolog
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,70 @@
1
+ $:.push File.expand_path('../../', __FILE__)
2
+ require 'fileutils'
3
+ require 'longbow/colors'
4
+ require 'longbow/targets'
5
+ require 'longbow/images'
6
+ require 'longbow/json'
7
+ require 'json'
8
+
9
+ command :shoot do |c|
10
+ c.syntax = 'longbow shoot [options]'
11
+ c.summary = 'Creates/updates a target or all targets in your workspace or project.'
12
+ c.description = ''
13
+ c.option '-n', '--name NAME', 'Target name from the corresponding longbow.json file.'
14
+ c.option '-d', '--directory DIRECTORY', 'Path where the .xcodeproj or .xcworkspace file && the longbow.json file live.'
15
+ c.option '-u', '--url URL', 'URL of a longbow formatted JSON file.'
16
+ c.option '-i', '--images', 'Set this flag to not recreate images in the longbow file.'
17
+
18
+ c.action do |args, options|
19
+ # Check for newer version
20
+ Longbow::check_for_newer_version unless $nolog
21
+
22
+ # Set Up
23
+ @target_name = options.name ? options.name : nil
24
+ @directory = options.directory ? options.directory : Dir.pwd
25
+
26
+ puts 'Directory'
27
+ puts @directory
28
+
29
+ @noimages = options.images ? true : false
30
+ @url = options.url ? options.url : nil
31
+ @targets = []
32
+
33
+ # Create JSON object
34
+ if @url
35
+ obj = Longbow::json_object_from_url @url
36
+ else
37
+ obj = Longbow::json_object_from_directory @directory
38
+ end
39
+
40
+ # Break if Bad
41
+ unless obj || Longbow::lint_json_object(obj)
42
+ Longbow::red "\n Invalid JSON. Please lint the file, and try again.\n"
43
+ next
44
+ end
45
+
46
+
47
+ # Check for Target Name
48
+ if @target_name
49
+ obj['targets'].each do |t|
50
+ @targets << t if t['name'] == @target_name
51
+ end
52
+
53
+ if @targets.length == 0
54
+ Longbow::red "\n Couldn't find a target named #{@target_name} in the longbow.json file.\n"
55
+ next
56
+ end
57
+ else
58
+ @targets = obj['targets']
59
+ end
60
+
61
+ # Begin
62
+ @targets.each do |t|
63
+ icon = t['icon_url'] || t['icon_path']
64
+ launch = t['launch_phone_p_url'] || t['launch_phone_p_path'] || t['launch_phone_l_url'] || t['launch_phone_l_path'] || t['launch_tablet_p_url'] || t['launch_tablet_p_path'] || t['launch_tablet_l_url'] || t['launch_tablet_l_path']
65
+ Longbow::update_target @directory, t['name'], obj['global_info_keys'], t['info_plist'], icon, launch
66
+ # Longbow::create_images(@directory, t, obj) unless @noimages
67
+ Longbow::green " Finished: #{t['name']}\n" unless $nolog
68
+ end
69
+ end
70
+ end