ot-ios-builder 0.7.9.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.md +82 -0
- data/LICENSE +19 -0
- data/README.md +248 -0
- data/lib/beta_builder.rb +435 -0
- data/lib/beta_builder/archived_build.rb +101 -0
- data/lib/beta_builder/build_output_parser.rb +56 -0
- data/lib/beta_builder/deployment_strategies.rb +39 -0
- data/lib/beta_builder/deployment_strategies/testflight.rb +92 -0
- data/lib/beta_builder/deployment_strategies/web.rb +104 -0
- data/lib/beta_builder/release_strategies.rb +34 -0
- data/lib/beta_builder/release_strategies/git.rb +116 -0
- data/lib/ot-ios-builder.rb +1 -0
- metadata +146 -0
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'uuid'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'cfpropertylist'
|
4
|
+
|
5
|
+
module BetaBuilder
|
6
|
+
def self.archive(configuration)
|
7
|
+
if configuration.xcode4_archive_mode
|
8
|
+
Xcode4ArchivedBuild.new(configuration)
|
9
|
+
else
|
10
|
+
ArchivedBuild.new(configuration)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class ArchivedBuild
|
15
|
+
def initialize(configuration)
|
16
|
+
@configuration = configuration
|
17
|
+
@uuid = UUID.generate.upcase
|
18
|
+
end
|
19
|
+
|
20
|
+
def save_to(path)
|
21
|
+
archive_path = File.join(path, "#{@uuid}.apparchive")
|
22
|
+
FileUtils.mkdir(archive_path)
|
23
|
+
FileUtils.cp_r(@configuration.built_app_path, archive_path)
|
24
|
+
FileUtils.cp_r(@configuration.built_app_dsym_path, archive_path)
|
25
|
+
archive_path
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Xcode4ArchivedBuild
|
30
|
+
def initialize(configuration)
|
31
|
+
@configuration = configuration
|
32
|
+
end
|
33
|
+
|
34
|
+
def archive_file_name
|
35
|
+
"#{@configuration.archive_name} #{Time.now.strftime('%Y-%m-%d %H.%M')}.xcarchive"
|
36
|
+
end
|
37
|
+
|
38
|
+
def archive_path_within(path)
|
39
|
+
File.join(path, "#{Time.now.strftime('%Y-%m-%d')}", archive_file_name)
|
40
|
+
end
|
41
|
+
|
42
|
+
def applications_path
|
43
|
+
File.join("Products", "Applications")
|
44
|
+
end
|
45
|
+
|
46
|
+
def dsyms_path
|
47
|
+
"dSYMs"
|
48
|
+
end
|
49
|
+
|
50
|
+
def plist_info_path
|
51
|
+
File.join(@configuration.built_app_path, "Info.plist")
|
52
|
+
end
|
53
|
+
|
54
|
+
def save_to(path)
|
55
|
+
archive_path = archive_path_within(path)
|
56
|
+
FileUtils.mkdir_p(archive_path)
|
57
|
+
|
58
|
+
application_path = File.join(archive_path, applications_path)
|
59
|
+
FileUtils.mkdir_p(application_path)
|
60
|
+
FileUtils.cp_r(@configuration.built_app_path, application_path)
|
61
|
+
|
62
|
+
dsym_path = File.join(archive_path, dsyms_path)
|
63
|
+
FileUtils.mkdir_p(dsym_path)
|
64
|
+
FileUtils.cp_r(@configuration.built_app_dsym_path, dsym_path)
|
65
|
+
|
66
|
+
write_plist_to(archive_path)
|
67
|
+
archive_path
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def write_plist_to(path)
|
73
|
+
version = metadata["CFBundleShortVersionString"] || metadata["CFBundleVersion"]
|
74
|
+
plist = {
|
75
|
+
"ApplicationProperties" => {
|
76
|
+
"ApplicationPath" => File.join("Applications", @configuration.app_file_name),
|
77
|
+
"CFBundleIdentifier" => metadata["CFBundleIdentifier"],
|
78
|
+
"CFBundleShortVersionString" => version,
|
79
|
+
"IconPaths" => metadata["CFBundleIcons"]["CFBundlePrimaryIcon"]["CFBundleIconFiles"].map { |file| File.join("Applications", @configuration.app_file_name, file) }
|
80
|
+
},
|
81
|
+
"ArchiveVersion" => 1.0,
|
82
|
+
"Comment" => @configuration.release_notes_text,
|
83
|
+
"CreationDate" => Time.now,
|
84
|
+
"Name" => @configuration.archive_name,
|
85
|
+
"SchemeName" => @configuration.scheme
|
86
|
+
}
|
87
|
+
File.open(File.join(path, "Info.plist"), "w") do |io|
|
88
|
+
io.write plist.to_plist(:convert_unknown_to_string => true)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def metadata
|
93
|
+
@metadata ||= load_property_list(plist_info_path)
|
94
|
+
end
|
95
|
+
|
96
|
+
def load_property_list(path)
|
97
|
+
plist = CFPropertyList::List.new(:file => path)
|
98
|
+
CFPropertyList.native_types(plist.value)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module BetaBuilder
|
2
|
+
class BuildOutputParser
|
3
|
+
|
4
|
+
def initialize(output)
|
5
|
+
@output = output
|
6
|
+
end
|
7
|
+
|
8
|
+
def build_output_dir
|
9
|
+
# yes, this is truly horrible, but unless somebody else can find a better way...
|
10
|
+
found = @output.split("\n").grep(/^Validate(.*)\/Xcode\/DerivedData\/(.*)-(.*)/).first
|
11
|
+
if found && found =~ /Validate [\"]?([^\"|$]*)/
|
12
|
+
reference = $1
|
13
|
+
else
|
14
|
+
raise "Cannot parse build_dir from build output."
|
15
|
+
end
|
16
|
+
derived_data_directory = reference.split("/Build/Products/").first
|
17
|
+
"#{derived_data_directory}/Build/Products/"
|
18
|
+
end
|
19
|
+
|
20
|
+
def failed?
|
21
|
+
@output.split("\n").any? {|line| line.include? "** BUILD FAILED **"}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# quick testing
|
27
|
+
if __FILE__ == $0
|
28
|
+
|
29
|
+
require 'test/unit'
|
30
|
+
class BuildOutputTest < Test::Unit::TestCase
|
31
|
+
|
32
|
+
def test_parses_output_with_unquoted_build_path
|
33
|
+
bop = BetaBuilder::BuildOutputParser.new(<<eos)
|
34
|
+
Validate /Users/johnsmith/Library/Developer/Xcode/DerivedData/Application-hegpgdbpjylesafhkxnsymrzjavl/Build/Products/Distribution-iphoneos/Application.app
|
35
|
+
cd /Users/user/app/ios
|
36
|
+
setenv PATH \"/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Developer/usr/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11/bin\"
|
37
|
+
setenv PRODUCT_TYPE com.apple.product-type.application
|
38
|
+
/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/Validation /Users/user/Library/Developer/Xcode/DerivedData/Application-hegpgdbpjylesafhkxnsymrzjavl/Build/Products/Distribution-iphoneos/Application.app
|
39
|
+
eos
|
40
|
+
assert_equal "/Users/johnsmith/Library/Developer/Xcode/DerivedData/Application-hegpgdbpjylesafhkxnsymrzjavl/Build/Products/", bop.build_output_dir
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_parses_output_with_quoted_build_path
|
44
|
+
bop = BetaBuilder::BuildOutputParser.new(<<eos)
|
45
|
+
Validate \"/Users/john smith/Library/Developer/Xcode/DerivedData/Application-hegpgdbpjylesafhkxnsymrzjavl/Build/Products/Distribution-iphoneos/Application.app\"
|
46
|
+
cd /Users/user/app/ios
|
47
|
+
setenv PATH \"/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Developer/usr/bin:/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11/bin\"
|
48
|
+
setenv PRODUCT_TYPE com.apple.product-type.application
|
49
|
+
/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/Validation /Users/user/Library/Developer/Xcode/DerivedData/Application-hegpgdbpjylesafhkxnsymrzjavl/Build/Products/Distribution-iphoneos/Application.app
|
50
|
+
eos
|
51
|
+
assert_equal "/Users/john smith/Library/Developer/Xcode/DerivedData/Application-hegpgdbpjylesafhkxnsymrzjavl/Build/Products/", bop.build_output_dir
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module BetaBuilder
|
2
|
+
module DeploymentStrategies
|
3
|
+
def self.valid_strategy?(strategy_name)
|
4
|
+
strategies.keys.include?(strategy_name.to_sym)
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.build(strategy_name, configuration)
|
8
|
+
strategies[strategy_name.to_sym].new(configuration)
|
9
|
+
end
|
10
|
+
|
11
|
+
class Strategy
|
12
|
+
def initialize(configuration)
|
13
|
+
@configuration = configuration
|
14
|
+
|
15
|
+
if respond_to?(:extended_configuration_for_strategy)
|
16
|
+
@configuration.instance_eval(&extended_configuration_for_strategy)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def configure(&block)
|
21
|
+
yield @configuration
|
22
|
+
end
|
23
|
+
|
24
|
+
def prepare
|
25
|
+
puts "Nothing to prepare!" if @configuration.verbose
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def self.strategies
|
32
|
+
{:web => Web, :testflight => TestFlight}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
require File.dirname(__FILE__) + '/deployment_strategies/web'
|
38
|
+
require File.dirname(__FILE__) + '/deployment_strategies/testflight'
|
39
|
+
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'rest_client'
|
2
|
+
require 'json'
|
3
|
+
require 'tmpdir'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
module BetaBuilder
|
7
|
+
module DeploymentStrategies
|
8
|
+
class TestFlight < Strategy
|
9
|
+
include Rake::DSL
|
10
|
+
include FileUtils
|
11
|
+
ENDPOINT = "https://testflightapp.com/api/builds.json"
|
12
|
+
|
13
|
+
def extended_configuration_for_strategy
|
14
|
+
proc do
|
15
|
+
def generate_release_notes(&block)
|
16
|
+
self.release_notes = block if block
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def deploy
|
22
|
+
release_notes = get_notes
|
23
|
+
payload = {
|
24
|
+
:api_token => @configuration.api_token,
|
25
|
+
:team_token => @configuration.team_token,
|
26
|
+
:file => File.new(@configuration.ipa_path, 'rb'),
|
27
|
+
:notes => release_notes,
|
28
|
+
:distribution_lists => (@configuration.distribution_lists || []).join(","),
|
29
|
+
:notify => @configuration.notify || false,
|
30
|
+
:replace => @configuration.replace || false
|
31
|
+
}
|
32
|
+
if @configuration.verbose
|
33
|
+
puts "ipa path: #{@configuration.ipa_path}"
|
34
|
+
puts "release notes: #{release_notes}"
|
35
|
+
end
|
36
|
+
|
37
|
+
if @configuration.dry_run
|
38
|
+
puts '** Dry Run - No action here! **'
|
39
|
+
return
|
40
|
+
end
|
41
|
+
|
42
|
+
print "Uploading build to TestFlight..."
|
43
|
+
|
44
|
+
begin
|
45
|
+
response = RestClient.post(ENDPOINT, payload, :accept => :json)
|
46
|
+
rescue => e
|
47
|
+
response = e.response
|
48
|
+
end
|
49
|
+
|
50
|
+
if (response.code == 201) || (response.code == 200)
|
51
|
+
puts "Done."
|
52
|
+
else
|
53
|
+
puts "Failed."
|
54
|
+
puts "#{response}"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def get_notes
|
61
|
+
notes = @configuration.release_notes_text
|
62
|
+
notes || get_notes_using_editor || get_notes_using_prompt
|
63
|
+
end
|
64
|
+
|
65
|
+
def get_notes_using_editor
|
66
|
+
return unless (editor = ENV["EDITOR"])
|
67
|
+
|
68
|
+
dir = Dir.mktmpdir
|
69
|
+
begin
|
70
|
+
filepath = "#{dir}/release_notes"
|
71
|
+
system("#{editor} #{filepath}")
|
72
|
+
@configuration.release_notes = File.read(filepath)
|
73
|
+
ensure
|
74
|
+
rm_rf(dir)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def get_notes_using_prompt
|
79
|
+
puts "Enter the release notes for this build (hit enter twice when done):\n"
|
80
|
+
@configuration.release_notes = gets_until_match(/\n{2}$/).strip
|
81
|
+
end
|
82
|
+
|
83
|
+
def gets_until_match(pattern, string = "")
|
84
|
+
if (string += STDIN.gets) =~ pattern
|
85
|
+
string
|
86
|
+
else
|
87
|
+
gets_until_match(pattern, string)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module BetaBuilder
|
2
|
+
module DeploymentStrategies
|
3
|
+
class Web < Strategy
|
4
|
+
def extended_configuration_for_strategy
|
5
|
+
proc do
|
6
|
+
def deployment_url
|
7
|
+
File.join(deploy_to, ipa_name)
|
8
|
+
end
|
9
|
+
|
10
|
+
def manifest_url
|
11
|
+
File.join(deploy_to, "manifest.plist")
|
12
|
+
end
|
13
|
+
|
14
|
+
def remote_installation_path
|
15
|
+
File.join(remote_directory)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def prepare
|
21
|
+
plist = CFPropertyList::List.new(:file => "#{@configuration.built_app_path}/Info.plist")
|
22
|
+
plist_data = CFPropertyList.native_types(plist.value)
|
23
|
+
File.open("pkg/dist/manifest.plist", "w") do |io|
|
24
|
+
io << %{<?xml version="1.0" encoding="UTF-8"?>
|
25
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
26
|
+
<plist version="1.0">
|
27
|
+
<dict>
|
28
|
+
<key>items</key>
|
29
|
+
<array>
|
30
|
+
<dict>
|
31
|
+
<key>assets</key>
|
32
|
+
<array>
|
33
|
+
<dict>
|
34
|
+
<key>kind</key>
|
35
|
+
<string>software-package</string>
|
36
|
+
<key>url</key>
|
37
|
+
<string>#{@configuration.deployment_url}</string>
|
38
|
+
</dict>
|
39
|
+
</array>
|
40
|
+
<key>metadata</key>
|
41
|
+
<dict>
|
42
|
+
<key>bundle-identifier</key>
|
43
|
+
<string>#{plist_data['CFBundleIdentifier']}</string>
|
44
|
+
<key>bundle-version</key>
|
45
|
+
<string>#{plist_data['CFBundleVersion']}</string>
|
46
|
+
<key>kind</key>
|
47
|
+
<string>software</string>
|
48
|
+
<key>title</key>
|
49
|
+
<string>#{plist_data['CFBundleDisplayName']}</string>
|
50
|
+
</dict>
|
51
|
+
</dict>
|
52
|
+
</array>
|
53
|
+
</dict>
|
54
|
+
</plist>
|
55
|
+
}
|
56
|
+
end
|
57
|
+
File.open("pkg/dist/index.html", "w") do |io|
|
58
|
+
io << %{<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
59
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
60
|
+
<head>
|
61
|
+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
62
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"/>
|
63
|
+
<title>Beta Download</title>
|
64
|
+
<style type="text/css">
|
65
|
+
body {background:#fff;margin:0;padding:0;font-family:arial,helvetica,sans-serif;text-align:center;padding:10px;color:#333;font-size:16px;}
|
66
|
+
#container {width:300px;margin:0 auto;}
|
67
|
+
h1 {margin:0;padding:0;font-size:14px;}
|
68
|
+
p {font-size:13px;}
|
69
|
+
.link {background:#ecf5ff;border-top:1px solid #fff;border:1px solid #dfebf8;margin-top:.5em;padding:.3em;}
|
70
|
+
.link a {text-decoration:none;font-size:15px;display:block;color:#069;}
|
71
|
+
</style>
|
72
|
+
</head>
|
73
|
+
<body>
|
74
|
+
<div id="container">
|
75
|
+
<div class="link"><a href="itms-services://?action=download-manifest&url=#{@configuration.manifest_url}">Tap Here to Install<br />#{@configuration.target} #{plist_data['CFBundleVersion']}<br />On Your Device</a></div>
|
76
|
+
<p><strong>Link didn't work?</strong><br />
|
77
|
+
Make sure you're visiting this page on your device, not your computer.</p>
|
78
|
+
</div>
|
79
|
+
</body>
|
80
|
+
</html>
|
81
|
+
}
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def deploy
|
86
|
+
cmd = []
|
87
|
+
|
88
|
+
cmd.push "scp"
|
89
|
+
|
90
|
+
if @configuration.remote_port
|
91
|
+
cmd.push "-P #{@configuration.remote_port}"
|
92
|
+
end
|
93
|
+
|
94
|
+
cmd.push "pkg/dist/*"
|
95
|
+
cmd.push "#{@configuration.remote_host}:#{@configuration.remote_installation_path}"
|
96
|
+
|
97
|
+
cmd = cmd.join(" ")
|
98
|
+
|
99
|
+
puts "* Running `#{cmd}`"
|
100
|
+
system(cmd)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module BetaBuilder
|
2
|
+
module ReleaseStrategies
|
3
|
+
def self.valid_strategy?(strategy_name)
|
4
|
+
strategies.keys.include?(strategy_name.to_sym)
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.build(strategy_name, configuration)
|
8
|
+
strategies[strategy_name.to_sym].new(configuration)
|
9
|
+
end
|
10
|
+
|
11
|
+
class ReleaseStrategy
|
12
|
+
def initialize(configuration)
|
13
|
+
@configuration = configuration
|
14
|
+
end
|
15
|
+
|
16
|
+
def configure(&block)
|
17
|
+
yield self
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def prepare
|
22
|
+
puts "Nothing to prepare!" if @configuration.verbose
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def self.strategies
|
28
|
+
{:git => Git}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
require File.dirname(__FILE__) + '/release_strategies/git'
|
34
|
+
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module BetaBuilder
|
2
|
+
module ReleaseStrategies
|
3
|
+
class Git < ReleaseStrategy
|
4
|
+
attr_accessor :branch, :origin, :tag_name
|
5
|
+
|
6
|
+
def prepare
|
7
|
+
|
8
|
+
if @origin == nil then
|
9
|
+
@origin = "origin"
|
10
|
+
end
|
11
|
+
|
12
|
+
if @branch == nil then
|
13
|
+
@branch = "master"
|
14
|
+
end
|
15
|
+
|
16
|
+
if @tag_name == nil then
|
17
|
+
@tag_name = "v#{@configuration.build_number}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def tag_current_version
|
22
|
+
puts "Relasing with Git"
|
23
|
+
print "Tagging version #{@tag_name}"
|
24
|
+
cmd = []
|
25
|
+
|
26
|
+
#first, tag
|
27
|
+
cmd << "git"
|
28
|
+
cmd << "tag"
|
29
|
+
# -f sounds brutal to start with, so let's give it a try without
|
30
|
+
# cmd << "-f"
|
31
|
+
cmd << @tag_name
|
32
|
+
|
33
|
+
cmd << "2>&1 %s git.output" % (@configuration.verbose ? '| tee' : '>')
|
34
|
+
system(cmd.join " ")
|
35
|
+
puts
|
36
|
+
puts "Done"
|
37
|
+
|
38
|
+
# then push tags to the remote server
|
39
|
+
print "Pushing tag to #{@origin} on branch #{@branch}"
|
40
|
+
cmd = []
|
41
|
+
|
42
|
+
cmd << "git"
|
43
|
+
cmd << "push"
|
44
|
+
cmd << "--tags"
|
45
|
+
cmd << @origin
|
46
|
+
cmd << @branch
|
47
|
+
cmd << "2>&1 %s git.output" % (@configuration.verbose ? '| tee' : '>')
|
48
|
+
system(cmd.join " ")
|
49
|
+
|
50
|
+
puts
|
51
|
+
puts "Done"
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
def prepare_for_next_pod_release
|
56
|
+
build_number = @configuration.build_number
|
57
|
+
raise "build number cannot be empty on release" unless (build_number != nil) && (!build_number.empty?)
|
58
|
+
|
59
|
+
print "Committing #{@configuration.app_info_plist} and #{@configuration.spec_file} with version #{build_number}"
|
60
|
+
|
61
|
+
stage_files [@configuration.app_info_plist, @configuration.spec_file]
|
62
|
+
commit_and_push_with_message "Preparing for next pod release..."
|
63
|
+
|
64
|
+
puts "Done"
|
65
|
+
end
|
66
|
+
|
67
|
+
def prepare_for_next_release
|
68
|
+
build_number = @configuration.build_number
|
69
|
+
raise "build number cannot be empty on release" unless (build_number != nil) && (!build_number.empty?)
|
70
|
+
|
71
|
+
print "Committing #{@configuration.app_info_plist} with version #{build_number}"
|
72
|
+
|
73
|
+
stage_files [@configuration.app_info_plist]
|
74
|
+
commit_and_push_with_message "Preparing for next release..."
|
75
|
+
|
76
|
+
puts "Done"
|
77
|
+
end
|
78
|
+
|
79
|
+
def stage_files files
|
80
|
+
cmd = []
|
81
|
+
|
82
|
+
cmd << "git"
|
83
|
+
cmd << "add"
|
84
|
+
files.each do |value|
|
85
|
+
cmd << value
|
86
|
+
end
|
87
|
+
system(cmd.join " ")
|
88
|
+
end
|
89
|
+
|
90
|
+
def commit_and_push_with_message message
|
91
|
+
# then commit it
|
92
|
+
cmd = []
|
93
|
+
cmd << "git"
|
94
|
+
cmd << "commit"
|
95
|
+
cmd << "-m"
|
96
|
+
cmd << "'#{message}'"
|
97
|
+
cmd << "2>&1 %s git.output" % (@configuration.verbose ? '| tee' : '>')
|
98
|
+
system(cmd.join " ")
|
99
|
+
puts
|
100
|
+
puts "Done"
|
101
|
+
|
102
|
+
# now, push the updated plist
|
103
|
+
print "Pushing update to #{@origin}/#{@branch}"
|
104
|
+
cmd = []
|
105
|
+
cmd << "git"
|
106
|
+
cmd << "push"
|
107
|
+
cmd << @origin
|
108
|
+
cmd << @branch
|
109
|
+
cmd << "2>&1 %s git.output" % (@configuration.verbose ? '| tee' : '>')
|
110
|
+
|
111
|
+
system(cmd.join " ")
|
112
|
+
puts
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|