hitimes 1.3.0-x64-mingw32

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.
Files changed (52) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.md +57 -0
  3. data/HISTORY.md +124 -0
  4. data/LICENSE +16 -0
  5. data/Manifest.txt +44 -0
  6. data/README.md +200 -0
  7. data/Rakefile +28 -0
  8. data/examples/benchmarks.rb +113 -0
  9. data/examples/stats.rb +31 -0
  10. data/ext/hitimes/c/extconf.rb +24 -0
  11. data/ext/hitimes/c/hitimes.c +37 -0
  12. data/ext/hitimes/c/hitimes_instant_clock_gettime.c +28 -0
  13. data/ext/hitimes/c/hitimes_instant_osx.c +45 -0
  14. data/ext/hitimes/c/hitimes_instant_windows.c +27 -0
  15. data/ext/hitimes/c/hitimes_interval.c +370 -0
  16. data/ext/hitimes/c/hitimes_interval.h +73 -0
  17. data/ext/hitimes/c/hitimes_stats.c +269 -0
  18. data/ext/hitimes/c/hitimes_stats.h +30 -0
  19. data/ext/hitimes/java/src/hitimes/Hitimes.java +66 -0
  20. data/ext/hitimes/java/src/hitimes/HitimesInterval.java +176 -0
  21. data/ext/hitimes/java/src/hitimes/HitimesService.java +16 -0
  22. data/ext/hitimes/java/src/hitimes/HitimesStats.java +112 -0
  23. data/lib/hitimes.rb +66 -0
  24. data/lib/hitimes/2.0/hitimes.so +0 -0
  25. data/lib/hitimes/2.1/hitimes.so +0 -0
  26. data/lib/hitimes/2.2/hitimes.so +0 -0
  27. data/lib/hitimes/2.3/hitimes.so +0 -0
  28. data/lib/hitimes/2.4/hitimes.so +0 -0
  29. data/lib/hitimes/2.5/hitimes.so +0 -0
  30. data/lib/hitimes/metric.rb +118 -0
  31. data/lib/hitimes/mutexed_stats.rb +32 -0
  32. data/lib/hitimes/paths.rb +53 -0
  33. data/lib/hitimes/stats.rb +58 -0
  34. data/lib/hitimes/timed_metric.rb +176 -0
  35. data/lib/hitimes/timed_value_metric.rb +233 -0
  36. data/lib/hitimes/value_metric.rb +71 -0
  37. data/lib/hitimes/version.rb +8 -0
  38. data/spec/hitimes_spec.rb +24 -0
  39. data/spec/interval_spec.rb +136 -0
  40. data/spec/metric_spec.rb +28 -0
  41. data/spec/mutex_stats_spec.rb +36 -0
  42. data/spec/paths_spec.rb +11 -0
  43. data/spec/spec_helper.rb +11 -0
  44. data/spec/stats_spec.rb +98 -0
  45. data/spec/timed_metric_spec.rb +155 -0
  46. data/spec/timed_value_metric_spec.rb +171 -0
  47. data/spec/value_metric_spec.rb +108 -0
  48. data/spec/version_spec.rb +7 -0
  49. data/tasks/default.rake +242 -0
  50. data/tasks/extension.rake +38 -0
  51. data/tasks/this.rb +208 -0
  52. metadata +216 -0
@@ -0,0 +1,171 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hitimes::TimedValueMetric do
4
+ before( :each ) do
5
+ @tm = Hitimes::TimedValueMetric.new( 'test-timed-value-metric' )
6
+ end
7
+
8
+ it "knows if it is running or not" do
9
+ @tm.running?.must_equal false
10
+ @tm.start
11
+ @tm.running?.must_equal true
12
+ @tm.stop( 1 )
13
+ @tm.running?.must_equal false
14
+ end
15
+
16
+ it "#split returns the last duration and the timer is still running" do
17
+ @tm.start
18
+ d = @tm.split( 1 )
19
+ @tm.running?.must_equal true
20
+ d.must_be :>, 0
21
+ @tm.value_stats.count.must_equal 1
22
+ @tm.timed_stats.count.must_equal 1
23
+ @tm.duration.must_equal d
24
+ end
25
+
26
+ it "#stop returns false if called more than once in a row" do
27
+ @tm.start
28
+ @tm.stop( 1 ).must_be :>, 0
29
+ @tm.stop( 1 ).must_equal false
30
+ end
31
+
32
+ it "does not count a currently running interval as an interval in calculations" do
33
+ @tm.start
34
+ @tm.value_stats.count.must_equal 0
35
+ @tm.timed_stats.count.must_equal 0
36
+ @tm.split( 1 )
37
+ @tm.value_stats.count.must_equal 1
38
+ @tm.timed_stats.count.must_equal 1
39
+ end
40
+
41
+ it "#split called on a stopped timer does nothing" do
42
+ @tm.start
43
+ @tm.stop( 1 )
44
+ @tm.split( 1 ).must_equal false
45
+ end
46
+
47
+ it "calculates the mean of the durations" do
48
+ 3.times { |x| @tm.start ; sleep 0.05 ; @tm.stop(x) }
49
+ @tm.timed_stats.mean.must_be_close_to(0.05, 0.01)
50
+ @tm.value_stats.mean.must_equal 1.00
51
+ end
52
+
53
+ it "calculates the rate of the counts " do
54
+ 5.times { |x| @tm.start ; sleep 0.05 ; @tm.stop( x ) }
55
+ @tm.rate.must_be_close_to(40.0, 1.0)
56
+ end
57
+
58
+
59
+ it "calculates the stddev of the durations" do
60
+ 3.times { |x| @tm.start ; sleep(0.05 * x) ; @tm.stop(x) }
61
+ @tm.timed_stats.stddev.must_be_close_to(0.05, 0.001)
62
+ @tm.value_stats.stddev.must_equal 1.0
63
+ end
64
+
65
+ it "returns 0.0 for stddev if there is no data" do
66
+ @tm.timed_stats.stddev.must_equal 0.0
67
+ @tm.value_stats.stddev.must_equal 0.0
68
+ end
69
+
70
+ it "keeps track of the min value" do
71
+ 3.times { |x| @tm.start ; sleep 0.05 ; @tm.stop( x ) }
72
+ @tm.timed_stats.min.must_be_close_to( 0.05, 0.003 )
73
+ @tm.value_stats.min.must_equal 0
74
+ end
75
+
76
+ it "keeps track of the max value" do
77
+ 3.times { |x| @tm.start ; sleep 0.05 ; @tm.stop( x ) }
78
+ @tm.timed_stats.max.must_be_close_to( 0.05, 0.003 )
79
+ @tm.value_stats.max.must_equal 2
80
+ end
81
+
82
+ it "keeps track of the sum value" do
83
+ 3.times { |x| @tm.start ; sleep 0.05 ; @tm.stop( x ) }
84
+ @tm.timed_stats.sum.must_be_close_to( 0.15, 0.01 )
85
+ @tm.value_stats.sum.must_equal 3
86
+ end
87
+
88
+ it "keeps track of the sum of squares value" do
89
+ 3.times { |x| @tm.start ; sleep 0.05 ; @tm.stop( x ) }
90
+ @tm.timed_stats.sumsq.must_be_close_to(0.0075, 0.0005)
91
+ @tm.value_stats.sumsq.must_equal 5
92
+ end
93
+
94
+ it "keeps track of the minimum start time of all the intervals" do
95
+ f1 = Time.now.gmtime.to_f * 1000000
96
+ 5.times { @tm.start ; sleep 0.05 ; @tm.stop( 1 ) }
97
+ f2 = Time.now.gmtime.to_f * 1000000
98
+ @tm.sampling_start_time.must_be :>=, f1
99
+ @tm.sampling_start_time.must_be :<, f2
100
+ # distance from now to start time should be greater than the distance from
101
+ # the start to the min start_time
102
+ (f2 - @tm.sampling_start_time).must_be :>, ( @tm.sampling_start_time - f1 )
103
+ end
104
+
105
+ it "keeps track of the last stop time of all the intervals" do
106
+ f1 = Time.now.gmtime.to_f * 1_000_000
107
+ 5.times { @tm.start ; sleep 0.05 ; @tm.stop( 1 ) }
108
+ sleep 0.05
109
+ f2 = Time.now.gmtime.to_f * 1_000_000
110
+ @tm.sampling_stop_time.must_be :>, f1
111
+ @tm.sampling_stop_time.must_be :<=, f2
112
+ # distance from now to max stop time time should be less than the distance
113
+ # from the start to the max stop time
114
+ (f2 - @tm.sampling_stop_time).must_be :<, ( @tm.sampling_stop_time - f1 )
115
+ end
116
+
117
+ it "can create an already running timer" do
118
+ t = Hitimes::TimedValueMetric.now( 'already-running' )
119
+ t.running?.must_equal true
120
+ end
121
+
122
+ it "can measure a block of code from an instance" do
123
+ t = Hitimes::TimedValueMetric.new( 'measure a block' )
124
+ 3.times { t.measure( 1 ) { sleep 0.05 } }
125
+ t.duration.must_be_close_to(0.15, 0.004)
126
+ t.timed_stats.count.must_equal 3
127
+ t.value_stats.count.must_equal 3
128
+ end
129
+
130
+ it "returns the value of the block when measuring" do
131
+ t = Hitimes::TimedValueMetric.new( 'measure a block' )
132
+ x = t.measure( 42 ) { sleep 0.05; 42 }
133
+ t.duration.must_be_close_to(0.05, 0.002)
134
+ x.must_equal 42
135
+ end
136
+
137
+ describe "#to_hash" do
138
+
139
+ it "has name value" do
140
+ h = @tm.to_hash
141
+ h['name'].must_equal "test-timed-value-metric"
142
+ end
143
+
144
+ it "has an empty has for additional_data" do
145
+ h = @tm.to_hash
146
+ h['additional_data'].must_equal Hash.new
147
+ h['additional_data'].size.must_equal 0
148
+ end
149
+
150
+ it "has a rate" do
151
+ 5.times { |x| @tm.start ; sleep 0.05 ; @tm.stop( x ) }
152
+ h = @tm.to_hash
153
+ h['rate'].must_be_close_to(40.0, 1.0)
154
+ end
155
+
156
+ it "has a unit_count" do
157
+ 5.times { |x| @tm.start ; sleep 0.05 ; @tm.stop( x ) }
158
+ h = @tm.to_hash
159
+ h['unit_count'].must_equal 10
160
+ end
161
+
162
+ fields = %w[ name additional_data sampling_start_time sampling_stop_time value_stats timed_stats rate unit_count ]
163
+ fields.each do |f|
164
+ it "has a value for #{f}" do
165
+ 3.times { |x| @tm.measure(x) { sleep 0.001 } }
166
+ h = @tm.to_hash
167
+ h[f].wont_be_nil
168
+ end
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,108 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hitimes::ValueMetric do
4
+ before( :each ) do
5
+ @metric = Hitimes::ValueMetric.new( "testing" )
6
+ 10.times { |x| @metric.measure( x ) }
7
+ end
8
+
9
+ it 'has a name' do
10
+ @metric.name.must_equal "testing"
11
+ end
12
+
13
+ it "has associated data from initialization" do
14
+ m = Hitimes::ValueMetric.new( "more-data", 'foo' => 'bar', 'this' => 'that' )
15
+ m.additional_data['foo'].must_equal 'bar'
16
+ m.additional_data['this'].must_equal 'that'
17
+
18
+ m = Hitimes::ValueMetric.new( "more-data", { 'foo' => 'bar', 'this' => 'that' } )
19
+ m.additional_data['foo'].must_equal 'bar'
20
+ m.additional_data['this'].must_equal 'that'
21
+ end
22
+
23
+ it "calculates the mean of the measurements" do
24
+ @metric.mean.must_equal 4.5
25
+ end
26
+
27
+ it "calculates the stddev of the measurements" do
28
+ @metric.stddev.must_be :>, 0.0
29
+ end
30
+
31
+ it "returns 0.0 for stddev if there is no data" do
32
+ m = Hitimes::ValueMetric.new('0-data')
33
+ m.stddev.must_equal 0.0
34
+ end
35
+
36
+ it "keeps track of the sum of data" do
37
+ @metric.sum.must_equal 45.0
38
+ end
39
+
40
+ it "keeps track of the sum of squars of data" do
41
+ @metric.sumsq.must_equal 285.0
42
+ end
43
+
44
+ it "retuns 0.0 for mean if there is no data" do
45
+ Hitimes::ValueMetric.new('0-data').mean.must_equal 0.0
46
+ end
47
+
48
+ it "keeps track of the min value" do
49
+ @metric.min.must_equal 0
50
+ end
51
+
52
+ it "keeps track of the max value" do
53
+ @metric.max.must_equal 9
54
+ end
55
+
56
+ it "keeps track of the first start time of all the measurements" do
57
+ m = Hitimes::ValueMetric.new( "first-start-time" )
58
+ f1 = Time.now.gmtime.to_f * 1_000_000
59
+ 10.times{ |x| m.measure( x ); sleep 0.1 }
60
+ f2 = Time.now.gmtime.to_f * 1_000_000
61
+ m.sampling_start_time.must_be :>=, f1
62
+ m.sampling_start_time.must_be :<, f2
63
+ # distance from now to start time should be greater than the distance from
64
+ # the start to the min start_time
65
+ (f2 - m.sampling_start_time).must_be :>, ( m.sampling_start_time - f1 )
66
+ end
67
+
68
+ it "keeps track of the last stop time of all the intervals" do
69
+ m = Hitimes::ValueMetric.new( "last-stop-time" )
70
+ f1 = Time.now.gmtime.to_f * 1_000_000
71
+ 10.times {|x| m.measure( x ); sleep 0.1 }
72
+ f2 = Time.now.gmtime.to_f * 1_000_000
73
+ m.sampling_stop_time.must_be :>, f1
74
+ m.sampling_stop_time.must_be :<=, f2
75
+ # distance from now to max stop time time should be less than the distance
76
+ # from the start to the max stop time
77
+ (f2 - m.sampling_stop_time).must_be :<, ( m.sampling_stop_time - f1 )
78
+ end
79
+
80
+ describe "#to_hash" do
81
+
82
+ it "has name value" do
83
+ h = @metric.to_hash
84
+ h['name'].must_equal "testing"
85
+ end
86
+
87
+ it "has an empty has for additional_data" do
88
+ h = @metric.to_hash
89
+ h['additional_data'].must_equal Hash.new
90
+ h['additional_data'].size.must_equal 0
91
+ end
92
+
93
+ it "has the right sum" do
94
+ h = @metric.to_hash
95
+ h['sum'].must_equal 45
96
+ end
97
+
98
+ fields = ::Hitimes::Stats::STATS.dup + %w[ name additional_data sampling_start_time sampling_stop_time ]
99
+ fields = fields - [ 'rate' ]
100
+ fields.each do |f|
101
+ it "has a value for #{f}" do
102
+ h = @metric.to_hash
103
+ h[f].wont_be_nil
104
+ end
105
+ end
106
+ end
107
+ end
108
+
@@ -0,0 +1,7 @@
1
+ require "spec_helper"
2
+
3
+ describe "Hitimes::Version" do
4
+ it "should be accessable as a constant" do
5
+ Hitimes::VERSION.must_match(/\d+\.\d+\.\d+/)
6
+ end
7
+ end
@@ -0,0 +1,242 @@
1
+ # vim: syntax=ruby
2
+ require 'rake/clean'
3
+ require 'digest'
4
+ #------------------------------------------------------------------------------
5
+ # If you want to Develop on this project just run 'rake develop' and you'll
6
+ # have all you need to get going. If you want to use bundler for development,
7
+ # then run 'rake develop:using_bundler'
8
+ #------------------------------------------------------------------------------
9
+ namespace :develop do
10
+
11
+ # Install all the development and runtime dependencies of this gem using the
12
+ # gemspec.
13
+ task :default => 'Gemfile' do
14
+ require 'rubygems/dependency_installer'
15
+ installer = ::Gem::DependencyInstaller.new
16
+ puts "Installing bundler..."
17
+ installer.install 'bundler'
18
+ sh 'bundle install'
19
+ puts "\n\nNow run 'rake test'"
20
+ end
21
+
22
+ # Create a Gemfile that just references the gemspec
23
+ file 'Gemfile' => :gemspec do
24
+ File.open( "Gemfile", "w+" ) do |f|
25
+ f.puts "# DO NOT EDIT - This file is automatically generated"
26
+ f.puts "# Make changes to Manifest.txt and/or Rakefile and regenerate"
27
+ f.puts 'source "https://rubygems.org"'
28
+ f.puts 'gemspec'
29
+ end
30
+ end
31
+ end
32
+ desc "Bootstrap development"
33
+ task :develop => "develop:default"
34
+
35
+ #------------------------------------------------------------------------------
36
+ # Minitest - standard TestTask
37
+ #------------------------------------------------------------------------------
38
+ begin
39
+ require 'rake/testtask'
40
+ Rake::TestTask.new( :test ) do |t|
41
+ t.ruby_opts = %w[ -w ]
42
+ t.libs = %w[ lib spec test ]
43
+ t.pattern = "{test,spec}/**/{test_*,*_spec}.rb"
44
+ end
45
+
46
+ task :test_requirements
47
+ task :test => :test_requirements
48
+ task :default => :test
49
+ rescue LoadError
50
+ This.task_warning( 'test' )
51
+ end
52
+
53
+ #------------------------------------------------------------------------------
54
+ # RDoc - standard rdoc rake task, although we must make sure to use a more
55
+ # recent version of rdoc since it is the one that has 'tomdoc' markup
56
+ #------------------------------------------------------------------------------
57
+ begin
58
+ gem 'rdoc' # otherwise we get the wrong task from stdlib
59
+ require 'rdoc/task'
60
+ RDoc::Task.new do |t|
61
+ t.markup = 'tomdoc'
62
+ t.rdoc_dir = 'doc'
63
+ t.main = 'README.md'
64
+ t.title = "#{This.name} #{This.version}"
65
+ t.rdoc_files.include( FileList['*.{rdoc,md,txt}'], FileList['ext/**/*.c'],
66
+ FileList['lib/**/*.rb'] )
67
+ end
68
+ rescue StandardError, LoadError
69
+ This.task_warning( 'rdoc' )
70
+ end
71
+
72
+ #------------------------------------------------------------------------------
73
+ # Coverage - optional code coverage, rcov for 1.8 and simplecov for 1.9, so
74
+ # for the moment only rcov is listed.
75
+ #------------------------------------------------------------------------------
76
+ begin
77
+ require 'simplecov'
78
+ desc 'Run tests with code coverage'
79
+ task :coverage do
80
+ ENV['COVERAGE'] = 'true'
81
+ Rake::Task[:test].execute
82
+ end
83
+ CLOBBER << 'coverage' if File.directory?( 'coverage' )
84
+ rescue LoadError
85
+ This.task_warning( 'simplecov' )
86
+ end
87
+
88
+ #------------------------------------------------------------------------------
89
+ # Manifest - We want an explicit list of thos files that are to be packaged in
90
+ # the gem. Most of this is from Hoe.
91
+ #------------------------------------------------------------------------------
92
+ namespace 'manifest' do
93
+ desc "Check the manifest"
94
+ task :check => :clean do
95
+ files = FileList["**/*", ".*"].exclude( This.exclude_from_manifest ).to_a.sort
96
+ files = files.select{ |f| File.file?( f ) }
97
+
98
+ tmp = "Manifest.tmp"
99
+ File.open( tmp, 'w' ) do |f|
100
+ f.puts files.join("\n")
101
+ end
102
+
103
+ begin
104
+ sh "diff -du Manifest.txt #{tmp}"
105
+ ensure
106
+ rm tmp
107
+ end
108
+ puts "Manifest looks good"
109
+ end
110
+
111
+ desc "Generate the manifest"
112
+ task :generate => :clean do
113
+ files = %x[ git ls-files ].split("\n").sort
114
+ files.reject! { |f| f =~ This.exclude_from_manifest }
115
+ File.open( "Manifest.txt", "w" ) do |f|
116
+ f.puts files.join("\n")
117
+ end
118
+ end
119
+ end
120
+
121
+ #------------------------------------------------------------------------------
122
+ # Fixme - look for fixmes and report them
123
+ #------------------------------------------------------------------------------
124
+ namespace :fixme do
125
+ task :default => 'manifest:check' do
126
+ This.manifest.each do |file|
127
+ next if file == __FILE__
128
+ next unless file =~ %r/(txt|rb|md|rdoc|css|html|xml|css)\Z/
129
+ puts "FIXME: Rename #{file}" if file =~ /fixme/i
130
+ IO.readlines( file ).each_with_index do |line, idx|
131
+ prefix = "FIXME: #{file}:#{idx+1}".ljust(42)
132
+ puts "#{prefix} => #{line.strip}" if line =~ /fixme/i
133
+ end
134
+ end
135
+ end
136
+
137
+ def fixme_project_root
138
+ This.project_path( '../fixme' )
139
+ end
140
+
141
+ def fixme_project_path( subtree )
142
+ fixme_project_root.join( subtree )
143
+ end
144
+
145
+ def local_fixme_files
146
+ This.manifest.select { |p| p =~ %r|^tasks/| }
147
+ end
148
+
149
+ def outdated_fixme_files
150
+ local_fixme_files.select do |local|
151
+ upstream = fixme_project_path( local )
152
+ upstream.exist? &&
153
+ ( Digest::SHA256.file( local ) != Digest::SHA256.file( upstream ) )
154
+ end
155
+ end
156
+
157
+ def fixme_up_to_date?
158
+ outdated_fixme_files.empty?
159
+ end
160
+
161
+ desc "See if the fixme tools are outdated"
162
+ task :outdated => :release_check do
163
+ if fixme_up_to_date? then
164
+ puts "Fixme files are up to date."
165
+ else
166
+ outdated_fixme_files.each do |f|
167
+ puts "#{f} is outdated"
168
+ end
169
+ end
170
+ end
171
+
172
+ desc "Update outdated fixme files"
173
+ task :update => :release_check do
174
+ if fixme_up_to_date? then
175
+ puts "Fixme files are already up to date."
176
+ else
177
+ puts "Updating fixme files:"
178
+ outdated_fixme_files.each do |local|
179
+ upstream = fixme_project_path( local )
180
+ puts " * #{local}"
181
+ FileUtils.cp( upstream, local )
182
+ end
183
+ puts "Use your git commands as appropriate."
184
+ end
185
+ end
186
+ end
187
+ desc "Look for fixmes and report them"
188
+ task :fixme => "fixme:default"
189
+
190
+ #------------------------------------------------------------------------------
191
+ # Gem Specification
192
+ #------------------------------------------------------------------------------
193
+ # Really this is only here to support those who use bundler
194
+ desc "Build the #{This.name}.gemspec file"
195
+ task :gemspec do
196
+ File.open( This.gemspec_file, "wb+" ) do |f|
197
+ f.puts "# DO NOT EDIT - This file is automatically generated"
198
+ f.puts "# Make changes to Manifest.txt and/or Rakefile and regenerate"
199
+ f.write This.platform_gemspec.to_ruby
200
+ end
201
+ end
202
+
203
+ # .rbc files from ruby 2.0
204
+ CLOBBER << FileList["**/*.rbc"]
205
+
206
+ # The standard gem packaging task, everyone has it.
207
+ require 'rubygems/package_task'
208
+ ::Gem::PackageTask.new( This.platform_gemspec ) do
209
+ # nothing
210
+ end
211
+
212
+ #------------------------------------------------------------------------------
213
+ # Release - the steps we go through to do a final release, this is pulled from
214
+ # a compbination of mojombo's rakegem, hoe and hoe-git
215
+ #
216
+ # 1) make sure we are on the master branch
217
+ # 2) make sure there are no uncommitted items
218
+ # 3) check the manifest and make sure all looks good
219
+ # 4) build the gem
220
+ # 5) do an empty commit to have the commit message of the version
221
+ # 6) tag that commit as the version
222
+ # 7) push master
223
+ # 8) push the tag
224
+ # 7) pus the gem
225
+ #------------------------------------------------------------------------------
226
+ task :release_check do
227
+ unless `git branch` =~ /^\* master$/
228
+ abort "You must be on the master branch to release!"
229
+ end
230
+ unless `git status` =~ /^nothing to commit/m
231
+ abort "Nope, sorry, you have unfinished business"
232
+ end
233
+ end
234
+
235
+ desc "Create tag v#{This.version}, build and push #{This.platform_gemspec.full_name} to rubygems.org"
236
+ task :release => [ :release_check, 'manifest:check', :gem ] do
237
+ sh "git commit --allow-empty -a -m 'Release #{This.version}'"
238
+ sh "git tag -a -m 'v#{This.version}' v#{This.version}"
239
+ sh "git push origin master"
240
+ sh "git push origin v#{This.version}"
241
+ sh "gem push pkg/#{This.platform_gemspec.full_name}.gem"
242
+ end