yolo 1.2.8 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -16,3 +16,7 @@ deployment:
16
16
  url: http://example.com
17
17
  api_token: example
18
18
  team_token: example
19
+
20
+ # Github
21
+ github:
22
+ token: token
@@ -168,6 +168,16 @@ module Yolo
168
168
  end
169
169
  end
170
170
 
171
+ #
172
+ # The github token used to connect to the github api
173
+ #
174
+ # @return [String] The token defined in config.yml
175
+ def github_token
176
+ if @yaml["github"]["token"] != "token"
177
+ return @yaml["github"]["token"]
178
+ end
179
+ end
180
+
171
181
  #
172
182
  # The path to the users home directory, same as ~
173
183
  #
@@ -46,6 +46,14 @@ module Yolo
46
46
  puts red("There was a problem deploying the ipa: #{error}")
47
47
  end
48
48
 
49
+ #
50
+ # Outputs a red string stating that there was an issue deploying the bundle to github
51
+ # @param error [String] The error string
52
+ #
53
+ def github_upload_failed(error)
54
+ puts red("There was a problem deploying the bundle to github: #{error}")
55
+ end
56
+
49
57
  #
50
58
  # Outputs a red string stating that no deploy URL was found in the config file
51
59
  #
@@ -74,6 +82,10 @@ module Yolo
74
82
  puts red("Can't send mail notification, missing details")
75
83
  end
76
84
 
85
+ def no_github_token
86
+ puts red("No Github token found, please specify one in ~/.yolo/config.yml ")
87
+ end
88
+
77
89
  #
78
90
  # Outputs a red string stating that a release notes file could not be found
79
91
  # @param notes [String] The path which should contain a notes file
@@ -93,6 +93,41 @@ module Yolo
93
93
  puts
94
94
  end
95
95
 
96
+ #
97
+ # Outputs a string stating that the github release is being generated
98
+ #
99
+ def creating_github_release
100
+ github = "Generating Github release"
101
+ puts bold(github)
102
+ puts github.length.times.map {"="}.join
103
+ puts
104
+ end
105
+
106
+ #
107
+ # Outputs a green string stating that the github release was created
108
+ #
109
+ def created_release(version)
110
+ puts green("Release #{version} created")
111
+ end
112
+
113
+ #
114
+ # Outputs a green string stating that the github release finished
115
+ #
116
+ def github_released
117
+ puts green("Release completed")
118
+ end
119
+
120
+ #
121
+ # Outputs an underlined bold string stating that the is uploading
122
+ #
123
+ def github_uploading
124
+ puts
125
+ github = "Uploading package"
126
+ puts bold(github)
127
+ puts github.length.times.map {"="}.join
128
+ puts
129
+ end
130
+
96
131
  #
97
132
  # Outputs a green string stating that the release notes have been generated
98
133
  # @param notes [String] The path to the release notes
@@ -23,7 +23,6 @@ module Yolo
23
23
  self.format = :junit
24
24
  self.device = "iphone"
25
25
  self.output_dir = "test-reports/calabash"
26
- super
27
26
  end
28
27
 
29
28
  #
@@ -16,6 +16,8 @@ module Yolo
16
16
  attr_accessor :deployment
17
17
  # A Hash of additional options
18
18
  attr_accessor :options
19
+ # A Github repo to release to
20
+ attr_accessor :github_repo
19
21
 
20
22
  #
21
23
  # Initializes the class with default settings
@@ -127,6 +129,22 @@ module Yolo
127
129
  end
128
130
  end
129
131
 
132
+ #
133
+ # Release the ipa using the github releases API, the ipa will be zipped and
134
+ # uploaded as well as the release notes used as the release body and
135
+ # version for the release title
136
+ #
137
+ # @param ipa_path [String] The full path to the IPA file to deploy
138
+ #
139
+ def release_to_github(bundle_path)
140
+ if self.github_repo
141
+ github = Yolo::Tools::Github.new
142
+ notes = Yolo::Tools::Ios::ReleaseNotes.html
143
+ github.repo = self.github_repo
144
+ github.release(bundle_path, version, notes)
145
+ end
146
+ end
147
+
130
148
  #
131
149
  # Sends a notificaiton email from a deployment
132
150
  # @param url [String] The URL which the build has been deplyed too
@@ -172,6 +190,7 @@ module Yolo
172
190
  xcodebuild :build
173
191
  Yolo::Tools::Ios::IPA.generate(app_path,dsym_path,bundle_path) do |ipa|
174
192
  deploy(ipa) if ipa and self.deployment
193
+ release_to_github(bundle_path) if ipa and self.github_repo
175
194
  end
176
195
  end
177
196
 
@@ -9,4 +9,5 @@ module Yolo
9
9
  end
10
10
 
11
11
  require 'yolo/tools/git'
12
+ require 'yolo/tools/github'
12
13
  require 'yolo/tools/ios'
@@ -79,6 +79,20 @@ module Yolo
79
79
  @commit
80
80
  end
81
81
 
82
+ #
83
+ # Finds the current branch using some regex and git branch
84
+ #
85
+ # @return [String] The current branch name
86
+ def current_branch
87
+ branch = `git branch`
88
+ branchs = branch.split("\n")
89
+ current_branch = ""
90
+ branchs.each do |b|
91
+ current_branch = b if b.count("*") == 1
92
+ end
93
+ current_branch.gsub("* ", "")
94
+ end
95
+
82
96
  private
83
97
 
84
98
  #
@@ -198,19 +212,6 @@ module Yolo
198
212
  `git log --decorate=short -n 1 --pretty=oneline`
199
213
  end
200
214
 
201
- #
202
- # Finds the current branch using some regex and git branch
203
- #
204
- # @return [String] The current branch name
205
- def current_branch
206
- branch = `git branch`
207
- branchs = branch.split("\n")
208
- current_branch = ""
209
- branchs.each do |b|
210
- current_branch = b if b.count("*") == 1
211
- end
212
- current_branch.gsub("* ", "")
213
- end
214
215
  end
215
216
  end
216
217
  end
@@ -0,0 +1,145 @@
1
+ require "zip"
2
+ require "net/http"
3
+ require "uri"
4
+ require 'json'
5
+
6
+ module Yolo
7
+ module Tools
8
+ #
9
+ # Communicates with Github
10
+ #
11
+ # @author [Alex Fish]
12
+ #
13
+ class Github
14
+
15
+ # The github repo that all actions will target
16
+ attr_accessor :repo
17
+
18
+ #
19
+ # Creates the class with default variables
20
+ #
21
+ def initialize
22
+ @token = Yolo::Config::Settings.instance.github_token
23
+ if !@token
24
+ error = Yolo::Formatters::ErrorFormatter.new
25
+ error.no_github_token
26
+ end
27
+ end
28
+
29
+ # Release the bundle using the github releases API, the bundle will be zipped and
30
+ # uploaded as well as the release notes used as the release body and
31
+ # version for the release title
32
+ #
33
+ # @param bundle [String] The full path to the bundle folder to release
34
+ # @param version [String] The version of the release
35
+ # @param body [String] The body of the release
36
+ #
37
+ def release(bundle, version, body)
38
+ @progress = Yolo::Formatters::ProgressFormatter.new
39
+ @progress.creating_github_release
40
+
41
+ uri = URI.parse("https://api.github.com/repos/#{self.repo}/releases?access_token=#{@token}")
42
+
43
+ http = Net::HTTP.new(uri.host, uri.port)
44
+ http.use_ssl = true
45
+
46
+ request = Net::HTTP::Post.new(uri.request_uri)
47
+ request.body = options(body, version)
48
+
49
+ # Tweak headers, removing this will default to application/x-www-form-urlencoded
50
+ request["Content-Type"] = "application/json"
51
+
52
+ response = http.request(request)
53
+ response = JSON.parse(response.body)
54
+
55
+ @progress.created_release(version)
56
+
57
+ url = response["upload_url"].gsub("{?name}","")
58
+ upload_bundle(bundle, url, "#{version}.zip")
59
+ end
60
+
61
+ # Upload the bundle to the github release url
62
+ #
63
+ # @param bundle [String] The full path to the bundle folder to release
64
+ # @param url [String] The github asset url returned from create_release
65
+ #
66
+ def upload_bundle(bundle, url, name)
67
+ @progress = Yolo::Formatters::ProgressFormatter.new
68
+ @progress.github_uploading
69
+ zipped_bundle = zip_bundle(bundle)
70
+
71
+ response = ""
72
+ curl = curl_string(name, zipped_bundle, url)
73
+ puts curl
74
+ IO.popen(curl) do |io|
75
+ begin
76
+ while line = io.readline
77
+ response << line
78
+ end
79
+ if response.length == 0
80
+ @error_formatter.github_upload_failed("Upload error")
81
+ end
82
+ rescue EOFError
83
+ end
84
+ end
85
+
86
+ @progress.github_released
87
+ end
88
+
89
+ private
90
+
91
+ # Generate a curl command string to upload the release to github with
92
+ #
93
+ # @param name [String] The name of the file
94
+ # @param zipped_bundle [String] The full path to the zipped bundle folder
95
+ # @param url [String] The URL for the request
96
+ #
97
+ # @return [String] The curl command string
98
+ def curl_string(name, zipped_bundle, url)
99
+ "curl -# -H \"Accept: application/vnd.github.manifold-preview\" \
100
+ -H \"Content-Type: application/zip\" \
101
+ --data-binary @#{zipped_bundle} \
102
+ \"#{url}?name=#{name}&access_token=#{@token}\"
103
+ "
104
+ end
105
+
106
+ # Zip the bundle ready for upload to github, the zip will have the same
107
+ # name as the bundle folder with .zip appended
108
+ #
109
+ # @param bundle [String] The full path to the bundle folder to zip
110
+ #
111
+ # @return [String] The zipped bundle path
112
+ def zip_bundle(bundle)
113
+ bundle.sub!(%r[/$],'')
114
+ archive = File.join(bundle,File.basename(bundle))+'.zip'
115
+ FileUtils.rm archive, :force=>true
116
+
117
+ Zip::File.open(archive, 'w') do |zipfile|
118
+ Dir["#{bundle}/**/**"].reject{|f|f==archive}.each do |file|
119
+ zipfile.add(file.sub(bundle+'/',''),file)
120
+ end
121
+ return archive
122
+ end
123
+ end
124
+
125
+ #
126
+ # Generates an options hash for a github release
127
+ #
128
+ # @return [String] The current branch name
129
+ def options(body, version)
130
+ options = {"body" => body, "tag_name" => version, "name" => version, "target_commitish" => current_branch}
131
+ options.to_json
132
+ end
133
+
134
+ #
135
+ # Finds the current branch using the git tool
136
+ #
137
+ # @return [String] The current branch name
138
+ def current_branch
139
+ git = Yolo::Tools::Git.new
140
+ git.current_branch
141
+ end
142
+
143
+ end
144
+ end
145
+ end
@@ -22,14 +22,6 @@ module Yolo
22
22
  File.open("#{directory}/release_notes.md", 'w') {|f|
23
23
  f.write("### Version\n- - -\n")
24
24
  f.write("#{xcode.version_number} (#{xcode.build_number})\n\n")
25
- f.write("### Change log\n- - -\n")
26
- f.write("* No Changes\n\n")
27
- f.write("### Fixes\n- - -\n")
28
- f.write("* No Fixes\n\n")
29
- f.write("### Notes\n- - -\n")
30
- f.write("No Notes\n\n")
31
- f.write("### Known issues\n- - -\n")
32
- f.write("No Known issues\n\n")
33
25
  f.write("### Date\n- - -\n")
34
26
  f.write("#{time.day}/#{time.month}/#{time.year} - #{time.hour}:#{time.min}")
35
27
  }
@@ -37,7 +29,7 @@ module Yolo
37
29
  formatter = Yolo::Formatters::ProgressFormatter.new
38
30
  formatter.notes_generated("#{directory}/release_notes.md")
39
31
 
40
- `open #{directory}/release_notes.md`
32
+ #`open #{directory}/release_notes.md`
41
33
  end
42
34
 
43
35
  #
@@ -98,6 +98,9 @@ describe Yolo::Config::Settings do
98
98
  "port" => "test_port",
99
99
  "host" => "test_host",
100
100
  "from" => "test_from"
101
+ },
102
+ "github" => {
103
+ "token" => "test_token"
101
104
  }
102
105
  }
103
106
  YAML.stub(:load_file){@yaml}
@@ -139,5 +142,9 @@ describe Yolo::Config::Settings do
139
142
  it "should hold a mail from" do
140
143
  Yolo::Config::Settings.instance.mail_from.should eq("test_from")
141
144
  end
145
+
146
+ it "should hold a github token" do
147
+ Yolo::Config::Settings.instance.github_token.should eq("test_token")
148
+ end
142
149
  end
143
150
  end
@@ -11,6 +11,10 @@ describe Yolo::Tasks::Ios::Release do
11
11
  @email.stub(:send)
12
12
  Yolo::Notify::Ios::OTAEmail.stub(:new){@email}
13
13
 
14
+ @github = mock(Yolo::Tools::Github)
15
+ @github.stub(:repo=)
16
+ Yolo::Tools::Github.stub(:new){@github}
17
+
14
18
  @ota = mock(Yolo::Deployment::OTA)
15
19
  Yolo::Deployment::OTA.stub(:new){@ota}
16
20
 
@@ -149,6 +153,18 @@ describe Yolo::Tasks::Ios::Release do
149
153
  @release.deploy("")
150
154
  end
151
155
 
156
+ it "should release to github if a repo is set" do
157
+ @github.should_receive(:release)
158
+ @release.stub(:github_repo){"test_repo"}
159
+ @release.release_to_github("")
160
+ end
161
+
162
+ it "should not release to github if no repo is set" do
163
+ @github.should_not_receive(:release)
164
+ @release.stub(:github_repo){nil}
165
+ @release.release_to_github("")
166
+ end
167
+
152
168
  it "shouldnt build mail options without a url" do
153
169
  @ota.stub(:deploy).and_yield(nil, nil)
154
170
  @email.should_not_receive(:send)
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+ require 'yolo'
3
+
4
+ describe Yolo::Tools::Github do
5
+
6
+ before do
7
+ Yolo::Formatters::ProgressFormatter.any_instance.stub(:puts)
8
+ Yolo::Formatters::ErrorFormatter.any_instance.stub(:puts)
9
+ end
10
+
11
+ describe "when initlized" do
12
+ it "should load the token from settings" do
13
+ Yolo::Config::Settings.instance.stub(:github_token){"token"}
14
+ github = Yolo::Tools::Github.new
15
+ github.instance_variable_get(:@token).should_not eq(nil)
16
+ end
17
+
18
+ it "should thrown an error if there is no token" do
19
+ Yolo::Config::Settings.instance.stub(:github_token){nil}
20
+ Yolo::Formatters::ErrorFormatter.any_instance.should_receive(:no_github_token)
21
+
22
+ github = Yolo::Tools::Github.new
23
+ end
24
+ end
25
+
26
+ describe "when releasing" do
27
+ before do
28
+ @git = mock(Yolo::Tools::Git)
29
+ Yolo::Tools::Git.stub(:new){@git}
30
+ @git.stub(:current_branch){"branch"}
31
+
32
+ @github = Yolo::Tools::Github.new
33
+ @github.instance_variable_get(:@octokit).stub(:create_release)
34
+ end
35
+
36
+ it "should get the current git branch" do
37
+ @github.instance_eval{current_branch}.should eq("branch")
38
+ end
39
+
40
+ it "should zip the bundle" do
41
+ @github.instance_variable_get(:@octokit).stub(:upload_asset)
42
+ @github.should_receive(:zip_bundle).with("path")
43
+ @github.upload_bundle("path", "version", "name")
44
+ end
45
+ end
46
+
47
+ describe "when generating options" do
48
+
49
+ before do
50
+ github = Yolo::Tools::Github.new
51
+ github.stub(:current_branch){"target_commitish"}
52
+ @options = github.instance_eval{options("body", "version")}
53
+ end
54
+
55
+ it "should hold a version" do
56
+ @options["name"].should eq("name")
57
+ end
58
+
59
+ it "should hold a body" do
60
+ @options["body"].should eq("body")
61
+ end
62
+
63
+ it "should hold the target_commitish" do
64
+ @options["target_commitish"].should eq("target_commitish")
65
+ end
66
+ end
67
+ end
@@ -54,11 +54,6 @@ describe Yolo::Tools::Ios::ReleaseNotes do
54
54
  @time.should_receive(:min)
55
55
  @release_notes.generate("path")
56
56
  end
57
-
58
- it "should open the release notes after writting" do
59
- @release_notes.should_receive(:`).with(/open current_path\/release_notes.md/)
60
- @release_notes.generate("path")
61
- end
62
57
  end
63
58
 
64
59
  describe "when parsing release notes to plain text" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yolo
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.8
4
+ version: 1.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-13 00:00:00.000000000 Z
12
+ date: 2013-11-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: xcodebuild-rb
@@ -75,6 +75,22 @@ dependencies:
75
75
  - - ! '>='
76
76
  - !ruby/object:Gem::Version
77
77
  version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: rubyzip
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - '='
84
+ - !ruby/object:Gem::Version
85
+ version: 1.1.0
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - '='
92
+ - !ruby/object:Gem::Version
93
+ version: 1.1.0
78
94
  description: yolo is a RubyGem which provides a Ruby interface to Continuous Integration
79
95
  build tools. yolo is currently geared towards the Xcode toolchain and iOS development.
80
96
  email: alex@alexefish.com
@@ -111,6 +127,7 @@ files:
111
127
  - lib/yolo/tasks/ios.rb
112
128
  - lib/yolo/tasks.rb
113
129
  - lib/yolo/tools/git.rb
130
+ - lib/yolo/tools/github.rb
114
131
  - lib/yolo/tools/ios/calabash.rb
115
132
  - lib/yolo/tools/ios/coverage.rb
116
133
  - lib/yolo/tools/ios/ipa.rb
@@ -134,6 +151,7 @@ files:
134
151
  - spec/tasks/ios/ocunit_spec.rb
135
152
  - spec/tasks/ios/release_spec.rb
136
153
  - spec/tools/git_spec.rb
154
+ - spec/tools/github_spec.rb
137
155
  - spec/tools/ios/calabash_spec.rb
138
156
  - spec/tools/ios/coverage_spec.rb
139
157
  - spec/tools/ios/ipa_spec.rb
@@ -160,7 +178,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
160
178
  version: '0'
161
179
  requirements: []
162
180
  rubyforge_project:
163
- rubygems_version: 1.8.23
181
+ rubygems_version: 1.8.24
164
182
  signing_key:
165
183
  specification_version: 3
166
184
  summary: YOLO!