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
@@ -0,0 +1,36 @@
|
|
1
|
+
module IOSBox
|
2
|
+
module Tools
|
3
|
+
class Config < Thor
|
4
|
+
desc "show", "Displays current configuration information"
|
5
|
+
def show
|
6
|
+
shell.print_table IOSBox.new.config.to_a
|
7
|
+
end
|
8
|
+
|
9
|
+
desc "set key value", "Sets certain key to value value"
|
10
|
+
def set(key, value)
|
11
|
+
if ["true", "yes"].include?(value.downcase)
|
12
|
+
value = true
|
13
|
+
elsif ["false", "no"].include?(value.downcase)
|
14
|
+
value = false
|
15
|
+
end
|
16
|
+
|
17
|
+
config = IOSBox.new.config
|
18
|
+
# Split config
|
19
|
+
category, key = key.split(/\./)
|
20
|
+
if key.nil?
|
21
|
+
config.send("#{category}=", value)
|
22
|
+
else
|
23
|
+
if !config.send(category).kind_of?(Hash)
|
24
|
+
config.send("#{category}=", {})
|
25
|
+
end
|
26
|
+
config.send(category).send(:[]=, key, value)
|
27
|
+
end
|
28
|
+
|
29
|
+
# config.testflight = {}
|
30
|
+
# config.testflight['apikey'] = 'XXXX'
|
31
|
+
# # config.send("#{key}=", value)
|
32
|
+
config.save
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,179 @@
|
|
1
|
+
require 'ios-box/deploy'
|
2
|
+
require 'pbxproject'
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
module IOSBox
|
6
|
+
module Tools
|
7
|
+
class Deploy < Thor
|
8
|
+
include Thor::Actions
|
9
|
+
|
10
|
+
desc "add PROVIDER", "Configures deployment targets"
|
11
|
+
def add(provider)
|
12
|
+
iosbox = IOSBox.new
|
13
|
+
pbx = PBXProject::PBXProject.new :file => File.join(iosbox.project_dir, iosbox.config.project, "project.pbxproj")
|
14
|
+
pbx.parse
|
15
|
+
|
16
|
+
# Find all configuration lists and check if we have already Ad Hoc configuration
|
17
|
+
cfglists = pbx.find_item :type => PBXProject::PBXTypes::XCConfigurationList
|
18
|
+
cfglists.each do |cfg|
|
19
|
+
if cfg.buildConfigurations.select {|bc| bc.comment == "Ad Hoc"}.empty?
|
20
|
+
puts "Copy Release => Ad Hoc"
|
21
|
+
release = cfg.buildConfigurations.select {|bc| bc.comment == "Release"}.first.value
|
22
|
+
bc = pbx.find_item :guid => release, :type => PBXProject::PBXTypes::XCBuildConfiguration
|
23
|
+
adhoc = PBXProject::PBXTypes::XCBuildConfiguration.new
|
24
|
+
adhoc.comment = "Ad Hoc"
|
25
|
+
adhoc.name = PBXProject::PBXTypes::BasicValue.new(:value => '"Ad Hoc"')
|
26
|
+
adhoc.buildSettings = bc.buildSettings
|
27
|
+
pbx.add_item adhoc
|
28
|
+
|
29
|
+
cfg.buildConfigurations << PBXProject::PBXTypes::BasicValue.new(:value => adhoc.guid, :comment => "Ad Hoc")
|
30
|
+
cfg.defaultConfigurationName = "Release"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
pbx.write_to :file => File.join(iosbox.project_dir, iosbox.config.project, "project.pbxproj")
|
35
|
+
|
36
|
+
# Copy scheme
|
37
|
+
xcuserdata = File.join(iosbox.project_dir, iosbox.config.project, "xcuserdata", "#{ENV['USER']}.xcuserdatad")
|
38
|
+
scheme = File.open(Dir[File.join(xcuserdata, "xcschemes", "*.xcscheme")].first)
|
39
|
+
deploy = File.join(xcuserdata, "xcschemes", "Deploy.xcscheme")
|
40
|
+
doc = Nokogiri::XML(scheme)
|
41
|
+
|
42
|
+
# Get identifier
|
43
|
+
blueprint_id = doc.xpath("//BuildableReference").first.attr("BlueprintIdentifier")
|
44
|
+
|
45
|
+
# Change configuration of Archive
|
46
|
+
action = doc.xpath("//ArchiveAction").first
|
47
|
+
action.attribute("buildConfiguration").value = "Ad Hoc"
|
48
|
+
# Add Post Action
|
49
|
+
Nokogiri::XML::Builder.with(action) do |xml|
|
50
|
+
xml.PostActions {
|
51
|
+
xml.ExecutionAction(:ActionType => "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction") {
|
52
|
+
xml.ActionContent(:title => "Run Script", :scriptText=> "(cd $PROJECT_DIR; ios-box deploy #{provider})") {
|
53
|
+
xml.EnvironmentBuildable {
|
54
|
+
xml.BuildableReference(
|
55
|
+
:BuildableIdentifier => "primary",
|
56
|
+
:BlueprintIdentifier => "C0B33A571451827A000B80A2",
|
57
|
+
:BuildableName => "ios.app",
|
58
|
+
:BlueprintName => "ios",
|
59
|
+
:ReferencedContainer => "container:ios.xcodeproj")
|
60
|
+
}
|
61
|
+
}
|
62
|
+
}
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
File.open(deploy, 'w') {|io| io.puts doc.to_xml }
|
67
|
+
|
68
|
+
# Configure provider
|
69
|
+
send(provider, "config")
|
70
|
+
end
|
71
|
+
|
72
|
+
desc "testflight", "Deploys latest built archive to TestFlight"
|
73
|
+
method_option :notes, :type => :string, :desc => "Supply build notes. If a file, notes are read from given file."
|
74
|
+
method_option :distribution, :type => :array, :desc => "Distribution list to deploy"
|
75
|
+
method_option :notify, :type => :boolean, :default => true, :desc => "Notify testers of new build"
|
76
|
+
method_option :replace, :type => :boolean, :default => true, :desc => "Replace existing build"
|
77
|
+
def testflight(config = nil)
|
78
|
+
iosbox = IOSBox.new
|
79
|
+
|
80
|
+
if config == "config"
|
81
|
+
# Config mode
|
82
|
+
iosbox.config.testflight ||= {}
|
83
|
+
iosbox.config.testflight['apitoken'] = shell.ask("Testflight API token:")
|
84
|
+
iosbox.config.testflight['teamtoken'] = shell.ask("Testflight Team token:")
|
85
|
+
iosbox.config.save
|
86
|
+
|
87
|
+
exit
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
tf = ::IOSBox::Deploy::Testflight.new iosbox
|
92
|
+
|
93
|
+
# Do we have archive path in buildcache
|
94
|
+
if ENV['XCODE_VERSION_ACTUAL'] and ENV['CONFIGURATION'] == "Ad Hoc"
|
95
|
+
# Always use fresh data if ran from XCode
|
96
|
+
prod_path = ENV['ARCHIVE_PATH']
|
97
|
+
# Update cache
|
98
|
+
puts iosbox.cache.inspect
|
99
|
+
iosbox.cache[:"ad hoc"][:archive_path] = ENV['ARCHIVE_PATH']
|
100
|
+
iosbox.cache.save
|
101
|
+
elsif iosbox.cache[:"ad hoc"][:archive_path]
|
102
|
+
# Otherwise use build cache if exists
|
103
|
+
prod_path = iosbox.cache[:"ad hoc"][:archive_path]
|
104
|
+
else
|
105
|
+
# Otherwise, require Xcode
|
106
|
+
require_xcode
|
107
|
+
end
|
108
|
+
|
109
|
+
# Check that we have required keys
|
110
|
+
if iosbox.config.testflight['apitoken'].nil?
|
111
|
+
shell.error "Please set TestFlight API token (ios-box config set testflight_apitoken XXXXXX)"
|
112
|
+
end
|
113
|
+
if iosbox.config.testflight['teamtoken'].nil?
|
114
|
+
shell.error "Please set TestFlight Team token (ios-box config set testflight_teamtoken XXXXXX)"
|
115
|
+
end
|
116
|
+
if iosbox.config.testflight['apitoken'].nil? or iosbox.config.testflight['teamtoken'].nil?
|
117
|
+
tf.notify :name => "Deployment Failed",
|
118
|
+
:title => "Testflight Deployment",
|
119
|
+
:error => "Testflight has not been configured. Please run ios-box deploy testflight config"
|
120
|
+
end
|
121
|
+
|
122
|
+
puts "Deploying to TestFlight... Please wait..."
|
123
|
+
ipa = tf.create_ipa prod_path
|
124
|
+
dsym = tf.create_dsym prod_path
|
125
|
+
|
126
|
+
# Creating build notes
|
127
|
+
if options['notes'].nil?
|
128
|
+
if iosbox.config.deploy['autonotes']
|
129
|
+
# Get last deployment
|
130
|
+
last_deployed = iosbox.config.testflight['lastdeploy'] || iosbox.git.log.last.id
|
131
|
+
# Get git changelog
|
132
|
+
notes = ""
|
133
|
+
iosbox.git.commits_between(last_deployed, 'HEAD').reverse_each do |commit|
|
134
|
+
notes << commit.authored_date.to_s + "\n"
|
135
|
+
notes << commit.authored_date.to_s.length.times.inject("") { |i,c| i + "=" } + "\n"
|
136
|
+
notes << commit.message + "\n"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
else
|
140
|
+
if File.exists?(options['notes'])
|
141
|
+
notes = File.read(options['notes'])
|
142
|
+
else
|
143
|
+
notes = options['notes']
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
if notes.empty?
|
148
|
+
# Try to find TextMate
|
149
|
+
mate = %x{which mate}.strip
|
150
|
+
if File.exists?(mate)
|
151
|
+
f = Tempfile.new('notes')
|
152
|
+
f.write "Replace this with build notes."
|
153
|
+
f.close
|
154
|
+
system(mate, "--wait", f.path)
|
155
|
+
notes = File.read(f)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
tf.deploy :file => ipa,
|
160
|
+
:apitoken => iosbox.config.testflight['apitoken'],
|
161
|
+
:teamtoken => iosbox.config.testflight['teamtoken'],
|
162
|
+
:notes => notes,
|
163
|
+
:dsym => dsym,
|
164
|
+
:distribution => options['distribution'],
|
165
|
+
:notify => options['notify'],
|
166
|
+
:replace => options['replace'],
|
167
|
+
:growl => iosbox.config.growl
|
168
|
+
end
|
169
|
+
|
170
|
+
private
|
171
|
+
def require_xcode
|
172
|
+
unless ENV['XCODE_VERSION_ACTUAL']
|
173
|
+
shell.error "This task must be run in XCode Environment"
|
174
|
+
exit
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
@@ -1,32 +1,31 @@
|
|
1
|
-
module
|
2
|
-
module
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
1
|
+
module IOSBox
|
2
|
+
module Tools
|
3
|
+
class Version < Thor
|
4
|
+
desc "show", "Displays current version information"
|
5
|
+
def show
|
6
|
+
version = IOSBox.new.version
|
7
|
+
|
8
|
+
|
9
|
+
puts " Short Version: #{version[:short]}"
|
10
|
+
puts " Bundle Version: #{version[:bundle]}"
|
11
|
+
puts " Technical: %1.4f" % version[:technical]
|
12
|
+
puts " Build Number: #{version[:build]}"
|
13
|
+
puts " Commit: #{version[:commit]}"
|
14
|
+
end
|
15
|
+
|
16
|
+
desc "build [BUILDNUM]", "Increments current build number or sets it to defined."
|
17
|
+
def build(buildnum = nil)
|
18
|
+
IOSBox.new.version.bump_build(buildnum)
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "set VERSION", "Sets new marketing version"
|
22
|
+
def set(ver)
|
23
|
+
IOSBox.new.version.set_marketing(ver)
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "bump [major|minor]", "Bumps marketings version by one"
|
27
|
+
def bump(type = :patch)
|
28
|
+
IOSBox.new.version.bump_marketing(type.to_s.downcase.to_sym)
|
30
29
|
end
|
31
30
|
end
|
32
31
|
end
|
data/lib/ios_box.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ios-box
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-10-
|
12
|
+
date: 2011-10-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: thor
|
16
|
-
requirement: &
|
16
|
+
requirement: &70165439353500 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70165439353500
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: grit
|
27
|
-
requirement: &
|
27
|
+
requirement: &70165439352880 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70165439352880
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: plist
|
38
|
-
requirement: &
|
38
|
+
requirement: &70165439352280 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,7 +43,40 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70165439352280
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rubyzip
|
49
|
+
requirement: &70165439351660 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70165439351660
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: rest-client
|
60
|
+
requirement: &70165439350880 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :runtime
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70165439350880
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: nokogiri
|
71
|
+
requirement: &70165439350360 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *70165439350360
|
47
80
|
description: Include atuomatic vesion conrol for you XCode projects.
|
48
81
|
email:
|
49
82
|
- mikko@owlforestry.com
|
@@ -66,12 +99,15 @@ files:
|
|
66
99
|
- lib/ios-box.rb
|
67
100
|
- lib/ios-box/cli.rb
|
68
101
|
- lib/ios-box/config.rb
|
102
|
+
- lib/ios-box/deploy.rb
|
103
|
+
- lib/ios-box/deploy/testflight.rb
|
69
104
|
- lib/ios-box/iosbox.rb
|
70
105
|
- lib/ios-box/tasks.rb
|
71
106
|
- lib/ios-box/tools.rb
|
72
107
|
- lib/ios-box/tools/build.rb
|
108
|
+
- lib/ios-box/tools/config.rb
|
109
|
+
- lib/ios-box/tools/deploy.rb
|
73
110
|
- lib/ios-box/tools/version.rb
|
74
|
-
- lib/ios-box/version.rb
|
75
111
|
- lib/ios_box.rb
|
76
112
|
- spec/build_cache_spec.rb
|
77
113
|
- spec/ios-box_spec.rb
|