napa 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +21 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +172 -0
- data/Rakefile +3 -0
- data/bin/napa +17 -0
- data/lib/generators/scaffold.rb +67 -0
- data/lib/generators/templates/scaffold/.env +6 -0
- data/lib/generators/templates/scaffold/.env.test +7 -0
- data/lib/generators/templates/scaffold/.gitignore.tpl +10 -0
- data/lib/generators/templates/scaffold/Gemfile +28 -0
- data/lib/generators/templates/scaffold/README.md +3 -0
- data/lib/generators/templates/scaffold/Rakefile +8 -0
- data/lib/generators/templates/scaffold/app/apis/hello_api.rb +13 -0
- data/lib/generators/templates/scaffold/app.rb +21 -0
- data/lib/generators/templates/scaffold/config/database.yml +18 -0
- data/lib/generators/templates/scaffold/config/initializers/active_record.rb +5 -0
- data/lib/generators/templates/scaffold/config/middleware/honeybadger.rb +7 -0
- data/lib/generators/templates/scaffold/config.ru +17 -0
- data/lib/generators/templates/scaffold/console +5 -0
- data/lib/generators/templates/scaffold/lib/password_protected_helpers.rb +17 -0
- data/lib/generators/templates/scaffold/spec/apis/hello_api_spec.rb +17 -0
- data/lib/generators/templates/scaffold/spec/factories/.gitkeep +0 -0
- data/lib/generators/templates/scaffold/spec/spec_helper.rb +35 -0
- data/lib/napa/activerecord.rb +21 -0
- data/lib/napa/grape_api.rb +15 -0
- data/lib/napa/identity.rb +38 -0
- data/lib/napa/logger/log_transaction.rb +17 -0
- data/lib/napa/logger/logger.rb +34 -0
- data/lib/napa/middleware/app_monitor.rb +17 -0
- data/lib/napa/middleware/logger.rb +69 -0
- data/lib/napa/version.rb +45 -0
- data/lib/napa.rb +37 -0
- data/lib/tasks/db.rake +87 -0
- data/lib/tasks/deploy.rake +13 -0
- data/lib/tasks/git.rake +50 -0
- data/lib/tasks/routes.rake +9 -0
- data/napa.gemspec +31 -0
- data/spec/identity_spec.rb +50 -0
- data/spec/logger/log_transaction_spec.rb +34 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/version_spec.rb +40 -0
- data/tasks/version.rake +51 -0
- metadata +275 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
module Napa
|
2
|
+
class Logger
|
3
|
+
class << self
|
4
|
+
def name
|
5
|
+
[Napa::Identity.name, Napa::LogTransaction.id].join('-')
|
6
|
+
end
|
7
|
+
|
8
|
+
def logger=(logger)
|
9
|
+
@logger = logger
|
10
|
+
end
|
11
|
+
|
12
|
+
def logger
|
13
|
+
unless @logger
|
14
|
+
Logging.appenders.stdout(
|
15
|
+
'stdout',
|
16
|
+
:layout => Logging.layouts.json
|
17
|
+
)
|
18
|
+
Logging.appenders.file(
|
19
|
+
"log/#{Napa.env}.log",
|
20
|
+
:layout => Logging.layouts.json
|
21
|
+
)
|
22
|
+
|
23
|
+
@logger = Logging.logger["[#{name}]"]
|
24
|
+
unless Napa.env.test?
|
25
|
+
@logger.add_appenders 'stdout'
|
26
|
+
end
|
27
|
+
@logger.add_appenders "log/#{Napa.env}.log"
|
28
|
+
end
|
29
|
+
|
30
|
+
@logger
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Napa
|
2
|
+
class Middleware
|
3
|
+
class AppMonitor
|
4
|
+
def initialize(app)
|
5
|
+
@app = app
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
if env['REQUEST_PATH'] == '/health'
|
10
|
+
[200, {'Content-type' => 'application/json'}, [Napa::Identity.health.to_json]]
|
11
|
+
else
|
12
|
+
@app.call(env)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Napa
|
2
|
+
class Middleware
|
3
|
+
class Logger
|
4
|
+
def initialize(app)
|
5
|
+
@app = app
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
# set transaction_id
|
10
|
+
transaction_id=SecureRandom.uuid
|
11
|
+
|
12
|
+
# log the request
|
13
|
+
Napa::Logger.logger.debug format_request(env)
|
14
|
+
|
15
|
+
# process the request
|
16
|
+
status, headers, body = @app.call(env)
|
17
|
+
|
18
|
+
# log the response
|
19
|
+
Napa::Logger.logger.debug format_response(status, headers, body)
|
20
|
+
|
21
|
+
# return the results
|
22
|
+
[status, headers, body]
|
23
|
+
ensure
|
24
|
+
# Clear the transaction id after each request
|
25
|
+
Napa::LogTransaction.clear
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
def format_request(env)
|
30
|
+
request = Rack::Request.new(env)
|
31
|
+
params = request.params
|
32
|
+
begin
|
33
|
+
params = JSON.parse(request.body.read) if env['CONTENT_TYPE'] == 'application/json'
|
34
|
+
rescue
|
35
|
+
# do nothing, params is already set
|
36
|
+
end
|
37
|
+
|
38
|
+
request_data = {
|
39
|
+
method: env['REQUEST_METHOD'],
|
40
|
+
path: env['PATH_INFO'],
|
41
|
+
query: env['QUERY_STRING'],
|
42
|
+
host: Napa::Identity.hostname,
|
43
|
+
pid: Napa::Identity.pid,
|
44
|
+
revision: Napa::Identity.revision,
|
45
|
+
params: params
|
46
|
+
}
|
47
|
+
request_data[:user_id] = current_user.try(:id) if defined?(current_user)
|
48
|
+
{request: request_data}
|
49
|
+
end
|
50
|
+
|
51
|
+
def format_response(status, headers, body)
|
52
|
+
response_body = nil
|
53
|
+
begin
|
54
|
+
response_body = body.respond_to?(:body) ? body.body.map{|r| r} : nil
|
55
|
+
rescue
|
56
|
+
response_body = body.inspect
|
57
|
+
end
|
58
|
+
|
59
|
+
{response:
|
60
|
+
{
|
61
|
+
status: status,
|
62
|
+
headers: headers,
|
63
|
+
response: response_body
|
64
|
+
}
|
65
|
+
}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/napa/version.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
module Napa
|
2
|
+
VERSION = "0.1.0"
|
3
|
+
|
4
|
+
class Version
|
5
|
+
class << self
|
6
|
+
def next_major
|
7
|
+
self.next_level(:major)
|
8
|
+
end
|
9
|
+
|
10
|
+
def next_minor
|
11
|
+
self.next_level(:minor)
|
12
|
+
end
|
13
|
+
|
14
|
+
def next_patch
|
15
|
+
self.next_level(:patch)
|
16
|
+
end
|
17
|
+
|
18
|
+
def next_level(level)
|
19
|
+
raise "Unidentified Level" unless [:major,:minor,:patch].include?(level)
|
20
|
+
|
21
|
+
parts = Napa::VERSION.split('.').map{|p| p.to_i}
|
22
|
+
|
23
|
+
if level == :major
|
24
|
+
parts[0] += 1
|
25
|
+
significant_index = 1
|
26
|
+
end
|
27
|
+
|
28
|
+
if level == :minor
|
29
|
+
parts[1] += 1
|
30
|
+
significant_index = 2
|
31
|
+
end
|
32
|
+
|
33
|
+
if level == :patch
|
34
|
+
parts[2] += 1
|
35
|
+
significant_index = 3
|
36
|
+
end
|
37
|
+
|
38
|
+
parts.map.with_index{|p,i| parts[i] = 0 if i >= significant_index}
|
39
|
+
|
40
|
+
parts.join('.')
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/napa.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# require external libraries
|
2
|
+
require 'rake'
|
3
|
+
require 'dotenv'
|
4
|
+
require 'logging'
|
5
|
+
require 'octokit'
|
6
|
+
require 'grape'
|
7
|
+
|
8
|
+
# require internal files
|
9
|
+
require "napa/version"
|
10
|
+
require "napa/logger/logger"
|
11
|
+
require "napa/logger/log_transaction"
|
12
|
+
require "napa/identity"
|
13
|
+
require "napa/middleware/logger"
|
14
|
+
require "napa/middleware/app_monitor"
|
15
|
+
require "napa/activerecord"
|
16
|
+
require "napa/grape_api"
|
17
|
+
require "generators/scaffold"
|
18
|
+
|
19
|
+
# load rake tasks if Rake installed
|
20
|
+
if defined?(Rake)
|
21
|
+
load 'tasks/git.rake'
|
22
|
+
load 'tasks/deploy.rake'
|
23
|
+
load 'tasks/routes.rake'
|
24
|
+
load 'tasks/db.rake'
|
25
|
+
end
|
26
|
+
|
27
|
+
module Napa
|
28
|
+
class << self
|
29
|
+
def env
|
30
|
+
@_env ||= ActiveSupport::StringInquirer.new(ENV["RACK_ENV"] || "development")
|
31
|
+
end
|
32
|
+
|
33
|
+
def env=(environment)
|
34
|
+
@_env = ActiveSupport::StringInquirer.new(environment)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/tasks/db.rake
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
task :environment do
|
2
|
+
require 'erb'
|
3
|
+
require './app'
|
4
|
+
|
5
|
+
raise "ActiveRecord Not Found" unless Module.const_defined?(:ActiveRecord)
|
6
|
+
end
|
7
|
+
|
8
|
+
namespace :db do
|
9
|
+
desc "Migrate the database through scripts in db/migrate. Target specific version with VERSION=x"
|
10
|
+
task :migrate => :environment do
|
11
|
+
ActiveRecord::Migrator.migrate('db/migrate', ENV["VERSION"] ? ENV["VERSION"].to_i : nil )
|
12
|
+
Rake::Task["db:schema:dump"].invoke
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "Create the database"
|
16
|
+
task :create => :environment do
|
17
|
+
db = YAML.load(ERB.new(File.read('./config/database.yml')).result)[Napa.env]
|
18
|
+
adapter = db.merge({'database'=> 'mysql'})
|
19
|
+
ActiveRecord::Base.establish_connection(adapter)
|
20
|
+
ActiveRecord::Base.connection.create_database(db.fetch('database'))
|
21
|
+
end
|
22
|
+
|
23
|
+
desc "Delete the database"
|
24
|
+
task :drop => :environment do
|
25
|
+
db = YAML.load(ERB.new(File.read('./config/database.yml')).result)[Napa.env]
|
26
|
+
adapter = db.merge({'database'=> 'mysql'})
|
27
|
+
ActiveRecord::Base.establish_connection(adapter)
|
28
|
+
ActiveRecord::Base.connection.drop_database(db.fetch('database'))
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "Create the test database"
|
32
|
+
task :reset => :environment do
|
33
|
+
Rake::Task["db:drop"].invoke
|
34
|
+
Rake::Task["db:create"].invoke
|
35
|
+
Rake::Task["db:schema:load"].invoke
|
36
|
+
end
|
37
|
+
|
38
|
+
namespace :generate do
|
39
|
+
desc "Generate a migration with given name. Specify migration name with NAME=my_migration_name"
|
40
|
+
task :migration => :environment do
|
41
|
+
raise "Please specify desired migration name with NAME=my_migration_name" unless ENV['NAME']
|
42
|
+
|
43
|
+
# Find migration name from env
|
44
|
+
migration_name = ENV['NAME'].strip.chomp
|
45
|
+
|
46
|
+
# Define migrations path (needed later)
|
47
|
+
migrations_path = './db/migrate'
|
48
|
+
|
49
|
+
# Find the highest existing migration version or set to 1
|
50
|
+
if (existing_migrations = Dir[File.join(migrations_path, '*.rb')]).length > 0
|
51
|
+
version = File.basename(existing_migrations.sort.reverse.first)[/^(\d+)_/,1].to_i + 1
|
52
|
+
else
|
53
|
+
version = 1
|
54
|
+
end
|
55
|
+
|
56
|
+
# Use the migration template to fill the body of the migration
|
57
|
+
migration_content = Napa::ActiveRecord.migration_template(migration_name.camelize)
|
58
|
+
|
59
|
+
# Generate migration filename
|
60
|
+
migration_filename = "#{"%03d" % version}_#{migration_name}.rb"
|
61
|
+
|
62
|
+
# Write the migration
|
63
|
+
File.open(File.join(migrations_path, migration_filename), "w+") do |migration|
|
64
|
+
migration.puts migration_content
|
65
|
+
end
|
66
|
+
|
67
|
+
# Done!
|
68
|
+
puts "Successfully created migration #{migration_filename}"
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
namespace :schema do
|
73
|
+
desc "Create a db/schema.rb file that can be portably used against any DB supported by AR"
|
74
|
+
task :dump => :environment do
|
75
|
+
require 'active_record/schema_dumper'
|
76
|
+
File.open(ENV['SCHEMA'] || "db/schema.rb", "w") do |file|
|
77
|
+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
desc "Load a schema.rb file into the database"
|
82
|
+
task :load => :environment do
|
83
|
+
file = ENV['SCHEMA'] || "db/schema.rb"
|
84
|
+
load(file)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
namespace :deploy do
|
2
|
+
desc "Deploy to production"
|
3
|
+
task :production do
|
4
|
+
Rake::Task["git:verify"].invoke
|
5
|
+
Rake::Task["git:set_tag"].invoke
|
6
|
+
end
|
7
|
+
|
8
|
+
desc "Deploy to staging"
|
9
|
+
task :staging do
|
10
|
+
Rake::Task["git:verify"].invoke
|
11
|
+
Rake::Task["git:set_tag"].invoke("staging")
|
12
|
+
end
|
13
|
+
end
|
data/lib/tasks/git.rake
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
namespace :git do
|
2
|
+
client = Octokit::Client.new(:oauth_token => ENV['GITHUB_OAUTH_TOKEN'])
|
3
|
+
logger = Logger.new(STDOUT)
|
4
|
+
|
5
|
+
github_repo = ENV['GITHUB_REPO']
|
6
|
+
local_sha = `git rev-parse HEAD`.strip
|
7
|
+
|
8
|
+
desc "Verify git repository is in a good state for deployment"
|
9
|
+
task :verify do
|
10
|
+
logger.info "Verifying git repository is in a good state"
|
11
|
+
|
12
|
+
# Be sure local HEAD exists on remote
|
13
|
+
begin
|
14
|
+
remote_commit = client.commit(github_repo, local_sha)
|
15
|
+
rescue Octokit::NotFound
|
16
|
+
raise RuntimeError, "Local commit #{local_sha} does not exist on remote. Be sure to push your changes."
|
17
|
+
end
|
18
|
+
|
19
|
+
# Check for uncommited changes
|
20
|
+
unless(system("git diff --quiet HEAD"))
|
21
|
+
raise RuntimeError, "You have uncommited changes. Either commit or stash them before continuing."
|
22
|
+
end
|
23
|
+
|
24
|
+
# Check for untracked files
|
25
|
+
unless(`git status --porcelain | grep '^??' | wc -l`.strip == "0")
|
26
|
+
raise RuntimeError, "You have untracked files. Either commit or remove them before continuing."
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
desc "Set tag, which triggers deploy"
|
31
|
+
task :set_tag, :tag do |t, args|
|
32
|
+
tag = args[:tag] || "production"
|
33
|
+
logger.info "Setting #{tag} tag on github"
|
34
|
+
|
35
|
+
# Update ref, create ref if it doesn't exist
|
36
|
+
begin
|
37
|
+
client.update_ref(
|
38
|
+
github_repo,
|
39
|
+
"tags/#{tag}",
|
40
|
+
local_sha
|
41
|
+
)
|
42
|
+
rescue Octokit::UnprocessableEntity
|
43
|
+
client.create_ref(
|
44
|
+
github_repo,
|
45
|
+
"tags/#{tag}",
|
46
|
+
local_sha
|
47
|
+
)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/napa.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/napa/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Darby Frey"]
|
6
|
+
gem.email = ["darby@bellycard.com"]
|
7
|
+
gem.description = %q{A simple framework for building APIs with Grape}
|
8
|
+
gem.summary = %q{A simple framework for building APIs with Grape}
|
9
|
+
gem.homepage = ""
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables << 'napa'
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "napa"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Napa::VERSION
|
17
|
+
|
18
|
+
|
19
|
+
gem.add_dependency 'rake'
|
20
|
+
gem.add_dependency 'logging'
|
21
|
+
gem.add_dependency 'dotenv'
|
22
|
+
gem.add_dependency 'octokit', '~> 1.25'
|
23
|
+
gem.add_dependency 'virtus', '0.5.5'
|
24
|
+
gem.add_dependency 'grape'
|
25
|
+
gem.add_dependency 'grape-swagger'
|
26
|
+
gem.add_dependency 'unicorn'
|
27
|
+
|
28
|
+
gem.add_development_dependency "rspec"
|
29
|
+
gem.add_development_dependency "pry"
|
30
|
+
gem.add_development_dependency "git"
|
31
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'napa/identity'
|
3
|
+
|
4
|
+
describe Napa::Identity do
|
5
|
+
context "#name" do
|
6
|
+
it "returns 'api-service' if no ENV['SERVICE_NAME'] is set" do
|
7
|
+
ENV['SERVICE_NAME'] = nil
|
8
|
+
Napa::Identity.name.should == 'api-service'
|
9
|
+
end
|
10
|
+
|
11
|
+
it "returns the ENV['SERVICE_NAME'] when specified" do
|
12
|
+
ENV['SERVICE_NAME'] = nil
|
13
|
+
ENV['SERVICE_NAME'] = 'my-service'
|
14
|
+
Napa::Identity.name.should == 'my-service'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context "#hostname" do
|
19
|
+
it "returns the value of the hostname system call and doesn't make a second system call" do
|
20
|
+
Napa::Identity.should_receive(:`).with("hostname").and_return("system-hostname")
|
21
|
+
Napa::Identity.hostname.should == 'system-hostname'
|
22
|
+
|
23
|
+
Napa::Identity.should_not_receive(:`).with("hostname")
|
24
|
+
Napa::Identity.hostname.should == 'system-hostname'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context "#revision" do
|
29
|
+
it "returns the value of the 'git rev-parse HEAD' system call and doesn't make a second system call" do
|
30
|
+
Napa::Identity.should_receive(:`).with("git rev-parse HEAD").and_return("12345")
|
31
|
+
Napa::Identity.revision.should == '12345'
|
32
|
+
|
33
|
+
Napa::Identity.should_not_receive(:`).with("git rev-parse HEAD")
|
34
|
+
Napa::Identity.revision.should == '12345'
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "#pid" do
|
39
|
+
it "returns the process ID value" do
|
40
|
+
Process.stub(:pid).and_return(112233)
|
41
|
+
Napa::Identity.pid.should == 112233
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "#platform_revision" do
|
46
|
+
it "returns the current version of the platform gem" do
|
47
|
+
Napa::Identity.platform_revision.should == Napa::VERSION
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'napa/logger/log_transaction'
|
3
|
+
|
4
|
+
describe Napa::LogTransaction do
|
5
|
+
before(:each) do
|
6
|
+
Napa::LogTransaction.clear
|
7
|
+
end
|
8
|
+
|
9
|
+
context "#id" do
|
10
|
+
it "returns the current transaction id if it has been set" do
|
11
|
+
id = SecureRandom.hex(10)
|
12
|
+
Thread.current[:napa_tid] = id
|
13
|
+
Napa::LogTransaction.id.should == id
|
14
|
+
end
|
15
|
+
|
16
|
+
it "sets and returns a new id if the transaction id hasn't been set" do
|
17
|
+
Napa::LogTransaction.id.should_not be_nil
|
18
|
+
end
|
19
|
+
|
20
|
+
it "allows the id to be overridden by a setter" do
|
21
|
+
Napa::LogTransaction.id.should_not be_nil
|
22
|
+
Napa::LogTransaction.id = 'foo'
|
23
|
+
Napa::LogTransaction.id.should == 'foo'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "#clear" do
|
28
|
+
it "sets the id to nil" do
|
29
|
+
Napa::LogTransaction.id.should_not be_nil
|
30
|
+
Napa::LogTransaction.clear
|
31
|
+
Thread.current[:napa_tid].should be_nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'napa'
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'napa/version'
|
3
|
+
|
4
|
+
describe Napa::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("Napa::VERSION", "1.2.3")
|
8
|
+
Napa::Version.next_major.should == "2.0.0"
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should set the major revision value, and the rest should be 0" do
|
12
|
+
stub_const("Napa::VERSION", "5.0.0")
|
13
|
+
Napa::Version.next_major.should == "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("Napa::VERSION", "1.2.3")
|
20
|
+
Napa::Version.next_minor.should == "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("Napa::VERSION", "0.5.0")
|
25
|
+
Napa::Version.next_minor.should == "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("Napa::VERSION", "1.2.3")
|
32
|
+
Napa::Version.next_patch.should == "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("Napa::VERSION", "5.5.5")
|
37
|
+
Napa::Version.next_patch.should == "5.5.6"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/tasks/version.rake
ADDED
@@ -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 = Napa::Version.next_major
|
7
|
+
execute_version_bump
|
8
|
+
end
|
9
|
+
|
10
|
+
task :minor do
|
11
|
+
@new_version = Napa::Version.next_minor
|
12
|
+
execute_version_bump
|
13
|
+
end
|
14
|
+
|
15
|
+
task :patch do
|
16
|
+
@new_version = Napa::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/napa/version.rb')
|
30
|
+
git.commit("Version bump: #{release_tag}")
|
31
|
+
git.add_tag(release_tag)
|
32
|
+
git.push(git.remote('origin'), git.branch, release_tag) if git.remote('origin')
|
33
|
+
puts "Version bumped: #{release_tag}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def write_update
|
38
|
+
filedata = File.read('lib/napa/version.rb')
|
39
|
+
changed_filedata = filedata.gsub("VERSION = \"#{Napa::VERSION}\"\n", "VERSION = \"#{@new_version}\"\n")
|
40
|
+
File.open('lib/napa/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
|