noveku 0.6 → 0.7

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.gem
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- noveku (0.5)
4
+ noveku (0.7)
5
5
  gomon
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -1,39 +1,48 @@
1
1
  # Noveku
2
2
 
3
- A collection of aliases we use when interacting with heroku.
3
+ A console utility easing up interactions with heroku when you have several heroku apps for one project (most common use case: production and staging environments for a webapp).
4
4
  This gem was inspired by [a collection of thoughtbot aliases](https://github.com/thoughtbot/dotfiles/commit/86494030441e88ef9c2e2ceaa00a4da82023e445).
5
5
 
6
6
  ## Prerequisites
7
7
 
8
- Ruby 1.9+ only. This gem depends on novelys/gomon. However, the presence of the command `heroku` (either via the gem, or the toolbelt) is assumed
8
+ Ruby 1.9+ only. This gem depends on novelys/gomon. However, the presence of the commands `heroku` and `git` is assumed.
9
9
 
10
10
  ## Installation
11
11
 
12
- `gem install noveku`. Since it will not be part of your application, only of your workflow,
13
- you should install it globally, not via bundler and your project's Gemfile.
12
+ `gem install noveku`
14
13
 
15
14
  ## Usage
16
15
 
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.
16
+ This gem is developed with Rails 3+ in mind.
18
17
 
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.
18
+ However, it should be suited to any project with a notion of "app environment",
19
+ with different heroku apps for these environments.
20
+ It is assumed that your apps are using the cedar stack.
21
+ While some commands might work for other stacks, this is purely coincidental.
22
+
23
+ `noveku ENV COMMAND` means that `COMMAND` will be executed for the heroku app with the remote named `heroku-ENV`.
24
+ In the case of the commands `push` and `deploy`, the local branch used as source is `ENV`.
25
+ Please read the next two paragraphs for detailed explications.
20
26
 
21
27
  ### Conventions
22
28
 
23
29
  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.
30
+ This is *not* configurable, and there is no plans to change this.
25
31
 
26
- * `origin` is the main git remote, pointing towards github, bitbucket, or any other server.
32
+ * `origin` is the main git remote, pointing towards GitHub, BitBucket, or any other server.
27
33
  * if you have a branch named `novelys`, the heroku git remote corresponding this branch is assumed to be `heroku-novelys`.
28
34
 
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.
35
+ Our git flow at Novelys is pretty straightforward :
36
+ the branch `master` is the current version of the app;
37
+ `staging` is the pre-production version;
38
+ `production` the production one.
30
39
 
31
40
  This translates to two heroku apps (the name of the apps does not matter), and the remotes named `heroku-staging` and `heroku-master` :
32
41
 
33
42
  [remote "heroku-production"]
34
43
  url = git@heroku.com:sampleapp.git
35
44
  fetch = +refs/heads/*:refs/remotes/production/*
36
- [remote "heroky-staging"]
45
+ [remote "heroku-staging"]
37
46
  url = git@heroku.com:sampleapp-preprod.git
38
47
  fetch = +refs/heads/*:refs/remotes/staging/*
39
48
 
@@ -43,31 +52,35 @@ Considering what is written above :
43
52
 
44
53
  `noveku ENV COMMAND`: will execute the given `COMMAND` in the context of the `ENV` local branch and `heroku-ENV` heroku git remote.
45
54
 
46
- ## Heroku commands
55
+ ## Commands
56
+
57
+ When giving a command that has no specific support, it will be proxied to `heroku` : `heroku ARGS --remote ENV`.
58
+ This makes several other commands available, such as `restart`, `releases`, `ps`, `open`...
59
+
60
+ ### Common options
61
+
62
+ Exception made of mongodb related commands, they all accept the following options:
63
+
64
+ * `--dry-run`: only prints the git command that is going to be executed, without executing it;
65
+ * `--verbose`: prints the git command that is going to be executed, and then execute it.
66
+
67
+ ### Heroku
47
68
 
48
69
  Supported commands and their equivalent :
49
70
 
50
- * `rake` : `heroku run rake ARGS --remove ENV`
71
+ * `rake ARGS` : `heroku run rake ARGS --remove ENV`
51
72
  * `console`: `heroku run console --remote ENV`
52
73
  * `migrate`: `heroku run rake db:migrate --remote ENV && heroku restart --remote ENV`
53
74
  * `tail`: `heroku logs --tail --remote ENV`
54
-
55
- When giving a command that is not specifically supported, it will be passed to `heroku` : `heroku ARGS --remote ENV`.
56
- This makes several other commands available, such as `restart`, `releases`, `ps`, `open`...
57
-
58
- ## Advanced commands
75
+ * `create APP_NAME ENV [ADDONS...]`: creates `APP_NAME` bound to the remote `heroku-ENV`. Each listed addon will be added right away. If any part of the subcommand fails, the remaining will not be executed.
76
+ * `clone APP_NAME NEW_ENV BASE_ENV [ADDONS...]`: creates APP_NAME bound to the remote `heroku-NEW_ENV`, and adds every addon from `BASE_ENV`.
59
77
 
60
78
  ### Git
61
79
 
62
80
  Those commands are shortcuts for other git commands.
63
81
 
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.
82
+ * `push`: `git push origin ENV`, push your changes in your local branch to the `origin` remote.
83
+ * `deploy`: `git push heroku-ENV ENV:master`, push your changes in your local branch to the heroku remote.
71
84
 
72
85
  ### MongoDB
73
86
 
@@ -81,7 +94,7 @@ Since the restoration of the database does not involve any interaction with hero
81
94
 
82
95
  ## What's next
83
96
 
84
- I plan on adding a command allowing you to create a heroku app, setup your addons, update your git config, create a local branch if needed.. all that in one step. We're still thinking about what the command api will look like. This will probably be the last feature before tagging 1.0.0.
97
+ Better test coverage. This will be bumped to `1.0.0` once this is done and after using the gem in our daily flow for a few weeks.
85
98
 
86
99
  ## Contributions
87
100
 
@@ -92,6 +105,7 @@ I plan on adding a command allowing you to create a heroku app, setup your addon
92
105
 
93
106
  ## Changelog
94
107
 
108
+ * `0.7`: Adds `create` and `clone`.
95
109
  * `0.6`: Adds `deploy` and `push`; assumes heroku remotes are prefixed with `heroku-`; enhanced README; internal refactoring.
96
110
  * `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.
97
111
  * `0.4`: Require `gomon` for mongodump, changed executable names, internal refactoring.
@@ -0,0 +1,31 @@
1
+ module Noveku
2
+ module Addon
3
+ # Command string to add an addon
4
+ def addon_cmd_str(name)
5
+ "addons:add #{name}"
6
+ end
7
+
8
+ # Command string to list addons for current env
9
+ def raw_list_addons_str
10
+ "addons"
11
+ end
12
+
13
+ # Get the raw list of addons
14
+ def raw_list_addons
15
+ heroku = get_heroku raw_list_addons_str
16
+
17
+ `#{heroku.command}`
18
+ end
19
+
20
+ # Clean the list of addons
21
+ def cleaned_addons_list
22
+ return @addons if @addons
23
+
24
+ @addons = raw_list_addons.split("\n")
25
+ @addons.reject! { |addon| addon.start_with?('===') }
26
+ @addons.map! { |addon| addon.split(' ').first }
27
+ @addons.uniq!
28
+ @addons
29
+ end
30
+ end
31
+ end
@@ -2,6 +2,7 @@ module Noveku
2
2
  module CLI
3
3
  class Base
4
4
  attr_reader :commands
5
+ attr_accessor :noveku
5
6
 
6
7
  # Extract commands & options
7
8
  def initialize(*commands)
@@ -42,12 +43,12 @@ module Noveku
42
43
 
43
44
  # Only print the command
44
45
  def print
45
- puts command
46
+ puts ">> Command to be executed: #{command}"
46
47
  end
47
48
 
48
49
  # The command template, with stream redirection handled
49
- def template_command_with_output_cleaned(*args)
50
- base = template_command(*args)
50
+ def template_command_with_output_cleaned(command)
51
+ base = template_command(command)
51
52
 
52
53
  stream = if hide_both?
53
54
  '&'
@@ -13,7 +13,7 @@ module Noveku
13
13
 
14
14
  # Template for commands
15
15
  def template_command(command)
16
- "heroku #{command} --remote '#{environment}'"
16
+ "heroku #{command} --remote '#{noveku.remote}'"
17
17
  end
18
18
  end
19
19
  end
@@ -0,0 +1,23 @@
1
+ module Noveku
2
+ module Clone
3
+ # Clone args
4
+ def clone_cmd_args
5
+ base = ["apps:create #{@app_name}"]
6
+
7
+ cleaned_addons_list.each { |addon| base << addon_cmd_str(addon) }
8
+
9
+ base
10
+ end
11
+
12
+ # Clone command
13
+ def clone_cmd
14
+ # Get the command from base env...
15
+ commands = clone_cmd_args
16
+
17
+ # Switch to new env and execute
18
+ @environment = @new_environment
19
+
20
+ execute_heroku *commands
21
+ end
22
+ end
23
+ end
data/lib/noveku/config.rb CHANGED
@@ -6,8 +6,8 @@ module Noveku
6
6
 
7
7
  # Returns config value for key
8
8
  def config_value_for(key)
9
- cmd = execute_heroku config_value_str(key), hide_stderr: true
10
- value = `#{cmd}`.strip
9
+ heroku = get_heroku config_value_str(key), hide_stderr: true
10
+ value = `#{heroku.command}`.strip
11
11
  value = nil if value == ''
12
12
  value
13
13
  end
data/lib/noveku/core.rb CHANGED
@@ -1,7 +1,10 @@
1
+ require 'noveku/addon'
1
2
  require 'noveku/cli/git'
2
3
  require 'noveku/cli/heroku'
4
+ require 'noveku/clone'
3
5
  require 'noveku/config'
4
6
  require 'noveku/console'
7
+ require 'noveku/create'
5
8
  require 'noveku/deploy'
6
9
  require 'noveku/exceptions'
7
10
  require 'noveku/migrate'
@@ -25,6 +28,9 @@ module Noveku
25
28
  include Rake
26
29
  include Tail
27
30
  # Advanced Features
31
+ include Addon
32
+ include Clone
33
+ include Create
28
34
  include Deploy
29
35
  include Mongo
30
36
  include Push
@@ -35,11 +41,18 @@ module Noveku
35
41
  def initialize(*arguments)
36
42
  @environment = arguments.shift
37
43
 
38
- ensure_env
39
- ensure_heroku_app
44
+ if environmentless_command?
45
+ arguments.unshift @environment
46
+ @environment = nil
47
+ else
48
+ ensure_env
49
+ ensure_heroku_app
50
+ end
40
51
 
41
52
  @command = arguments.shift
42
53
  @arguments = arguments
54
+
55
+ post_arguments_handling
43
56
  rescue Exception => e
44
57
  handle_exception(e)
45
58
  end
@@ -64,22 +77,61 @@ module Noveku
64
77
 
65
78
  private
66
79
 
67
- # Execute the commands
68
- def execute_heroku(*commands)
80
+ # Post treatment of arguments in some cases
81
+ def post_arguments_handling
82
+ return unless environmentless_command?
83
+
84
+ send "#{command}_arguments_handling"
85
+ end
86
+
87
+ # Arguments handling for `create` command
88
+ def create_arguments_handling
89
+ @app_name = arguments.shift
90
+ @environment = arguments.shift
91
+
92
+ raise ArgumentError, '`create` expects an app name: noveku create APPNAME ENV [addons...]' unless @app_name
93
+ raise ArgumentError, '`create` expects an env name: noveku create APPNAME ENV [addons...]' unless @environment
94
+ end
95
+
96
+ # Arguments handling for `clone` command
97
+ def clone_arguments_handling
98
+ @app_name = arguments.shift
99
+ @new_environment = arguments.shift
100
+ @environment = arguments.shift
101
+
102
+ raise ArgumentError, '`clone` expects an app name: noveku clone APPNAME NEW_ENV BASE_ENV' unless @app_name
103
+ raise ArgumentError, '`clone` expects a new env name: noveku clone APPNAME NEW_ENV BASE_ENV' unless @new_environment
104
+ raise ArgumentError, '`clone` expects a base env name: noveku clone APPNAME NEW_ENV BASE_ENV' unless @environment
105
+ end
106
+
107
+ # Retrieve heroku object setup
108
+ def get_heroku(*commands)
69
109
  options = (commands.last.is_a?(Hash) && commands.pop) || {}
70
110
  options = {dry_run: dry_run?, verbose: verbose?}.merge(options)
71
111
 
72
112
  h = Noveku::CLI::Heroku.new environment, *commands, options
73
- h.()
113
+ h.noveku = self
114
+ h
74
115
  end
75
116
 
76
117
  # Execute the commands
77
- def execute_git(*commands)
118
+ def execute_heroku(*commands)
119
+ get_heroku(*commands).call
120
+ end
121
+
122
+ # Retrieve heroku object setup
123
+ def get_git(*commands)
78
124
  options = (commands.last.is_a?(Hash) && commands.pop) || {}
79
125
  options = {dry_run: dry_run?, verbose: verbose?}.merge(options)
80
126
 
81
127
  g = Noveku::CLI::Git.new *commands, options
82
- g.()
128
+ g.noveku = self
129
+ g
130
+ end
131
+
132
+ # Execute the commands
133
+ def execute_git(*commands)
134
+ get_git(*commands).call
83
135
  end
84
136
  end
85
137
  end
@@ -0,0 +1,17 @@
1
+ module Noveku
2
+ module Create
3
+ # Create args
4
+ def create_cmd_args
5
+ base = ["apps:create #{@app_name}"]
6
+
7
+ proxied_arguments.each { |addon| base << addon_cmd_str(addon) }
8
+
9
+ base
10
+ end
11
+
12
+ # Open the console
13
+ def create_cmd
14
+ execute_heroku *create_cmd_args
15
+ end
16
+ end
17
+ end
@@ -13,6 +13,11 @@ module Noveku
13
13
  module Exceptions
14
14
  private
15
15
 
16
+ # Some commands do not require an environment supplied
17
+ def environmentless_command?
18
+ @envless ||= (environment && ['create', 'clone'].include?(environment))
19
+ end
20
+
16
21
  # Check if environment is present
17
22
  def ensure_env
18
23
  raise NotAValidEnvironment unless @environment
@@ -23,7 +28,7 @@ module Noveku
23
28
  # This env is used for testing
24
29
  return if @environment == 'noveku-safe-env'
25
30
 
26
- system "heroku releases --remote '#{environment}' >& /dev/null"
31
+ system "heroku releases --remote '#{remote}' >& /dev/null"
27
32
 
28
33
  raise NoHerokuApp unless $?.exitstatus == 0
29
34
  end
@@ -1,3 +1,3 @@
1
1
  module Noveku
2
- VERSION = '0.6'
2
+ VERSION = '0.7'
3
3
  end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+ require 'noveku/core'
3
+
4
+ describe 'Clone' do
5
+ let(:app_less) { Noveku::Core.new 'clone' }
6
+ let(:new_env_less) { Noveku::Core.new 'clone', 'newapp' }
7
+ let(:base_env_less) { Noveku::Core.new 'clone', 'newapp', 'new-env' }
8
+ subject { Noveku::Core.new 'clone', 'newapp', 'new-env', 'base-env' }
9
+
10
+ it 'should have the app name supplied' do
11
+ expect(-> {app_less}).to raise_error(ArgumentError)
12
+ end
13
+
14
+ it 'should have the new env name supplied' do
15
+ expect(-> {new_env_less}).to raise_error(ArgumentError)
16
+ end
17
+
18
+ it 'should have the base env name supplied' do
19
+ expect(-> {base_env_less}).to raise_error(ArgumentError)
20
+ end
21
+
22
+ it 'should be environmentless' do
23
+ expect(subject.send(:environmentless_command?)).to be_true
24
+ end
25
+ end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+ require 'noveku/core'
3
+
4
+ describe 'Create' do
5
+ let(:app_less) { Noveku::Core.new 'create' }
6
+ let(:env_less) { Noveku::Core.new 'create', 'newapp' }
7
+ subject { Noveku::Core.new 'create', 'newapp', 'env-name' }
8
+
9
+ it 'should have the app name supplied' do
10
+ expect(-> {app_less}).to raise_error(ArgumentError)
11
+ end
12
+
13
+ it 'should have the env name supplied' do
14
+ expect(-> {env_less}).to raise_error(ArgumentError)
15
+ end
16
+
17
+ it 'should be environmentless' do
18
+ expect(subject.send(:environmentless_command?)).to be_true
19
+ end
20
+
21
+ it 'should have a prefixed remote' do
22
+ expect(subject.remote).to eq "#{subject.prefix}-env-name"
23
+ end
24
+
25
+ context 'Without addons' do
26
+ it 'must have an executable command string' do
27
+ expect(subject.create_cmd_args).to eq ['apps:create newapp']
28
+ end
29
+ end
30
+
31
+ context 'With addons' do
32
+ subject { Noveku::Core.new 'create', 'newapp', 'env-name', 'addon:1', 'otherone' }
33
+
34
+ it 'must have an executable command string' do
35
+ expect(subject.create_cmd_args).to eq ['apps:create newapp', 'addons:add addon:1', 'addons:add otherone']
36
+ end
37
+ end
38
+ end
data/spec/heroku_spec.rb CHANGED
@@ -1,17 +1,22 @@
1
1
  require 'spec_helper'
2
+ require 'noveku/core'
2
3
  require 'noveku/cli/heroku'
3
4
 
4
5
  describe 'CLI' do
5
6
  context 'Heroku' do
7
+ let(:core) { Noveku::Core.new 'noveku-safe-env', 'notrelevant'}
8
+
6
9
  it 'string to execute should contain given command' do
7
10
  heroku = Noveku::CLI::Heroku.new 'noveku-safe-env', 'run rake stats'
8
- str = "heroku run rake stats --remote 'noveku-safe-env'"
11
+ heroku.noveku = core
12
+ str = "heroku run rake stats --remote '#{heroku.noveku.prefix}-noveku-safe-env'"
9
13
  expect(heroku.command).to eq str
10
14
  end
11
15
 
12
16
  it 'string to execute should chain given command' do
13
17
  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'"
18
+ heroku.noveku = core
19
+ str = "heroku run rake stats --remote '#{heroku.noveku.prefix}-noveku-safe-env' && heroku releases --remote '#{heroku.noveku.prefix}-noveku-safe-env'"
15
20
  expect(heroku.command).to eq str
16
21
  end
17
22
  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.6'
4
+ version: '0.7'
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-02-21 00:00:00.000000000 Z
13
+ date: 2013-02-22 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: gomon
@@ -69,6 +69,7 @@ executables:
69
69
  extensions: []
70
70
  extra_rdoc_files: []
71
71
  files:
72
+ - .gitignore
72
73
  - .rspec
73
74
  - .travis.yml
74
75
  - Gemfile
@@ -77,12 +78,15 @@ files:
77
78
  - Rakefile
78
79
  - bin/noveku
79
80
  - lib/noveku.rb
81
+ - lib/noveku/addon.rb
80
82
  - lib/noveku/cli/base.rb
81
83
  - lib/noveku/cli/git.rb
82
84
  - lib/noveku/cli/heroku.rb
85
+ - lib/noveku/clone.rb
83
86
  - lib/noveku/config.rb
84
87
  - lib/noveku/console.rb
85
88
  - lib/noveku/core.rb
89
+ - lib/noveku/create.rb
86
90
  - lib/noveku/deploy.rb
87
91
  - lib/noveku/exceptions.rb
88
92
  - lib/noveku/migrate.rb
@@ -94,9 +98,11 @@ files:
94
98
  - lib/noveku/tail.rb
95
99
  - lib/noveku/version.rb
96
100
  - noveku.gemspec
101
+ - spec/clone_spec.rb
97
102
  - spec/config_spec.rb
98
103
  - spec/console_spec.rb
99
104
  - spec/core_spec.rb
105
+ - spec/create_spec.rb
100
106
  - spec/deploy_spec.rb
101
107
  - spec/heroku_spec.rb
102
108
  - spec/migrate_spec.rb