noveku 0.5 → 0.6

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.
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