ios-box 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +33 -27
- data/bin/ios-box +1 -1
- data/ios-box.gemspec +5 -2
- data/lib/ios-box.rb +2 -6
- data/lib/ios-box/cli.rb +89 -86
- data/lib/ios-box/config.rb +30 -16
- data/lib/ios-box/deploy.rb +96 -0
- data/lib/ios-box/deploy/testflight.rb +35 -0
- data/lib/ios-box/iosbox.rb +122 -122
- data/lib/ios-box/tools.rb +6 -6
- data/lib/ios-box/tools/build.rb +41 -42
- data/lib/ios-box/tools/config.rb +36 -0
- data/lib/ios-box/tools/deploy.rb +179 -0
- data/lib/ios-box/tools/version.rb +28 -29
- data/lib/ios_box.rb +1 -1
- metadata +45 -9
- data/lib/ios-box/version.rb +0 -5
data/README.md
CHANGED
@@ -1,23 +1,20 @@
|
|
1
1
|
IosBox
|
2
2
|
======
|
3
3
|
|
4
|
-
IosBox is
|
5
|
-
It includes rake tasks that take care of updating app Info.plist with proper
|
6
|
-
version information (e.g. build date, GIT hash, etc).
|
7
|
-
Further version will integrate deployment options, such as deploy beta versions
|
8
|
-
to TestFlight.
|
4
|
+
IosBox is tool that integrates with XCode to automate some of the tasks.
|
9
5
|
|
10
6
|
Current Features
|
11
7
|
----------------
|
12
8
|
|
13
9
|
Currently IosBox supports following features:
|
14
10
|
|
15
|
-
* <b>Build Prepare</b> (`
|
16
|
-
Build prepare task generates new build
|
11
|
+
* <b>Build Prepare</b> (`build prepare`)
|
12
|
+
Build prepare task generates new build and bundle version and stores
|
17
13
|
it to application Info.plist.
|
18
|
-
It also
|
14
|
+
It also prepares buildcache for further tasks.
|
19
15
|
|
20
|
-
* <b>Version
|
16
|
+
* <b>Version Management</b> (`version`)
|
17
|
+
IosBox offers simple
|
21
18
|
IosBox offers simple tasks to bump version numbers. Either it is patch, minor or
|
22
19
|
major version bump, IosBox automatically handles increasing current version number.
|
23
20
|
|
@@ -29,39 +26,48 @@ In the roadmap are following features (but not yet planned)
|
|
29
26
|
* Asset management, slicing assets according to receipt etc.
|
30
27
|
* More to come, open for suggestions...
|
31
28
|
|
32
|
-
Installation
|
33
|
-
------------
|
29
|
+
# Installation
|
34
30
|
|
35
31
|
Install `IosBox` gem if you haven't done yet so
|
36
32
|
|
37
33
|
$ gem install ios-box
|
38
34
|
|
39
|
-
Create in the root of your project folder `Rakefile` -file with following contents:
|
40
|
-
|
41
|
-
require 'ios-box'
|
42
|
-
|
43
|
-
IosBox::Tasks.new do |config|
|
44
|
-
config.target = "iosboxdev"
|
45
|
-
end
|
46
|
-
|
47
35
|
Integrate toolbox with your XCode project by executing following command:
|
48
36
|
|
49
|
-
$
|
37
|
+
$ ios-box integrate
|
50
38
|
|
51
39
|
Notice! This command will modify your XCode project file and therefore can make your project to stop working.
|
52
40
|
Make sure you have proper backups done.
|
53
41
|
|
54
|
-
|
42
|
+
# Usage
|
43
|
+
|
44
|
+
Run `ios-box help` in project folder to see available commands.
|
45
|
+
|
46
|
+
# Commands
|
47
|
+
|
48
|
+
## ios-box integrate
|
49
|
+
|
50
|
+
Integrates ios-box to current project. During integration process you can
|
51
|
+
choose which targets build preparation task is ran.
|
52
|
+
|
53
|
+
## ios-box build prepare
|
54
|
+
|
55
|
+
This task prepares build process and can be only ran during XCode build phase.
|
56
|
+
|
57
|
+
## ios-box version show
|
58
|
+
|
59
|
+
Displays current version information of the project.
|
60
|
+
|
61
|
+
## ios-box version build
|
55
62
|
|
56
|
-
|
63
|
+
Increments build number.
|
57
64
|
|
58
|
-
|
59
|
-
-----
|
65
|
+
## ios-box version bump [major|minor]
|
60
66
|
|
61
|
-
|
67
|
+
Bumps marketing version by one step. By default it increases patch level
|
68
|
+
but if ptional argument is given, either major or minor version is increased.
|
62
69
|
|
63
|
-
Copyright
|
64
|
-
---------
|
70
|
+
# Copyright
|
65
71
|
|
66
72
|
Copyright © 2011 Mikko Kokkonen. See LICENSE.txt for
|
67
73
|
further details.
|
data/bin/ios-box
CHANGED
data/ios-box.gemspec
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
require File.expand_path('../lib/ios-box
|
2
|
+
require File.expand_path('../lib/ios-box', __FILE__)
|
3
3
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
5
|
gem.authors = ["Mikko Kokkonen"]
|
@@ -13,9 +13,12 @@ Gem::Specification.new do |gem|
|
|
13
13
|
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
14
14
|
gem.name = "ios-box"
|
15
15
|
gem.require_paths = ["lib"]
|
16
|
-
gem.version =
|
16
|
+
gem.version = IOSBox::VERSION
|
17
17
|
|
18
18
|
gem.add_runtime_dependency "thor"
|
19
19
|
gem.add_runtime_dependency "grit"
|
20
20
|
gem.add_runtime_dependency "plist"
|
21
|
+
gem.add_runtime_dependency "rubyzip"
|
22
|
+
gem.add_runtime_dependency "rest-client"
|
23
|
+
gem.add_runtime_dependency "nokogiri"
|
21
24
|
end
|
data/lib/ios-box.rb
CHANGED
data/lib/ios-box/cli.rb
CHANGED
@@ -1,96 +1,99 @@
|
|
1
|
+
require 'ios-box/config'
|
1
2
|
require 'ios-box/tools'
|
2
3
|
require 'ios-box/iosbox'
|
3
4
|
require 'thor'
|
4
5
|
require 'pbxproject'
|
5
6
|
|
6
|
-
module
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
# Create iosbox configuration file
|
81
|
-
create_file ".iosbox" do
|
82
|
-
"# ios-box configuration file\n" +
|
83
|
-
"# https://github.com/owl-forestry/ios-box\n" +
|
84
|
-
"#\n" +
|
85
|
-
"config.project = \"#{project}\"\n" +
|
86
|
-
"#{_targets}\n"
|
7
|
+
module IOSBox
|
8
|
+
class CLI < Thor
|
9
|
+
include Thor::Actions
|
10
|
+
|
11
|
+
desc "version COMMAND", "Version related subcommands"
|
12
|
+
subcommand "version", Tools::Version
|
13
|
+
|
14
|
+
desc "build COMMAND", "Build related subcommands"
|
15
|
+
subcommand "build", Tools::Build
|
16
|
+
|
17
|
+
desc "config COMMAND", "Configuration related subcommands"
|
18
|
+
subcommand "config", Tools::Config
|
19
|
+
|
20
|
+
desc "deploy COMMAND", "Deploymend subcommands"
|
21
|
+
subcommand "deploy", Tools::Deploy
|
22
|
+
|
23
|
+
desc "integrate [PROJECT]", "Integrates ios-box with project, by default first founded"
|
24
|
+
def integrate(project = nil)
|
25
|
+
shell = Thor::Shell::Basic.new
|
26
|
+
|
27
|
+
# Find our project
|
28
|
+
if project.nil?
|
29
|
+
project = Dir["*.xcodeproj"].first
|
30
|
+
end
|
31
|
+
|
32
|
+
unless File.exists?(project) and File.directory?(project)
|
33
|
+
shell.error "Project #{project} is not valid."
|
34
|
+
exit
|
35
|
+
end
|
36
|
+
|
37
|
+
shell.say "Integrating to project #{project}"
|
38
|
+
|
39
|
+
# Find our project file, either from command-line or just using first one
|
40
|
+
xcode = project || Dir["*.xcodeproj"].first
|
41
|
+
raise "Cannot find project.pbxproj in #{xcode}" unless File.file? "#{xcode}/project.pbxproj"
|
42
|
+
|
43
|
+
# Load our project file
|
44
|
+
pbx = PBXProject::PBXProject.new :file => "#{xcode}/project.pbxproj"
|
45
|
+
pbx.parse
|
46
|
+
|
47
|
+
# If target missing, fetch first target
|
48
|
+
# Find all targets
|
49
|
+
targets = pbx.find_item :type => PBXProject::PBXTypes::PBXNativeTarget
|
50
|
+
if targets.nil? or targets.empty?
|
51
|
+
raise "XCode project does not have any targets!"
|
52
|
+
end
|
53
|
+
|
54
|
+
# Generate build phase
|
55
|
+
# Try to find build phases
|
56
|
+
# prebuilds = pbx.find_item(:type => PBXProject::PBXTypes::PBXShellScriptBuildPhase) || []
|
57
|
+
# prebuilds.select! do |c|
|
58
|
+
# !c.comment.match(/ios-box prepare/).nil?
|
59
|
+
# end
|
60
|
+
#
|
61
|
+
prebuilds = [] # Always add new build phase
|
62
|
+
if prebuilds.empty?
|
63
|
+
initPhase = PBXProject::PBXTypes::PBXShellScriptBuildPhase.new(
|
64
|
+
:shellPath => '/bin/sh',
|
65
|
+
:shellScript => "\"(cd $PROJECT_DIR; ios-box build prepare)\"",
|
66
|
+
:showEnvVarsInLog => 0,
|
67
|
+
:name => '"ios-box prepare"'
|
68
|
+
)
|
69
|
+
initPhase.comment = "ios-box prepare"
|
70
|
+
|
71
|
+
pbx.add_item initPhase
|
72
|
+
else
|
73
|
+
initPhase = prebuilds.first
|
74
|
+
end
|
75
|
+
|
76
|
+
targets.each do |target|
|
77
|
+
if shell.yes?("Integrate with target #{target.name.value}? [yn]")
|
78
|
+
# Inject buildphase to target
|
79
|
+
# Add to target
|
80
|
+
target.add_build_phase initPhase, 0
|
87
81
|
end
|
88
|
-
# Append buildcache to gitignore
|
89
|
-
send((File.exists?(".gitignore") ? :append_to_file : :create_file), ".gitignore", ".buildcache\n")
|
90
|
-
|
91
|
-
# Write project file
|
92
|
-
pbx.write_to :file => "#{xcode}/project.pbxproj"
|
93
82
|
end
|
83
|
+
|
84
|
+
# Create iosbox configuration file
|
85
|
+
config = Config.new
|
86
|
+
config.project = project
|
87
|
+
config.targets = targets.collect{|c| c.name.value}
|
88
|
+
config.growl = true # Enable Growl support
|
89
|
+
config.deploy = {'autonotes' => true} # Generate deployment changelogs from GIT logs
|
90
|
+
config.save(".iosbox")
|
91
|
+
|
92
|
+
# Append buildcache to gitignore
|
93
|
+
send((File.exists?(".gitignore") ? :append_to_file : :create_file), ".gitignore", ".buildcache\n")
|
94
|
+
|
95
|
+
# Write project file
|
96
|
+
pbx.write_to :file => "#{xcode}/project.pbxproj"
|
94
97
|
end
|
95
98
|
end
|
96
99
|
end
|
data/lib/ios-box/config.rb
CHANGED
@@ -1,23 +1,37 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
class Config
|
4
|
-
attr_accessor :project
|
5
|
-
attr_reader :targets
|
1
|
+
require 'yaml'
|
2
|
+
require 'ostruct'
|
6
3
|
|
7
|
-
|
4
|
+
module IOSBox
|
5
|
+
class Config < OpenStruct
|
6
|
+
attr_accessor :file
|
7
|
+
|
8
|
+
def self.load(file)
|
9
|
+
if File.exists?(file)
|
10
|
+
config = self.new(YAML.load(File.read(file)))
|
11
|
+
else
|
8
12
|
config = self.new
|
9
|
-
config.instance_eval(File.read(file), file)
|
10
|
-
config
|
11
|
-
end
|
12
|
-
|
13
|
-
def initialize
|
14
|
-
@targets = []
|
15
|
-
@project = nil
|
16
13
|
end
|
17
|
-
|
18
|
-
|
19
|
-
|
14
|
+
|
15
|
+
config.file = file
|
16
|
+
config
|
17
|
+
end
|
18
|
+
|
19
|
+
def save(file = nil)
|
20
|
+
puts "Saving config to #{file || @file}"
|
21
|
+
File.open(file || @file, 'w') {|io| io.puts @table.to_yaml }
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_a
|
25
|
+
res = []
|
26
|
+
@table.collect do |k,v|
|
27
|
+
if v.kind_of?(Hash)
|
28
|
+
res << ["#{k.to_s}:", ""]
|
29
|
+
v.each {|k,v| res << [" #{k.to_s}", v]}
|
30
|
+
else
|
31
|
+
res << [k.to_s, v]
|
32
|
+
end
|
20
33
|
end
|
34
|
+
res
|
21
35
|
end
|
22
36
|
end
|
23
37
|
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'plist'
|
2
|
+
require 'zip/zip'
|
3
|
+
|
4
|
+
module IOSBox
|
5
|
+
module Deploy
|
6
|
+
autoload :Testflight, 'ios-box/deploy/testflight'
|
7
|
+
|
8
|
+
class Deployer
|
9
|
+
attr_reader :iosbox
|
10
|
+
|
11
|
+
def initialize(iosbox)
|
12
|
+
@iosbox = iosbox
|
13
|
+
|
14
|
+
if iosbox.config.growl
|
15
|
+
begin
|
16
|
+
require 'ruby_gntp'
|
17
|
+
|
18
|
+
@growl = GNTP.new("ios-box")
|
19
|
+
@growl.register({:notifications => [
|
20
|
+
{:name => "Deployment Succeeded", :enabled => true},
|
21
|
+
{:name => "Deployment Failed", :enabled => true},
|
22
|
+
]})
|
23
|
+
rescue LoadError
|
24
|
+
iosbox.config.growl = false
|
25
|
+
puts "Please install ruby_gntp gem if you want to enable Growl notifications."
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def notify(opts)
|
31
|
+
return unless iosbox.config.growl
|
32
|
+
|
33
|
+
@growl.notify(
|
34
|
+
:name => opts[:name],
|
35
|
+
:title => opts[:title],
|
36
|
+
:text => opts[:text] || opts[:error]
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
def create_ipa(path)
|
41
|
+
puts "Creating IPA from path #{path}..."
|
42
|
+
|
43
|
+
# Check for missing plist
|
44
|
+
raise "Archive info.plist is missing" unless File.exists?(File.join(path, "Info.plist"))
|
45
|
+
pl = Plist::parse_xml(File.join(path, "Info.plist"))
|
46
|
+
raise "Invalid XCArchive version" unless pl['ArchiveVersion'] == 1
|
47
|
+
|
48
|
+
app_path = pl['ApplicationProperties']['ApplicationPath']
|
49
|
+
app_name = File.basename(app_path, File.extname(app_path))
|
50
|
+
ipa_name = File.join(path, "Products", "#{app_name}.ipa")
|
51
|
+
puts "Compressing #{app_path}"
|
52
|
+
if File.exists?(ipa_name)
|
53
|
+
File.unlink(ipa_name)
|
54
|
+
end
|
55
|
+
|
56
|
+
Zip::ZipFile.open(ipa_name, Zip::ZipFile::CREATE) do |zip|
|
57
|
+
Dir["#{File.join(path, "Products", app_path)}/**/*"].each do |entry|
|
58
|
+
e_name = entry.gsub(/#{File.join(path, "Products", app_path)}\//, '')
|
59
|
+
e_name = "Payload/#{app_name}.app/#{e_name}"
|
60
|
+
zip.add e_name, entry
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
ipa_name
|
65
|
+
end
|
66
|
+
|
67
|
+
def create_dsym(path)
|
68
|
+
puts "Creating Zipped dSYM from path #{path}..."
|
69
|
+
|
70
|
+
# Check for missing plist
|
71
|
+
raise "Archive info.plist is missing" unless File.exists?(File.join(path, "Info.plist"))
|
72
|
+
pl = Plist::parse_xml(File.join(path, "Info.plist"))
|
73
|
+
raise "Invalid XCArchive version" unless pl['ArchiveVersion'] == 1
|
74
|
+
|
75
|
+
app_path = pl['ApplicationProperties']['ApplicationPath']
|
76
|
+
app_name = File.basename(app_path)
|
77
|
+
dsym_name = File.join(path, "dSYMs", "#{app_name}.dSYM.zip")
|
78
|
+
|
79
|
+
if File.exists?(dsym_name)
|
80
|
+
File.unlink(dsym_name)
|
81
|
+
end
|
82
|
+
|
83
|
+
Zip::ZipFile.open(dsym_name, Zip::ZipFile::CREATE) do |zip|
|
84
|
+
dsym_path = File.join(path, "dSYMs")
|
85
|
+
puts "Path #{dsym_path}"
|
86
|
+
Dir["#{File.join(dsym_path, "#{app_name}.dSYM")}/**/*"].each do |entry|
|
87
|
+
e_name = entry.gsub(/#{dsym_path}\//, '')
|
88
|
+
zip.add e_name, entry
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
dsym_name
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|