service_template 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.rubocop.yml +23 -0
  4. data/.travis.yml +13 -0
  5. data/CHANGELOG.md +64 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE +24 -0
  8. data/README.md +217 -0
  9. data/Rakefile +9 -0
  10. data/bin/service_template +5 -0
  11. data/lib/service_template.rb +55 -0
  12. data/lib/service_template/active_record_extensions/notifications_subscriber.rb +17 -0
  13. data/lib/service_template/active_record_extensions/seeder.rb +14 -0
  14. data/lib/service_template/active_record_extensions/stats.rb +37 -0
  15. data/lib/service_template/authentication.rb +8 -0
  16. data/lib/service_template/cli.rb +111 -0
  17. data/lib/service_template/deploy.rb +98 -0
  18. data/lib/service_template/gem_dependency.rb +37 -0
  19. data/lib/service_template/generators.rb +3 -0
  20. data/lib/service_template/generators/api_generator.rb +30 -0
  21. data/lib/service_template/generators/readme_generator.rb +47 -0
  22. data/lib/service_template/generators/scaffold_generator.rb +29 -0
  23. data/lib/service_template/generators/templates/api/app/apis/%name_tableize%_api.rb.tt +40 -0
  24. data/lib/service_template/generators/templates/api/app/models/%name_underscore%.rb.tt +2 -0
  25. data/lib/service_template/generators/templates/api/app/representers/%name_underscore%_representer.rb.tt +4 -0
  26. data/lib/service_template/generators/templates/api/spec/apis/%name_tableize%_api_spec.rb.tt +16 -0
  27. data/lib/service_template/generators/templates/api/spec/models/%name_underscore%_spec.rb.tt +9 -0
  28. data/lib/service_template/generators/templates/readme/README.md.tt +55 -0
  29. data/lib/service_template/generators/templates/readme/spec/docs/readme_spec.rb +7 -0
  30. data/lib/service_template/generators/templates/scaffold/.env.development.tt +9 -0
  31. data/lib/service_template/generators/templates/scaffold/.env.test.tt +10 -0
  32. data/lib/service_template/generators/templates/scaffold/.gitignore.tt +13 -0
  33. data/lib/service_template/generators/templates/scaffold/.rubocop.yml +24 -0
  34. data/lib/service_template/generators/templates/scaffold/.ruby-version.tt +1 -0
  35. data/lib/service_template/generators/templates/scaffold/Gemfile.tt +29 -0
  36. data/lib/service_template/generators/templates/scaffold/README.md +3 -0
  37. data/lib/service_template/generators/templates/scaffold/Rakefile +21 -0
  38. data/lib/service_template/generators/templates/scaffold/app.rb +19 -0
  39. data/lib/service_template/generators/templates/scaffold/app/apis/application_api.rb +9 -0
  40. data/lib/service_template/generators/templates/scaffold/app/apis/hello_api.rb.tt +10 -0
  41. data/lib/service_template/generators/templates/scaffold/config.ru.tt +21 -0
  42. data/lib/service_template/generators/templates/scaffold/config/database.yml.tt +19 -0
  43. data/lib/service_template/generators/templates/scaffold/config/initializers/active_record.rb +5 -0
  44. data/lib/service_template/generators/templates/scaffold/db/schema.rb +11 -0
  45. data/lib/service_template/generators/templates/scaffold/lib/.keep +0 -0
  46. data/lib/service_template/generators/templates/scaffold/log/.keep +0 -0
  47. data/lib/service_template/generators/templates/scaffold/spec/apis/hello_api_spec.rb.tt +17 -0
  48. data/lib/service_template/generators/templates/scaffold/spec/factories/.gitkeep +0 -0
  49. data/lib/service_template/generators/templates/scaffold/spec/spec_helper.rb +47 -0
  50. data/lib/service_template/grape_extenders.rb +30 -0
  51. data/lib/service_template/grape_extensions/error_formatter.rb +18 -0
  52. data/lib/service_template/grape_extensions/grape_helpers.rb +27 -0
  53. data/lib/service_template/identity.rb +45 -0
  54. data/lib/service_template/json_error.rb +24 -0
  55. data/lib/service_template/logger/log_transaction.rb +17 -0
  56. data/lib/service_template/logger/logger.rb +42 -0
  57. data/lib/service_template/logger/parseable.rb +37 -0
  58. data/lib/service_template/middleware/app_monitor.rb +17 -0
  59. data/lib/service_template/middleware/authentication.rb +32 -0
  60. data/lib/service_template/middleware/database_stats.rb +15 -0
  61. data/lib/service_template/middleware/logger.rb +67 -0
  62. data/lib/service_template/middleware/request_stats.rb +42 -0
  63. data/lib/service_template/output_formatters/entity.rb +15 -0
  64. data/lib/service_template/output_formatters/include_nil.rb +16 -0
  65. data/lib/service_template/output_formatters/json_api_representer.rb +9 -0
  66. data/lib/service_template/param_sanitizer.rb +30 -0
  67. data/lib/service_template/rspec_extensions/response_helpers.rb +46 -0
  68. data/lib/service_template/setup.rb +36 -0
  69. data/lib/service_template/sortable_api.rb +17 -0
  70. data/lib/service_template/stats.rb +43 -0
  71. data/lib/service_template/stats_d_timer.rb +26 -0
  72. data/lib/service_template/version.rb +45 -0
  73. data/lib/tasks/deploy.rake +11 -0
  74. data/lib/tasks/routes.rake +11 -0
  75. data/service_template.gemspec +42 -0
  76. data/spec/active_record_extensions/filter_by_hash_spec.rb +23 -0
  77. data/spec/active_record_extensions/seeder_spec.rb +13 -0
  78. data/spec/authentication_spec.rb +17 -0
  79. data/spec/deprecations/application_api_spec.rb +19 -0
  80. data/spec/deprecations/entity_spec.rb +9 -0
  81. data/spec/deprecations/filter_by_hash_spec.rb +9 -0
  82. data/spec/deprecations/napa_setup_spec.rb +52 -0
  83. data/spec/generators/api_generator_spec.rb +63 -0
  84. data/spec/generators/migration_generator_spec.rb +105 -0
  85. data/spec/generators/readme_generator_spec.rb +35 -0
  86. data/spec/generators/scaffold_generator_spec.rb +90 -0
  87. data/spec/grape_extenders_spec.rb +50 -0
  88. data/spec/grape_extensions/error_formatter_spec.rb +29 -0
  89. data/spec/grape_extensions/include_nil_spec.rb +23 -0
  90. data/spec/identity_spec.rb +50 -0
  91. data/spec/json_error_spec.rb +33 -0
  92. data/spec/logger/log_transaction_spec.rb +34 -0
  93. data/spec/logger/logger_spec.rb +14 -0
  94. data/spec/logger/parseable_spec.rb +16 -0
  95. data/spec/middleware/authentication_spec.rb +54 -0
  96. data/spec/middleware/database_stats_spec.rb +64 -0
  97. data/spec/middleware/request_stats_spec.rb +21 -0
  98. data/spec/sortable_api_spec.rb +56 -0
  99. data/spec/spec_helper.rb +45 -0
  100. data/spec/stats_d_timer_spec.rb +23 -0
  101. data/spec/stats_spec.rb +66 -0
  102. data/spec/version_spec.rb +40 -0
  103. data/tasks/spec.rake +9 -0
  104. data/tasks/version.rake +51 -0
  105. metadata +456 -0
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+ require 'service_template/logger/logger'
3
+
4
+ describe ServiceTemplate::Logger do
5
+ context '#response' do
6
+ it 'returns response in the expected format' do
7
+ response = ServiceTemplate::Logger.response('foo', 'bar', 'baz')
8
+
9
+ expect(response[:response][:status]).to eq('foo')
10
+ expect(response[:response][:headers]).to eq('bar')
11
+ expect(response[:response][:response]).to eq('baz')
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,16 @@
1
+ require 'spec_helper'
2
+ require 'service_template/logger/parseable'
3
+
4
+ describe Logging::Layouts::Parseable do
5
+ context '#format_obj' do
6
+ it 'formats text as an object' do
7
+ p = Logging::Layouts::Parseable.new
8
+ expect(p.format_obj('foobar')).to eq({ text: 'foobar' })
9
+ end
10
+
11
+ it 'does not reformat objects' do
12
+ p = Logging::Layouts::Parseable.new
13
+ expect(p.format_obj({ foo: :bar })).to eq({ foo: :bar })
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+ require 'service_template/middleware/authentication'
3
+ require 'pry'
4
+
5
+ describe ServiceTemplate::Identity do
6
+ before do
7
+ ENV['HEADER_PASSWORDS'] = 'foo'
8
+ end
9
+
10
+ context 'Authenticated Request' do
11
+ it 'allows the request to continue if given a correct password header' do
12
+ app = lambda { |env| [200, {'Content-Type' => 'application/json'}, Array.new] }
13
+ middleware = ServiceTemplate::Middleware::Authentication.new(app)
14
+ env = Rack::MockRequest.env_for('/test', {'HTTP_PASSWORD' => 'foo'})
15
+ status, headers, body = middleware.call(env)
16
+
17
+ expect(status).to eq(200)
18
+ end
19
+ end
20
+
21
+ context 'Failed Authentication Request' do
22
+ it 'returns an error message if the Password header is not supplied' do
23
+ app = lambda { |env| [200, {'Content-Type' => 'application/json'}, Array.new] }
24
+ middleware = ServiceTemplate::Middleware::Authentication.new(app)
25
+ env = Rack::MockRequest.env_for('/test')
26
+ status, headers, body = middleware.call(env)
27
+
28
+ expect(status).to eq(401)
29
+ expect(body).to eq([ServiceTemplate::JsonError.new('bad_password', 'bad password').to_json])
30
+ end
31
+
32
+ it 'returns an error message if an incorrect Password header is supplied' do
33
+ app = lambda { |env| [200, {'Content-Type' => 'application/json'}, Array.new] }
34
+ middleware = ServiceTemplate::Middleware::Authentication.new(app)
35
+ env = Rack::MockRequest.env_for('/test', {'HTTP_PASSWORD' => 'incorrect'})
36
+ status, headers, body = middleware.call(env)
37
+
38
+ expect(status).to eq(401)
39
+ expect(body).to eq([ServiceTemplate::JsonError.new('bad_password', 'bad password').to_json])
40
+ end
41
+
42
+ it 'returns an error message if HEADER_PASSWORDS is not configured' do
43
+ ENV['HEADER_PASSWORDS'] = nil
44
+
45
+ app = lambda { |env| [200, {'Content-Type' => 'application/json'}, Array.new] }
46
+ middleware = ServiceTemplate::Middleware::Authentication.new(app)
47
+ env = Rack::MockRequest.env_for('/test', {'HTTP_PASSWORD' => 'incorrect'})
48
+ status, headers, body = middleware.call(env)
49
+
50
+ expect(status).to eq(401)
51
+ expect(body).to eq([ServiceTemplate::JsonError.new('not_configured', 'password not configured').to_json])
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,64 @@
1
+ require 'active_record'
2
+ require 'spec_helper'
3
+ require 'service_template/active_record_extensions/stats'
4
+
5
+ # Delete any prevous instantiations of the emitter and set valid statsd env vars
6
+ ServiceTemplate::Stats.emitter = nil
7
+ ENV['STATSD_HOST'] = 'localhost'
8
+ ENV['STATSD_PORT'] = '8125'
9
+
10
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
11
+
12
+ ActiveRecord::Schema.define(version: 1) do
13
+ create_table :foos do |t|
14
+ t.string :word
15
+ end
16
+ end
17
+
18
+ class Foo < ActiveRecord::Base
19
+ end
20
+
21
+ describe ServiceTemplate::Middleware::DatabaseStats do
22
+ before do
23
+ # Delete any prevous instantiations of the emitter and set valid statsd env vars
24
+ ServiceTemplate::Stats.emitter = nil
25
+ ENV['STATSD_HOST'] = 'localhost'
26
+ ENV['STATSD_PORT'] = '8125'
27
+
28
+ @foo = Foo.create(word: 'bar')
29
+ end
30
+
31
+ after do
32
+ middleware = ServiceTemplate::Middleware::DatabaseStats.new(@app)
33
+ env = Rack::MockRequest.env_for('/test/path')
34
+ middleware.call(env)
35
+ end
36
+
37
+ it 'should send a query_time for an insert' do
38
+ allow(ServiceTemplate::Stats.emitter).to receive(:timing).with('sql.query_time', an_instance_of(Float))
39
+ allow(ServiceTemplate::Stats.emitter).to receive(:timing).with('sql.table.foos.insert.query_time', an_instance_of(Float))
40
+
41
+ @app = lambda { |env| [200, { 'Content-Type' => 'application/json' }, Foo.create(word: 'baz')] }
42
+ end
43
+
44
+ it 'should send a query_time for a select' do
45
+ allow(ServiceTemplate::Stats.emitter).to receive(:timing).with('sql.query_time', an_instance_of(Float))
46
+ allow(ServiceTemplate::Stats.emitter).to receive(:timing).with('sql.table.foos.select.query_time', an_instance_of(Float))
47
+
48
+ @app = lambda { |env| [200, { 'Content-Type' => 'application/json' }, Foo.first] }
49
+ end
50
+
51
+ it 'should send a query_time for a delete' do
52
+ allow(ServiceTemplate::Stats.emitter).to receive(:timing).with('sql.query_time', an_instance_of(Float))
53
+ allow(ServiceTemplate::Stats.emitter).to receive(:timing).with('sql.table.foos.delete.query_time', an_instance_of(Float))
54
+
55
+ @app = lambda { |env| [200, { 'Content-Type' => 'application/json' }, @foo.delete ] }
56
+ end
57
+
58
+ it 'should send a query_time for an update' do
59
+ allow(ServiceTemplate::Stats.emitter).to receive(:timing).with('sql.query_time', an_instance_of(Float))
60
+ allow(ServiceTemplate::Stats.emitter).to receive(:timing).with('sql.table.foos.update.query_time', an_instance_of(Float))
61
+
62
+ @app = lambda { |env| [200, { 'Content-Type' => 'application/json' }, @foo.update_attributes(word: 'baz') ] }
63
+ end
64
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+ require 'service_template/middleware/request_stats'
3
+
4
+ describe ServiceTemplate::Middleware::RequestStats do
5
+ before do
6
+ # Delete any prevous instantiations of the emitter and set valid statsd env vars
7
+ ServiceTemplate::Stats.emitter = nil
8
+ ENV['STATSD_HOST'] = 'localhost'
9
+ ENV['STATSD_PORT'] = '8125'
10
+ end
11
+
12
+ it 'should send the api_response_time' do
13
+ expect(ServiceTemplate::Stats.emitter).to receive(:timing).with('response_time', an_instance_of(Float))
14
+ expect(ServiceTemplate::Stats.emitter).to receive(:timing).with('path.get.test.path.response_time', an_instance_of(Float))
15
+ app = lambda { |env| [200, { 'Content-Type' => 'application/json'}, Array.new] }
16
+ middleware = ServiceTemplate::Middleware::RequestStats.new(app)
17
+ env = Rack::MockRequest.env_for('/test/path')
18
+ middleware.call(env)
19
+ end
20
+
21
+ end
@@ -0,0 +1,56 @@
1
+ require 'active_record'
2
+ require 'spec_helper'
3
+ require 'service_template/sortable_api'
4
+
5
+ describe "SortableApi" do
6
+ describe "#sort_from_params" do
7
+ before do
8
+ build_model :foos do
9
+ integer :param1
10
+ integer :param2
11
+ end
12
+
13
+ @object1 = Foo.create(param1: 2, param2: 1)
14
+ @object2 = Foo.create(param1: 2, param2: 3)
15
+ @object3 = Foo.create(param1: 3, param2: 5)
16
+ @object4 = Foo.create(param1: 1, param2: 3)
17
+ @object5 = Foo.create(param1: 1, param2: 1)
18
+
19
+ @api = Object.new
20
+ @api.extend(ServiceTemplate::SortableApi)
21
+ @foos = Foo.scoped
22
+ end
23
+
24
+ it "returns the sortable objects if sort_param is nil" do
25
+ expect(@api.sort_from_params(@foos, nil)).to eq(@foos)
26
+ end
27
+
28
+ it "sorts by a given parameter" do
29
+ sorted = @api.sort_from_params(@foos, "param1")
30
+ expect(sorted.last).to eq(@object3)
31
+ expect(sorted.to_sql).to end_with("ORDER BY param1")
32
+ end
33
+
34
+ it "sorts by a given parameter descending if preceded by -" do
35
+ sorted = @api.sort_from_params(@foos, "-param1")
36
+ expect(sorted.first).to eq(@object3)
37
+ expect(sorted.to_sql).to end_with("ORDER BY param1 DESC")
38
+ end
39
+
40
+ it "sorts by multiple parameters in order" do
41
+ sorted = @api.sort_from_params(@foos, "param2,param1")
42
+ expect(sorted.to_a).to eq([@object5, @object1, @object4, @object2, @object3])
43
+ expect(sorted.to_sql).to end_with("ORDER BY param2, param1")
44
+
45
+ alt_sorted = @api.sort_from_params(@foos, "param1,param2")
46
+ expect(alt_sorted.to_a).to eq([@object5, @object4, @object1, @object2, @object3])
47
+ expect(alt_sorted.to_sql).to end_with("ORDER BY param1, param2")
48
+ end
49
+
50
+ it "sorts by multiple parameters, even if descending" do
51
+ sorted = @api.sort_from_params(@foos, "-param2,param1")
52
+ expect(sorted.to_a).to eq([@object3, @object4, @object2, @object5, @object1])
53
+ expect(sorted.to_sql).to end_with("ORDER BY param2 DESC, param1")
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,45 @@
1
+ ENV['RACK_ENV'] = 'test'
2
+
3
+ require 'service_template/setup'
4
+ require 'acts_as_fu'
5
+
6
+ require "codeclimate-test-reporter"
7
+ CodeClimate::TestReporter.start
8
+
9
+ ServiceTemplate.skip_initialization = true
10
+
11
+ require 'service_template'
12
+ require 'service_template/rspec_extensions/response_helpers'
13
+
14
+ # from https://gist.github.com/adamstegman/926858
15
+ RSpec.configure do |config|
16
+ config.include ServiceTemplate::RspecExtensions::ResponseHelpers
17
+
18
+ config.before(:all) { silence_output }
19
+ config.after(:all) { enable_output }
20
+
21
+ config.include ActsAsFu
22
+
23
+ config.before(:each) do
24
+ allow(ServiceTemplate).to receive(:initialize)
25
+ allow(ServiceTemplate::Logger).to receive_message_chain('logger.info').with(:service_template_deprecation_warning)
26
+ end
27
+ end
28
+
29
+ # Redirects stderr and stdout to /dev/null.
30
+ def silence_output
31
+ @orig_stderr = $stderr
32
+ @orig_stdout = $stdout
33
+
34
+ # redirect stderr and stdout to /dev/null
35
+ $stderr = File.new('/dev/null', 'w')
36
+ $stdout = File.new('/dev/null', 'w')
37
+ end
38
+
39
+ # Replace stdout and stderr so anything else is output correctly.
40
+ def enable_output
41
+ $stderr = @orig_stderr
42
+ $stdout = @orig_stdout
43
+ @orig_stderr = nil
44
+ @orig_stdout = nil
45
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+ require 'service_template/stats_d_timer'
3
+
4
+ class FooTimer
5
+ include ServiceTemplate::StatsDTimer
6
+ end
7
+
8
+ describe ServiceTemplate::StatsDTimer do
9
+ before do
10
+ # Delete any prevous instantiations of the emitter
11
+ ServiceTemplate::Stats.emitter = nil
12
+ # Stub out logging since there is no log to output to
13
+ allow(ServiceTemplate::Logger).to receive_message_chain(:logger, :warn)
14
+ end
15
+
16
+ it 'logs a timing event based on how long the block takes' do
17
+ expect(ServiceTemplate::Stats.emitter).to receive(:timing).with('foo', an_instance_of(Float))
18
+ FooTimer.report_time('foo') do
19
+ sleep(0.1)
20
+ end
21
+ end
22
+
23
+ end
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+ require 'service_template/stats'
3
+
4
+ describe ServiceTemplate::Stats do
5
+ before do
6
+ # Delete any prevous instantiations of the emitter
7
+ ServiceTemplate::Stats.emitter = nil
8
+ # Stub out logging since there is no log to output to
9
+ allow(ServiceTemplate::Logger).to receive_message_chain(:logger, :warn)
10
+ end
11
+
12
+ it 'should log an error if StatsD env variables are not configured' do
13
+ ENV['STATSD_HOST'] = nil
14
+ ENV['STATSD_PORT'] = nil
15
+ message = 'StatsD host and port not configured in environment variables, using default settings'
16
+ expect(ServiceTemplate::Logger.logger).to receive(:warn).with(message)
17
+ ServiceTemplate::Stats.emitter
18
+ end
19
+
20
+ it 'should default statsd to localhost port 8125 if env vars are not specified' do
21
+ ENV['STATSD_HOST'] = nil
22
+ ENV['STATSD_PORT'] = nil
23
+ expect(ServiceTemplate::Stats.emitter.host).to eq('127.0.0.1')
24
+ expect(ServiceTemplate::Stats.emitter.port).to eq(8125)
25
+ end
26
+
27
+ it 'should return a StatsD client object' do
28
+ expect(ServiceTemplate::Stats.emitter.class.name).to eq('Statsd')
29
+ end
30
+
31
+ it 'the namespace of the StatsD client object should equal the service name' do
32
+ ENV['SERVICE_NAME'] = 'my-service'
33
+ expect(ServiceTemplate::Stats.emitter.namespace).to eq("my-service.test")
34
+ end
35
+
36
+ it 'should use env variables to set statsd host and port' do
37
+ ENV['STATSD_HOST'] = 'localhost'
38
+ ENV['STATSD_PORT'] = '9000'
39
+ expect(ServiceTemplate::Stats.emitter.host).to eq('localhost')
40
+ expect(ServiceTemplate::Stats.emitter.port).to eq('9000')
41
+ end
42
+
43
+ describe '#namespace' do
44
+ it 'prepends the namespace with the STATSD_API_KEY if present' do
45
+ ENV['STATSD_API_KEY'] = 'foo'
46
+ expect(ServiceTemplate::Stats.namespace).to eq("#{ENV['STATSD_API_KEY']}.#{ServiceTemplate::Identity.name}.test")
47
+ end
48
+
49
+ it 'does not include the STATSD_API_KEY if empty' do
50
+ ENV['STATSD_API_KEY'] = nil
51
+ expect(ServiceTemplate::Stats.namespace).to eq("#{ServiceTemplate::Identity.name}.test")
52
+ end
53
+ end
54
+
55
+ describe '#path_to_key' do
56
+ it 'returns the key string with ids removed and parts joined with dots' do
57
+ method = 'GET'
58
+ path = '/foo/123/bar'
59
+ expect(ServiceTemplate::Stats.path_to_key(method, path)).to eq('get.foo._.bar')
60
+
61
+ method = 'POST'
62
+ path = '/foo'
63
+ expect(ServiceTemplate::Stats.path_to_key(method, path)).to eq('post.foo')
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+ require 'service_template/version'
3
+
4
+ describe ServiceTemplate::Version do
5
+ context '#major_bump' do
6
+ it 'should set the major revision value, and the rest should be 0' do
7
+ stub_const('ServiceTemplate::VERSION', '1.2.3')
8
+ expect(ServiceTemplate::Version.next_major).to eq('2.0.0')
9
+ end
10
+
11
+ it 'should set the major revision value, and the rest should be 0' do
12
+ stub_const('ServiceTemplate::VERSION', '5.0.0')
13
+ expect(ServiceTemplate::Version.next_major).to eq('6.0.0')
14
+ end
15
+ end
16
+
17
+ context '#minor_bump' do
18
+ it 'should set the minor revision value, leaving the major value unchanged and the patch value to 0' do
19
+ stub_const('ServiceTemplate::VERSION', '1.2.3')
20
+ expect(ServiceTemplate::Version.next_minor).to eq('1.3.0')
21
+ end
22
+
23
+ it 'should set the minor revision value, leaving the major value unchanged and the patch value to 0' do
24
+ stub_const('ServiceTemplate::VERSION', '0.5.0')
25
+ expect(ServiceTemplate::Version.next_minor).to eq('0.6.0')
26
+ end
27
+ end
28
+
29
+ context 'patch_bump' do
30
+ it 'should set the patch revision value, leaving the major and minor values unchanged' do
31
+ stub_const('ServiceTemplate::VERSION', '1.2.3')
32
+ expect(ServiceTemplate::Version.next_patch).to eq('1.2.4')
33
+ end
34
+
35
+ it 'should set the patch revision value, leaving the major and minor values unchanged' do
36
+ stub_const('ServiceTemplate::VERSION', '5.5.5')
37
+ expect(ServiceTemplate::Version.next_patch).to eq('5.5.6')
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,9 @@
1
+ desc 'Run the RSpec test suite'
2
+ task :spec do
3
+ sh *%w[
4
+ bundle exec
5
+ rspec --colour
6
+ --format documentation
7
+ --fail-fast
8
+ ]
9
+ end
@@ -0,0 +1,51 @@
1
+ desc "bump the gem version"
2
+ namespace :version do
3
+ namespace :bump do
4
+
5
+ task :major do
6
+ @new_version = ServiceTemplate::Version.next_major
7
+ execute_version_bump
8
+ end
9
+
10
+ task :minor do
11
+ @new_version = ServiceTemplate::Version.next_minor
12
+ execute_version_bump
13
+ end
14
+
15
+ task :patch do
16
+ @new_version = ServiceTemplate::Version.next_patch
17
+ execute_version_bump
18
+ end
19
+
20
+ def execute_version_bump
21
+ if !clean_staging_area?
22
+ system "git status"
23
+ raise "Unclean staging area! Be sure to commit or .gitignore everything first. See `git status` above."
24
+ else
25
+ require 'git'
26
+ git = Git.open('.')
27
+
28
+ write_update
29
+ git.add('lib/service_template/version.rb')
30
+ git.commit("Version bump: #{release_tag}")
31
+ git.add_tag(release_tag)
32
+ git.push(git.remote('upstream'), git.branch, release_tag) if git.remote('upstream')
33
+ puts "Version bumped: #{release_tag}"
34
+ end
35
+ end
36
+
37
+ def write_update
38
+ filedata = File.read('lib/service_template/version.rb')
39
+ changed_filedata = filedata.gsub("VERSION = '#{ServiceTemplate::VERSION}'\n", "VERSION = '#{@new_version}'\n")
40
+ File.open('lib/service_template/version.rb',"w"){|file| file.puts changed_filedata}
41
+ end
42
+
43
+ def clean_staging_area?
44
+ `git ls-files --deleted --modified --others --exclude-standard` == ""
45
+ end
46
+
47
+ def release_tag
48
+ "v#{@new_version}"
49
+ end
50
+ end
51
+ end