yolo 1.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +4 -0
- data/Rakefile +32 -0
- data/lib/yolo.rb +13 -0
- data/lib/yolo/config.rb +1 -0
- data/lib/yolo/config/config.yml +16 -0
- data/lib/yolo/config/settings.rb +89 -0
- data/lib/yolo/deployment.rb +2 -0
- data/lib/yolo/deployment/base_deployer.rb +14 -0
- data/lib/yolo/deployment/ota.rb +74 -0
- data/lib/yolo/formatters.rb +2 -0
- data/lib/yolo/formatters/error_formatter.rb +33 -0
- data/lib/yolo/formatters/progress_formatter.rb +96 -0
- data/lib/yolo/history/history.yml +3 -0
- data/lib/yolo/notify.rb +2 -0
- data/lib/yolo/notify/email.rb +64 -0
- data/lib/yolo/notify/ios/email.html +567 -0
- data/lib/yolo/notify/ios/ota_email.rb +24 -0
- data/lib/yolo/tasks.rb +5 -0
- data/lib/yolo/tasks/base_task.rb +22 -0
- data/lib/yolo/tasks/ios/build.rb +28 -0
- data/lib/yolo/tasks/ios/calabash.rb +46 -0
- data/lib/yolo/tasks/ios/ocunit.rb +58 -0
- data/lib/yolo/tasks/ios/release.rb +182 -0
- data/lib/yolo/tools.rb +5 -0
- data/lib/yolo/tools/git.rb +190 -0
- data/lib/yolo/tools/ios/calabash.rb +26 -0
- data/lib/yolo/tools/ios/ipa.rb +31 -0
- data/lib/yolo/tools/ios/release_notes.rb +34 -0
- data/lib/yolo/tools/ios/xcode.rb +51 -0
- metadata +138 -0
data/README.md
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'yolo'
|
3
|
+
|
4
|
+
namespace :gem do
|
5
|
+
desc "Builds and then installs the gem"
|
6
|
+
task :buildinstall do
|
7
|
+
system 'gem build yolo.gemspec'
|
8
|
+
system 'gem install yolo-1.0.0.pre.gem'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
### Sample
|
13
|
+
|
14
|
+
#Yolo::Tasks::Ios::Build.new do |t|
|
15
|
+
# t.workspace = "Honk.xcworkspace"
|
16
|
+
# t.scheme = "Honk"
|
17
|
+
# t.formatter = XcodeBuild::Formatters::ProgressFormatter.new
|
18
|
+
#end
|
19
|
+
#
|
20
|
+
#Yolo::Tasks::Ios::OCUnit.new do |t|
|
21
|
+
# t.workspace = "Honk.xcworkspace"
|
22
|
+
# t.scheme = "HonkTests"
|
23
|
+
# t.test_output = :junit
|
24
|
+
# t.formatter = XcodeBuild::Formatters::ProgressFormatter.new
|
25
|
+
#end
|
26
|
+
#
|
27
|
+
#Yolo::Tasks::Ios::Calabash.new do |t|
|
28
|
+
# t.workspace = "Honk.xcworkspace"
|
29
|
+
# t.scheme = "Honk-cal"
|
30
|
+
# t.format = :junit
|
31
|
+
# t.formatter = XcodeBuild::Formatters::ProgressFormatter.new
|
32
|
+
#end
|
data/lib/yolo.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#
|
2
|
+
# The master Yolo module wrapper which contains all of yolo's classes
|
3
|
+
#
|
4
|
+
# @author Alex Fish
|
5
|
+
module Yolo
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'yolo/tasks'
|
9
|
+
require 'yolo/tools'
|
10
|
+
require 'yolo/formatters'
|
11
|
+
require 'yolo/config'
|
12
|
+
require 'yolo/deployment'
|
13
|
+
require 'yolo/notify'
|
data/lib/yolo/config.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'yolo/config/settings'
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# The directory which applications are bundled to
|
2
|
+
# e.g /my/bundle/directory
|
3
|
+
paths:
|
4
|
+
bundle_directory: "/tmp"
|
5
|
+
|
6
|
+
# Email notification settings
|
7
|
+
mail:
|
8
|
+
host: your.server.ip
|
9
|
+
from: example@example.com
|
10
|
+
account: example@example.com
|
11
|
+
password: example
|
12
|
+
port: 0
|
13
|
+
|
14
|
+
# Deployment settings
|
15
|
+
deployment:
|
16
|
+
url: http://example.com
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'yaml'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module Yolo
|
6
|
+
module Config
|
7
|
+
class Settings
|
8
|
+
|
9
|
+
include Singleton
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@formatter = Yolo::Formatters::ProgressFormatter.new
|
13
|
+
@error = Yolo::Formatters::ErrorFormatter.new
|
14
|
+
check_config
|
15
|
+
@yaml = YAML::load_file yaml_path
|
16
|
+
end
|
17
|
+
|
18
|
+
def load_config
|
19
|
+
create_yolo_dir
|
20
|
+
unless File.exist?(yaml_path)
|
21
|
+
@formatter.config_created(yaml_path)
|
22
|
+
FileUtils.cp_r(File.dirname(__FILE__) + "/config.yml", yaml_path)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def bundle_directory
|
27
|
+
@yaml["paths"]["bundle_directory"]
|
28
|
+
end
|
29
|
+
|
30
|
+
def deploy_url
|
31
|
+
@yaml["deployment"]["url"] if @yaml["deployment"]["url"] and @yaml["deployment"]["url"] != "http://example.com"
|
32
|
+
end
|
33
|
+
|
34
|
+
# email
|
35
|
+
def mail_account
|
36
|
+
@yaml["mail"]["account"] if @yaml["mail"]["account"] and @yaml["mail"]["account"] != "example@example.com"
|
37
|
+
end
|
38
|
+
|
39
|
+
def mail_password
|
40
|
+
@yaml["mail"]["password"] if @yaml["mail"]["password"] and @yaml["mail"]["password"] != "example"
|
41
|
+
end
|
42
|
+
|
43
|
+
def mail_port
|
44
|
+
@yaml["mail"]["port"] if @yaml["mail"]["port"] and @yaml["mail"]["port"] != 0
|
45
|
+
end
|
46
|
+
|
47
|
+
def mail_host
|
48
|
+
@yaml["mail"]["host"] if @yaml["mail"]["host"] and @yaml["mail"]["host"] != "your.server.ip"
|
49
|
+
end
|
50
|
+
|
51
|
+
def mail_to
|
52
|
+
@yaml["mail"]["to"] if @yaml["mail"]["to"] and @yaml["mail"]["to"] != "example@example.com"
|
53
|
+
end
|
54
|
+
|
55
|
+
def mail_from
|
56
|
+
@yaml["mail"]["from"] if @yaml["mail"]["from"] and @yaml["mail"]["from"] != "example@example.com"
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def check_config
|
62
|
+
unless File.directory?(yolo_dir) and File.exist?(yaml_path)
|
63
|
+
@error.run_setup
|
64
|
+
load_config
|
65
|
+
@formatter.setup_complete
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def user_directory
|
70
|
+
File.expand_path('~')
|
71
|
+
end
|
72
|
+
|
73
|
+
def yaml_path
|
74
|
+
"#{user_directory}/.yolo/config.yml"
|
75
|
+
end
|
76
|
+
|
77
|
+
def yolo_dir
|
78
|
+
"#{user_directory}/.yolo"
|
79
|
+
end
|
80
|
+
|
81
|
+
def create_yolo_dir
|
82
|
+
unless File.directory?(yolo_dir)
|
83
|
+
FileUtils.mkdir_p(yolo_dir)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Yolo
|
4
|
+
module Deployment
|
5
|
+
class OTA < Yolo::Deployment::BaseDeployer
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@error_formatter = Yolo::Formatters::ErrorFormatter.new
|
9
|
+
@progress_formatter = Yolo::Formatters::ProgressFormatter.new
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
def deploy(ipa_path, &block)
|
14
|
+
self.ipa_path = ipa_path
|
15
|
+
@complete_block = block
|
16
|
+
|
17
|
+
unless self.url
|
18
|
+
@error_formatter.no_deploy_url
|
19
|
+
return
|
20
|
+
end
|
21
|
+
|
22
|
+
@progress_formatter.deploying_ipa(self.ipa_path)
|
23
|
+
|
24
|
+
upload
|
25
|
+
end
|
26
|
+
|
27
|
+
def package
|
28
|
+
filename = self.ipa_path.split("/").last
|
29
|
+
"{\"fileName\": \"#{filename}\", \"password\": \"\", \"validUntil\": \"2000000000\"}"
|
30
|
+
end
|
31
|
+
|
32
|
+
def upload
|
33
|
+
response = ""
|
34
|
+
IO.popen("curl -s #{self.url} -X POST -F fileContent=@\"#{self.ipa_path}\" -F params='#{package}'") do |io|
|
35
|
+
begin
|
36
|
+
while line = io.readline
|
37
|
+
begin
|
38
|
+
response << line
|
39
|
+
rescue StandardError => e
|
40
|
+
@error_formatter.deploy_failed("ParserError: #{e}")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
rescue EOFError
|
44
|
+
#@error_formatter.deploy_failed("ParserError")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
upload_complete(response)
|
48
|
+
end
|
49
|
+
|
50
|
+
def upload_complete(response)
|
51
|
+
json = nil
|
52
|
+
begin
|
53
|
+
json = JSON.parse(response)
|
54
|
+
rescue JSON::ParserError
|
55
|
+
@error_formatter.deploy_failed("\n ParserError: Deployment server response is not JSON")
|
56
|
+
return
|
57
|
+
end
|
58
|
+
|
59
|
+
unless json
|
60
|
+
@error_formatter.deploy_failed("\n ParserError: Deployment server response is not JSON")
|
61
|
+
return
|
62
|
+
end
|
63
|
+
|
64
|
+
url = json["link"]
|
65
|
+
password = json["password"]
|
66
|
+
|
67
|
+
@complete_block.call(url,password)
|
68
|
+
@progress_formatter.deploy_complete(url,password)
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'xcodebuild'
|
2
|
+
|
3
|
+
module Yolo
|
4
|
+
module Formatters
|
5
|
+
class ErrorFormatter < XcodeBuild::Formatters::ProgressFormatter
|
6
|
+
|
7
|
+
def info_plist_not_found
|
8
|
+
puts red("Can't locate Info.plist")
|
9
|
+
end
|
10
|
+
|
11
|
+
def run_setup
|
12
|
+
puts red("Setup required, running rake yolo:setup")
|
13
|
+
end
|
14
|
+
|
15
|
+
def deployment_class_error(klass)
|
16
|
+
puts red("#{klass} is not a valid Class in the Deployment module")
|
17
|
+
end
|
18
|
+
|
19
|
+
def deploy_failed(error)
|
20
|
+
puts red("There was a problem deploying the ipa: #{error}")
|
21
|
+
end
|
22
|
+
|
23
|
+
def no_deploy_url
|
24
|
+
puts red("No deploy url found, please specify one in ~/.yolo/config.yml")
|
25
|
+
end
|
26
|
+
|
27
|
+
def missing_email_details
|
28
|
+
puts red("Can't send mail notification, missing details")
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
require 'xcodebuild'
|
2
|
+
|
3
|
+
module Yolo
|
4
|
+
module Formatters
|
5
|
+
class ProgressFormatter < XcodeBuild::Formatters::ProgressFormatter
|
6
|
+
|
7
|
+
def config_created(config)
|
8
|
+
puts green("Config file created in: #{config}")
|
9
|
+
end
|
10
|
+
|
11
|
+
def setup_complete
|
12
|
+
puts green("Setup complete")
|
13
|
+
end
|
14
|
+
|
15
|
+
def generating_ipa
|
16
|
+
puts
|
17
|
+
generating = "Generating IPA"
|
18
|
+
puts bold(generating)
|
19
|
+
puts generating.length.times.map {"="}.join
|
20
|
+
puts
|
21
|
+
end
|
22
|
+
|
23
|
+
def deploying_ipa(ipa)
|
24
|
+
puts
|
25
|
+
deploying = "Deploying IPA"
|
26
|
+
puts bold(deploying)
|
27
|
+
puts deploying.length.times.map {"="}.join
|
28
|
+
puts
|
29
|
+
puts ("#{filesize(ipa)}MB")
|
30
|
+
puts
|
31
|
+
end
|
32
|
+
|
33
|
+
def ipa_generated(ipa)
|
34
|
+
puts green("IPA saved to: #{ipa}")
|
35
|
+
end
|
36
|
+
|
37
|
+
def generating_notes
|
38
|
+
puts
|
39
|
+
notes = "Generating release notes"
|
40
|
+
puts bold(notes)
|
41
|
+
puts notes.length.times.map {"="}.join
|
42
|
+
puts
|
43
|
+
end
|
44
|
+
|
45
|
+
def notes_generated(notes)
|
46
|
+
puts green("Release notes generated")
|
47
|
+
end
|
48
|
+
|
49
|
+
def new_tag(tag)
|
50
|
+
puts cyan("Found new tag: #{tag}")
|
51
|
+
end
|
52
|
+
|
53
|
+
def new_commit(commit)
|
54
|
+
puts cyan("Found new commit: #{commit}")
|
55
|
+
end
|
56
|
+
|
57
|
+
def no_new_commit
|
58
|
+
puts red("No new commit found")
|
59
|
+
end
|
60
|
+
|
61
|
+
def no_new_tag
|
62
|
+
puts red("No new tag found")
|
63
|
+
end
|
64
|
+
|
65
|
+
def sending_email
|
66
|
+
puts
|
67
|
+
email = "Sending notification email"
|
68
|
+
puts bold(email)
|
69
|
+
puts email.length.times.map {"="}.join
|
70
|
+
puts
|
71
|
+
end
|
72
|
+
|
73
|
+
def email_sent(to)
|
74
|
+
puts green("Notification sent to: #{to}")
|
75
|
+
end
|
76
|
+
|
77
|
+
def deploy_complete(url,password)
|
78
|
+
puts
|
79
|
+
deployed = "IPA deployed"
|
80
|
+
puts bold(deployed)
|
81
|
+
puts deployed.length.times.map {"="}.join
|
82
|
+
puts
|
83
|
+
puts green("URL")
|
84
|
+
puts green(url)
|
85
|
+
puts
|
86
|
+
puts green("Password")
|
87
|
+
puts green(password)
|
88
|
+
puts
|
89
|
+
end
|
90
|
+
|
91
|
+
def filesize(file)
|
92
|
+
'%.2f' % (File.size(file).to_f / 2**20)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
data/lib/yolo/notify.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'net/smtp'
|
2
|
+
|
3
|
+
module Yolo
|
4
|
+
module Notify
|
5
|
+
class Email
|
6
|
+
|
7
|
+
attr_accessor :to
|
8
|
+
attr_accessor :from
|
9
|
+
attr_accessor :server
|
10
|
+
attr_accessor :port
|
11
|
+
attr_accessor :account
|
12
|
+
attr_accessor :password
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
self.server = Yolo::Config::Settings.instance.mail_host
|
16
|
+
self.from = Yolo::Config::Settings.instance.mail_from
|
17
|
+
self.to = Yolo::Config::Settings.instance.mail_to
|
18
|
+
self.port = Yolo::Config::Settings.instance.mail_port
|
19
|
+
self.account = Yolo::Config::Settings.instance.mail_account
|
20
|
+
self.password = Yolo::Config::Settings.instance.mail_password
|
21
|
+
|
22
|
+
@error_formatter = Yolo::Formatters::ErrorFormatter.new
|
23
|
+
@progress_formatter = Yolo::Formatters::ProgressFormatter.new
|
24
|
+
end
|
25
|
+
|
26
|
+
def send(opts={})
|
27
|
+
|
28
|
+
opts[:server] ||= self.server
|
29
|
+
opts[:from] ||= self.from
|
30
|
+
opts[:subject] ||= "New Build!"
|
31
|
+
opts[:body] ||= body(opts)
|
32
|
+
opts[:password] ||= self.password
|
33
|
+
opts[:account] ||= self.account
|
34
|
+
opts[:port] ||= self.port
|
35
|
+
opts[:to] ||= self.to
|
36
|
+
|
37
|
+
msg = opts[:body]
|
38
|
+
|
39
|
+
if opts[:account] and opts[:password] and opts[:port] and opts[:to]
|
40
|
+
@progress_formatter.sending_email
|
41
|
+
smtp = Net::SMTP.new opts[:server], opts[:port]
|
42
|
+
smtp.enable_starttls
|
43
|
+
smtp.start(opts[:server], opts[:account], opts[:password], :login) do
|
44
|
+
smtp.send_message(msg, opts[:from], opts[:to])
|
45
|
+
@progress_formatter.email_sent(opts[:to])
|
46
|
+
end
|
47
|
+
elsif opts[:server] and opts[:to]
|
48
|
+
@progress_formatter.sending_email
|
49
|
+
Net::SMTP.start(opts[:server]) do |smtp|
|
50
|
+
smtp.send_message(msg, opts[:from], opts[:to])
|
51
|
+
@progress_formatter.email_sent(opts[:to])
|
52
|
+
end
|
53
|
+
else
|
54
|
+
@error_formatter.missing_email_details
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def body(opts)
|
59
|
+
""
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|