noveku 0.5 → 0.6

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- noveku (0.4)
4
+ noveku (0.5)
5
5
  gomon
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -14,14 +14,34 @@ you should install it globally, not via bundler and your project's Gemfile.
14
14
 
15
15
  ## Usage
16
16
 
17
- `noveku ENV commands...`: will execute the given commands for the `ENV` remote.
17
+ This gem is developed with Rails 3+ in mind. However, it should be suited to any project with a notion of "app environment", with different heroku apps for these environments.
18
18
 
19
- We strongly suggest adding shell aliases for convenience :
19
+ `noveku production COMMAND` translate `COMMAND` in the context of the heroku remote `heroku-production`. When pushing/deploying, the local source branche is `production`. Please read the next two paragraphs for more detailed explications.
20
20
 
21
- ```shell
22
- alias nvp='noveku production'
23
- alias nvs='noveku staging'
24
- ```
21
+ ### Conventions
22
+
23
+ This gem makes a few assumptions about how your branches and remotes are named.
24
+ This is *not* configurable, and that there is no plans to change this.
25
+
26
+ * `origin` is the main git remote, pointing towards github, bitbucket, or any other server.
27
+ * if you have a branch named `novelys`, the heroku git remote corresponding this branch is assumed to be `heroku-novelys`.
28
+
29
+ Our git flow at Novelys is pretty straightforward : the branch `master` is the current version of the app; `staging` is the pre-production version; `production` the production one.
30
+
31
+ This translates to two heroku apps (the name of the apps does not matter), and the remotes named `heroku-staging` and `heroku-master` :
32
+
33
+ [remote "heroku-production"]
34
+ url = git@heroku.com:sampleapp.git
35
+ fetch = +refs/heads/*:refs/remotes/production/*
36
+ [remote "heroky-staging"]
37
+ url = git@heroku.com:sampleapp-preprod.git
38
+ fetch = +refs/heads/*:refs/remotes/staging/*
39
+
40
+ ### Interface
41
+
42
+ Considering what is written above :
43
+
44
+ `noveku ENV COMMAND`: will execute the given `COMMAND` in the context of the `ENV` local branch and `heroku-ENV` heroku git remote.
25
45
 
26
46
  ## Heroku commands
27
47
 
@@ -37,6 +57,20 @@ This makes several other commands available, such as `restart`, `releases`, `ps`
37
57
 
38
58
  ## Advanced commands
39
59
 
60
+ ### Git
61
+
62
+ Those commands are shortcuts for other git commands.
63
+
64
+ * `push`: Push your changes in your local branch to the `origin` remote.
65
+ * `deploy`: Push your changes in your local branch to the heroku remote.
66
+
67
+ They accept the following options:
68
+
69
+ * `--dry-run`: only prints the git command that is going to be executed, without executing it;
70
+ * `--verbose`: prints the git command that is going to be executed, and then execute it.
71
+
72
+ ### MongoDB
73
+
40
74
  * `mongodump`: Dumps the mongo database. Shortcut for both `mongolab_dump` and `mongohq_dump`: tries mongolab first, then mongohq.
41
75
  * `mongolab_dump`: Dumps the mongo database. Look in the config keys of `ENV` to find `MONGOLAB_URI`.
42
76
  * `mongohq_dump`: Dumps the mongo database. Look in the config keys of `ENV` to find `MONGOHQ_URL`.
@@ -58,6 +92,7 @@ I plan on adding a command allowing you to create a heroku app, setup your addon
58
92
 
59
93
  ## Changelog
60
94
 
95
+ * `0.6`: Adds `deploy` and `push`; assumes heroku remotes are prefixed with `heroku-`; enhanced README; internal refactoring.
61
96
  * `0.5`: Test coverage, check the presence of environment & that it matches a heroku app, that pwd is a heroku app, the presence of mongohq/lab uri.
62
97
  * `0.4`: Require `gomon` for mongodump, changed executable names, internal refactoring.
63
98
  * `0.3`: Added `mongodump`, `mongolab_dump`, `mongohq_dump`.
@@ -0,0 +1,73 @@
1
+ module Noveku
2
+ module CLI
3
+ class Base
4
+ attr_reader :commands
5
+
6
+ # Extract commands & options
7
+ def initialize(*commands)
8
+ @options = (commands.last.is_a?(Hash) && commands.pop) || {}
9
+ @commands = commands
10
+ end
11
+
12
+ # Only print
13
+ def dry_run?
14
+ @options[:dry_run]
15
+ end
16
+
17
+ # Print & execute
18
+ def verbose?
19
+ @options[:verbose]
20
+ end
21
+
22
+ # Hide stderr ?
23
+ def hide_stderr?
24
+ !!(@options[:hide_stderr])
25
+ end
26
+
27
+ # Hide stderr ?
28
+ def hide_stdout?
29
+ !!(@options[:hide_stdout])
30
+ end
31
+
32
+ # Hide stderr & stdout ?
33
+ def hide_both?
34
+ hide_stderr? && hide_stdout?
35
+ end
36
+
37
+ # Execute the commands
38
+ def call
39
+ print if dry_run? || verbose?
40
+ system(command) unless dry_run?
41
+ end
42
+
43
+ # Only print the command
44
+ def print
45
+ puts command
46
+ end
47
+
48
+ # The command template, with stream redirection handled
49
+ def template_command_with_output_cleaned(*args)
50
+ base = template_command(*args)
51
+
52
+ stream = if hide_both?
53
+ '&'
54
+ elsif hide_stderr?
55
+ '2'
56
+ elsif hide_stdout?
57
+ '1'
58
+ end
59
+
60
+ base = "#{base} #{stream}> /dev/null" if stream
61
+ base
62
+ end
63
+
64
+ # Command string to execute
65
+ def command
66
+ return nil unless commands
67
+
68
+ # Map commands to template & chain
69
+ commands.map(&method(:template_command_with_output_cleaned)).join(' && ')
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,12 @@
1
+ require 'noveku/cli/base'
2
+
3
+ module Noveku
4
+ module CLI
5
+ class Git < Base
6
+ # Template for commands
7
+ def template_command(command)
8
+ "git #{command}"
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,20 @@
1
+ require 'noveku/cli/base'
2
+
3
+ module Noveku
4
+ module CLI
5
+ class Heroku < Base
6
+ attr_reader :environment
7
+
8
+ # Extract environment from commands
9
+ def initialize(*commands)
10
+ super
11
+ @environment = @commands.shift
12
+ end
13
+
14
+ # Template for commands
15
+ def template_command(command)
16
+ "heroku #{command} --remote '#{environment}'"
17
+ end
18
+ end
19
+ end
20
+ end
data/lib/noveku/config.rb CHANGED
@@ -6,7 +6,7 @@ module Noveku
6
6
 
7
7
  # Returns config value for key
8
8
  def config_value_for(key)
9
- cmd = executable_command config_value_str(key)
9
+ cmd = execute_heroku config_value_str(key), hide_stderr: true
10
10
  value = `#{cmd}`.strip
11
11
  value = nil if value == ''
12
12
  value
@@ -6,7 +6,7 @@ module Noveku
6
6
 
7
7
  # Open the console
8
8
  def console_cmd
9
- execute console_cmd_str
9
+ execute_heroku console_cmd_str
10
10
  end
11
11
  end
12
12
  end
data/lib/noveku/core.rb CHANGED
@@ -1,25 +1,33 @@
1
+ require 'noveku/cli/git'
2
+ require 'noveku/cli/heroku'
1
3
  require 'noveku/config'
2
- require 'noveku/exceptions'
3
- require 'noveku/rake'
4
4
  require 'noveku/console'
5
+ require 'noveku/deploy'
6
+ require 'noveku/exceptions'
5
7
  require 'noveku/migrate'
8
+ require 'noveku/mongo'
9
+ require 'noveku/options'
6
10
  require 'noveku/proxy'
11
+ require 'noveku/push'
12
+ require 'noveku/rake'
7
13
  require 'noveku/tail'
8
- require 'noveku/mongo'
9
14
 
10
15
  module Noveku
11
16
  # Common functionnality
12
17
  class Core
13
18
  include Config
14
19
  include Exceptions
20
+ include Options
15
21
  # Aliases
16
- include Rake
17
22
  include Console
18
23
  include Migrate
19
24
  include Proxy
25
+ include Rake
20
26
  include Tail
21
27
  # Advanced Features
28
+ include Deploy
22
29
  include Mongo
30
+ include Push
23
31
 
24
32
  attr_reader :environment, :command, :arguments
25
33
 
@@ -41,22 +49,37 @@ module Noveku
41
49
  send "#{@command}_cmd"
42
50
  end
43
51
 
52
+ # Prefix of heroku git remotes
53
+ def prefix
54
+ "heroku"
55
+ end
56
+
57
+ # Environment
58
+ alias :branch :environment
59
+
60
+ # Name of heroku remote
61
+ def remote
62
+ "#{prefix}-#{environment}"
63
+ end
64
+
44
65
  private
45
66
 
46
67
  # Execute the commands
47
- def execute(*commands)
48
- system executable_command(*commands)
49
- end
68
+ def execute_heroku(*commands)
69
+ options = (commands.last.is_a?(Hash) && commands.pop) || {}
70
+ options = {dry_run: dry_run?, verbose: verbose?}.merge(options)
50
71
 
51
- # Build command to execute
52
- def executable_command(*commands)
53
- return nil unless commands
72
+ h = Noveku::CLI::Heroku.new environment, *commands, options
73
+ h.()
74
+ end
54
75
 
55
- # Template proc
56
- template = ->(command) { "heroku #{command} --remote '#{environment}'" }
76
+ # Execute the commands
77
+ def execute_git(*commands)
78
+ options = (commands.last.is_a?(Hash) && commands.pop) || {}
79
+ options = {dry_run: dry_run?, verbose: verbose?}.merge(options)
57
80
 
58
- # Map commands to template & chain
59
- commands.map(&template).join(' && ')
81
+ g = Noveku::CLI::Git.new *commands, options
82
+ g.()
60
83
  end
61
84
  end
62
85
  end
@@ -0,0 +1,12 @@
1
+ module Noveku
2
+ module Deploy
3
+ def deploy_cmd_str
4
+ "push #{remote} #{branch}:master"
5
+ end
6
+
7
+ # Open the console
8
+ def deploy_cmd
9
+ execute_git(deploy_cmd_str)
10
+ end
11
+ end
12
+ end
@@ -21,7 +21,7 @@ module Noveku
21
21
  # Check if there is a matching heroku app
22
22
  def ensure_heroku_app
23
23
  # This env is used for testing
24
- return if environment == 'noveku-safe-env'
24
+ return if @environment == 'noveku-safe-env'
25
25
 
26
26
  system "heroku releases --remote '#{environment}' >& /dev/null"
27
27
 
@@ -7,7 +7,7 @@ module Noveku
7
7
 
8
8
  # Open the console
9
9
  def migrate_cmd
10
- execute *migrate_cmd_args
10
+ execute_heroku *migrate_cmd_args
11
11
  end
12
12
  end
13
13
  end
@@ -0,0 +1,15 @@
1
+ module Noveku
2
+ module Options
3
+ def verbose?
4
+ arguments.include?('--verbose')
5
+ end
6
+
7
+ def dry_run?
8
+ arguments.include?('--dry-run')
9
+ end
10
+
11
+ def proxied_arguments
12
+ arguments.reject { |a| %w(--verbose --dry-run).include?(a) }
13
+ end
14
+ end
15
+ end
data/lib/noveku/proxy.rb CHANGED
@@ -2,13 +2,13 @@ module Noveku
2
2
  module Proxy
3
3
  # String to execute when proxying commands
4
4
  def proxy_cmd_str
5
- ([@command] + @arguments).join(' ')
5
+ ([@command] + proxied_arguments).join(' ')
6
6
  end
7
7
 
8
8
  # If this is a command with no specific support, pass the raw arguments to `heroku` directly
9
9
  def method_missing(name, *args, &block)
10
10
  if name.to_s.end_with?('_cmd')
11
- execute proxy_cmd_str
11
+ execute_heroku proxy_cmd_str
12
12
  else
13
13
  super
14
14
  end
@@ -0,0 +1,12 @@
1
+ module Noveku
2
+ module Push
3
+ def push_cmd_str
4
+ "push origin #{environment}"
5
+ end
6
+
7
+ # Open the console
8
+ def push_cmd
9
+ execute_git(push_cmd_str)
10
+ end
11
+ end
12
+ end
data/lib/noveku/rake.rb CHANGED
@@ -9,7 +9,7 @@ module Noveku
9
9
 
10
10
  # Execute a rake task
11
11
  def rake_cmd
12
- execute rake_cmd_str
12
+ execute_heroku rake_cmd_str
13
13
  end
14
14
  end
15
15
  end
data/lib/noveku/tail.rb CHANGED
@@ -7,7 +7,7 @@ module Noveku
7
7
 
8
8
  # Tail logs
9
9
  def tail_cmd
10
- execute tail_cmd_str
10
+ execute_heroku tail_cmd_str
11
11
  end
12
12
  end
13
13
  end
@@ -1,3 +1,3 @@
1
1
  module Noveku
2
- VERSION = '0.5'
2
+ VERSION = '0.6'
3
3
  end
data/spec/core_spec.rb CHANGED
@@ -11,8 +11,16 @@ describe 'Core' do
11
11
  context 'commands' do
12
12
  subject { Noveku::Core.new 'noveku-safe-env', 'rake', 'stats' }
13
13
 
14
+ it 'prefix should be "heroku"' do
15
+ expect(subject.prefix).to eq 'heroku'
16
+ end
17
+
14
18
  it 'environment should be the first command' do
15
- expect(subject.environment).to eq 'noveku-safe-env'
19
+ expect(subject.environment).to eq "noveku-safe-env"
20
+ end
21
+
22
+ it 'remote should be the prefixed environment' do
23
+ expect(subject.remote).to eq "#{subject.prefix}-#{subject.environment}"
16
24
  end
17
25
 
18
26
  it 'main command should be the second command' do
@@ -22,15 +30,5 @@ describe 'Core' do
22
30
  it 'argument should be the remaining' do
23
31
  expect(subject.arguments).to eq ['stats']
24
32
  end
25
-
26
- it 'string to execute should contain given command' do
27
- str = "heroku run rake stats --remote 'noveku-safe-env'"
28
- expect(subject.send(:executable_command, 'run rake stats')).to eq str
29
- end
30
-
31
- it 'string to execute should chain given command' do
32
- str = "heroku run rake stats --remote 'noveku-safe-env' && heroku releases --remote 'noveku-safe-env'"
33
- expect(subject.send(:executable_command, 'run rake stats', 'releases')).to eq str
34
- end
35
33
  end
36
34
  end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+ require 'noveku/core'
3
+
4
+ describe 'Deploy' do
5
+ subject { Noveku::Core.new 'noveku-safe-env', 'deploy' }
6
+
7
+ it 'must have an executable command string' do
8
+ expect(subject.deploy_cmd_str).to eq "push #{subject.prefix}-noveku-safe-env noveku-safe-env:master"
9
+ end
10
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+ require 'noveku/cli/heroku'
3
+
4
+ describe 'CLI' do
5
+ context 'Heroku' do
6
+ it 'string to execute should contain given command' do
7
+ heroku = Noveku::CLI::Heroku.new 'noveku-safe-env', 'run rake stats'
8
+ str = "heroku run rake stats --remote 'noveku-safe-env'"
9
+ expect(heroku.command).to eq str
10
+ end
11
+
12
+ it 'string to execute should chain given command' do
13
+ heroku = Noveku::CLI::Heroku.new 'noveku-safe-env', 'run rake stats', 'releases'
14
+ str = "heroku run rake stats --remote 'noveku-safe-env' && heroku releases --remote 'noveku-safe-env'"
15
+ expect(heroku.command).to eq str
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+ require 'noveku/core'
3
+
4
+ describe 'Options handler' do
5
+ context 'Dry run' do
6
+ subject { Noveku::Core.new 'noveku-safe-env', 'anycommandyoulike', '--dry-run' }
7
+
8
+ it 'recognizes the long form option' do
9
+ expect(subject.dry_run?).to be_true
10
+ end
11
+
12
+ it 'does not proxy the option' do
13
+ expect(subject.proxied_arguments).not_to include '--dry-run'
14
+ end
15
+ end
16
+
17
+ context 'Verbose' do
18
+ subject { Noveku::Core.new 'noveku-safe-env', 'anycommandyoulike', '--verbose' }
19
+
20
+ it 'recognizes the long form option' do
21
+ expect(subject.verbose?).to be_true
22
+ end
23
+
24
+ it 'does not proxy the option' do
25
+ expect(subject.proxied_arguments).not_to include '--verbose'
26
+ end
27
+ end
28
+ end
data/spec/push_spec.rb ADDED
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+ require 'noveku/core'
3
+
4
+ describe 'Push' do
5
+ subject { Noveku::Core.new 'noveku-safe-env', 'push' }
6
+
7
+ it 'must have an executable command string' do
8
+ expect(subject.push_cmd_str).to eq "push origin #{subject.environment}"
9
+ end
10
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: noveku
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.5'
4
+ version: '0.6'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2013-01-19 00:00:00.000000000 Z
13
+ date: 2013-02-21 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: gomon
@@ -77,13 +77,19 @@ files:
77
77
  - Rakefile
78
78
  - bin/noveku
79
79
  - lib/noveku.rb
80
+ - lib/noveku/cli/base.rb
81
+ - lib/noveku/cli/git.rb
82
+ - lib/noveku/cli/heroku.rb
80
83
  - lib/noveku/config.rb
81
84
  - lib/noveku/console.rb
82
85
  - lib/noveku/core.rb
86
+ - lib/noveku/deploy.rb
83
87
  - lib/noveku/exceptions.rb
84
88
  - lib/noveku/migrate.rb
85
89
  - lib/noveku/mongo.rb
90
+ - lib/noveku/options.rb
86
91
  - lib/noveku/proxy.rb
92
+ - lib/noveku/push.rb
87
93
  - lib/noveku/rake.rb
88
94
  - lib/noveku/tail.rb
89
95
  - lib/noveku/version.rb
@@ -91,9 +97,13 @@ files:
91
97
  - spec/config_spec.rb
92
98
  - spec/console_spec.rb
93
99
  - spec/core_spec.rb
100
+ - spec/deploy_spec.rb
101
+ - spec/heroku_spec.rb
94
102
  - spec/migrate_spec.rb
95
103
  - spec/mongo_spec.rb
104
+ - spec/options_spec.rb
96
105
  - spec/proxy_spec.rb
106
+ - spec/push_spec.rb
97
107
  - spec/rake_spec.rb
98
108
  - spec/spec_helper.rb
99
109
  - spec/tail_spec.rb