hk 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +15 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +60 -0
- data/README.md +116 -0
- data/Rakefile +9 -0
- data/bin/hk +99 -0
- data/features/hk.feature +52 -0
- data/features/step_definitions/hk_steps.rb +52 -0
- data/features/support/env.rb +21 -0
- data/features/support/fake_heroku.rb +13 -0
- data/hk.gemspec +26 -0
- data/lib/hk.rb +13 -0
- data/lib/hk/app_lister.rb +11 -0
- data/lib/hk/app_name_deriver.rb +35 -0
- data/lib/hk/global_options.rb +49 -0
- data/lib/hk/heroku_command.rb +18 -0
- data/lib/hk/heroku_runner.rb +24 -0
- data/lib/hk/version.rb +3 -0
- data/lib/rake/bundler.rb +2 -0
- data/lib/rake/cucumber.rb +25 -0
- data/lib/rake/man.rb +8 -0
- data/lib/rake/test.rb +6 -0
- data/man/hk.1 +176 -0
- data/man/hk.1.ronn +101 -0
- data/test/app_name_deriver_test.rb +86 -0
- data/test/test_helper.rb +11 -0
- metadata +232 -0
data/.gitignore
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
|
2
|
+
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
3
|
+
#
|
4
|
+
# If you find yourself ignoring temporary files generated by your text editor
|
5
|
+
# or operating system, you probably want to add a global ignore instead:
|
6
|
+
# git config --global core.excludesfile ~/.gitignore_global
|
7
|
+
|
8
|
+
/tmp
|
9
|
+
*.swp
|
10
|
+
*.rbc
|
11
|
+
.DS_Store
|
12
|
+
.vimrc
|
13
|
+
.jhw-cache
|
14
|
+
results.html
|
15
|
+
pkg
|
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
hk
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
1.9.3-p429
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
hk (0.0.1)
|
5
|
+
gem-man
|
6
|
+
gli (~> 2)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
aruba (0.5.3)
|
12
|
+
childprocess (>= 0.3.6)
|
13
|
+
cucumber (>= 1.1.1)
|
14
|
+
rspec-expectations (>= 2.7.0)
|
15
|
+
builder (3.2.2)
|
16
|
+
childprocess (0.3.9)
|
17
|
+
ffi (~> 1.0, >= 1.0.11)
|
18
|
+
clean_test (1.0.0)
|
19
|
+
faker
|
20
|
+
cucumber (1.3.5)
|
21
|
+
builder (>= 2.1.2)
|
22
|
+
diff-lcs (>= 1.1.3)
|
23
|
+
gherkin (~> 2.12.0)
|
24
|
+
multi_json (~> 1.7.5)
|
25
|
+
multi_test (>= 0.0.2)
|
26
|
+
diff-lcs (1.2.4)
|
27
|
+
faker (1.2.0)
|
28
|
+
i18n (~> 0.5)
|
29
|
+
ffi (1.9.0)
|
30
|
+
gem-man (0.3.0)
|
31
|
+
gherkin (2.12.0)
|
32
|
+
multi_json (~> 1.3)
|
33
|
+
gli (2.7.0)
|
34
|
+
hpricot (0.8.6)
|
35
|
+
i18n (0.6.4)
|
36
|
+
json (1.8.0)
|
37
|
+
multi_json (1.7.8)
|
38
|
+
multi_test (0.0.2)
|
39
|
+
mustache (0.99.4)
|
40
|
+
rake (10.1.0)
|
41
|
+
rdiscount (2.1.6)
|
42
|
+
rdoc (4.0.1)
|
43
|
+
json (~> 1.4)
|
44
|
+
ronn (0.7.3)
|
45
|
+
hpricot (>= 0.8.2)
|
46
|
+
mustache (>= 0.7.0)
|
47
|
+
rdiscount (>= 1.5.8)
|
48
|
+
rspec-expectations (2.14.0)
|
49
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
50
|
+
|
51
|
+
PLATFORMS
|
52
|
+
ruby
|
53
|
+
|
54
|
+
DEPENDENCIES
|
55
|
+
aruba
|
56
|
+
clean_test
|
57
|
+
hk!
|
58
|
+
rake
|
59
|
+
rdoc
|
60
|
+
ronn
|
data/README.md
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
hk(1) -- Simplify your access to Heroku on the command-line
|
2
|
+
===========================================================
|
3
|
+
|
4
|
+
## SYNOPSIS
|
5
|
+
|
6
|
+
`hk **alias** _app_string_`
|
7
|
+
|
8
|
+
`hk **any heroku invocation** _app_string_`
|
9
|
+
|
10
|
+
## INSTALL
|
11
|
+
|
12
|
+
$ gem install hk
|
13
|
+
|
14
|
+
## DESCRIPTION
|
15
|
+
|
16
|
+
**hk** is an alias system for Heroku's command-line app that does three things:
|
17
|
+
|
18
|
+
* Wrap complex or cumbersome commands and options into single-word (or single-letter) aliases (e.g. `hk logs` will do `heroku logs --tail`)
|
19
|
+
* Derive application names from shorter-strings (e.g. `hk logs f-p` will run `heroku logs --tail --app=foo-production`)
|
20
|
+
* Alleviates you from typing `heroku`, which is hard to type and prone to misspellings
|
21
|
+
|
22
|
+
**hk** can easily be extended with whatever command aliases you would like. It also passes through any unknown command to the underlying `heroku` command, but *does do* the app name derivation.
|
23
|
+
|
24
|
+
## COMMAND ALIASING
|
25
|
+
|
26
|
+
Command aliasing is fairly straightforward - a string is used to generate a more complex heroku command invocation. You can create your own in `~/.hk/commands/commands.rb` (boilerplate which can be created via `hk init`).
|
27
|
+
|
28
|
+
desc 'Get app info'
|
29
|
+
arg_name Hk::ARG_NAME
|
30
|
+
command :info do |c|
|
31
|
+
c.action do |_,_,args|
|
32
|
+
Hk.run("apps:info",args)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
This code is the GLI DSL, so you can use that entire API if you want to, however the above is a minimal example.
|
37
|
+
|
38
|
+
You'll note that your command now shows up if you do `hk help`.
|
39
|
+
|
40
|
+
## APP NAME DERIVATION
|
41
|
+
|
42
|
+
If your team is maintaining various apps on heroku, and using it for staging, it can be quite cumbersome to be constantly typing out the names of apps. It's also somewhat dangerous to rely on the `.git/config` because it obfuscates what's going to happen behind your current directory.
|
43
|
+
|
44
|
+
**hk** will derive your application name, assuming that you use a canonical naming structure that is **app_name-environment_name**. **app_name** is a logical name for your app, e.g. "foobar". **environment_name** is a logical name for an environment, like "staging" or "production".
|
45
|
+
|
46
|
+
So, instead of typing `--app=foobar-production`, you can simply type `f-p`. As long as you have no other app that starts with "f", and no other environment that starts with "p" (based on the output of `heroku apps`), then **hk** will derive the name. You can add more letters to disambiguate, so if you had an app call "frob-production", you would use "fo-p" for "foobar-production" and "fr-p" for "frob-production"
|
47
|
+
|
48
|
+
## OPTIONS
|
49
|
+
|
50
|
+
* `--heroku PATH_TO_HEROKU`:
|
51
|
+
Specify where the heroku command line app is. If omitted, will just use your path
|
52
|
+
* `--verbose`:
|
53
|
+
If specified, will output the heroku command being executed
|
54
|
+
* `-n`,`--no-app-derivation`:
|
55
|
+
If specified, will skip deriving the app and tacking on a `--app` option
|
56
|
+
|
57
|
+
## EXAMPLES
|
58
|
+
|
59
|
+
There are three builtin aliases (which you can disable by setting SKIP_DEFAULTS=true in your customizations file): console, logs, and psql:
|
60
|
+
|
61
|
+
hk logs f-p
|
62
|
+
# heroku logs --tail --app=foo-production
|
63
|
+
|
64
|
+
hk console f-p
|
65
|
+
# heroku run rails c --app=foo-production
|
66
|
+
|
67
|
+
hk psql f-p
|
68
|
+
# heroku pg:psql --app=foo-production
|
69
|
+
|
70
|
+
Unknown commands will pass through, but app derivation will still take place:
|
71
|
+
|
72
|
+
hk run rake db:migrate f-s
|
73
|
+
# heroku run rake db:migrate --app=foo-staging
|
74
|
+
|
75
|
+
You can also be explicit about where `heroku` is you don't want to rely on your PATH:
|
76
|
+
|
77
|
+
hk --heroku=/sbin/herkou logs f-p
|
78
|
+
# /sbin/heroku logs --tail --app=foo-production
|
79
|
+
|
80
|
+
And, you can skip all the magic if you like:
|
81
|
+
|
82
|
+
hk -n --heroku=/sbin/herkou pg:info --app=hellblazer
|
83
|
+
# sbin/herkou pg:info --app=hellblazer
|
84
|
+
|
85
|
+
Note that because this is backed by GLI, you only need to specify the command-name with enough characters to disambiguate it. For example, given the three builtins, these two are equivalent:
|
86
|
+
|
87
|
+
|
88
|
+
hk logs f-p
|
89
|
+
hk l f-p
|
90
|
+
|
91
|
+
## AUTHOR
|
92
|
+
|
93
|
+
David Copeland, davec (at) naildrivin5.com
|
94
|
+
|
95
|
+
## COPYRIGHT
|
96
|
+
|
97
|
+
hk is copyright(c) 2012 by David Copeland, released under the Apache license.
|
98
|
+
|
99
|
+
## SEE ALSO
|
100
|
+
|
101
|
+
* Source on github: https://github.com/davetron5000/hk
|
102
|
+
|
103
|
+
|
104
|
+
[SYNOPSIS]: #SYNOPSIS "SYNOPSIS"
|
105
|
+
[INSTALL]: #INSTALL "INSTALL"
|
106
|
+
[DESCRIPTION]: #DESCRIPTION "DESCRIPTION"
|
107
|
+
[COMMAND ALIASING]: #COMMAND-ALIASING "COMMAND ALIASING"
|
108
|
+
[APP NAME DERIVATION]: #APP-NAME-DERIVATION "APP NAME DERIVATION"
|
109
|
+
[OPTIONS]: #OPTIONS "OPTIONS"
|
110
|
+
[EXAMPLES]: #EXAMPLES "EXAMPLES"
|
111
|
+
[AUTHOR]: #AUTHOR "AUTHOR"
|
112
|
+
[COPYRIGHT]: #COPYRIGHT "COPYRIGHT"
|
113
|
+
[SEE ALSO]: #SEE-ALSO "SEE ALSO"
|
114
|
+
|
115
|
+
|
116
|
+
[hk(1)]: hk.1.html
|
data/Rakefile
ADDED
data/bin/hk
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'gli'
|
3
|
+
require 'hk'
|
4
|
+
|
5
|
+
include GLI::App
|
6
|
+
|
7
|
+
program_desc 'Expedient interface to your heroku apps'
|
8
|
+
program_long_desc %{The heroku command-line app does a lot of stuff, however it's not geared toward making common things simple. Further, it doesn't know about environments, and it can be a pain to type app names in all the time.
|
9
|
+
|
10
|
+
hk aims to make that simpler by allowing expedient access to commonly-needed commands as well as a simpler way to specify which app - and which environment - you want to operate on}
|
11
|
+
|
12
|
+
preserve_argv
|
13
|
+
|
14
|
+
version Hk::VERSION
|
15
|
+
|
16
|
+
Hk::GlobalOptions.declare_gli_options(self)
|
17
|
+
|
18
|
+
desc "Bootstrap your extensions/customizations directory"
|
19
|
+
long_desc "You can create your own customizations and aliases for complex Heroku commands, by placing Ruby code in ~/.hk/commands. `init` will set that up and give you basic instructions on how to do it"
|
20
|
+
|
21
|
+
command :init do |c|
|
22
|
+
c.action do |_,_,_|
|
23
|
+
commands_dir = File.join(ENV["HOME"],".hk","commands")
|
24
|
+
FileUtils.mkdir_p commands_dir
|
25
|
+
filename = File.join(commands_dir,"commands.rb")
|
26
|
+
exit_now!("you already have commands defined in #{commands_dir.gsub(ENV['HOME'],'~')}") if File.exists?(filename)
|
27
|
+
File.open(filename,"w") do |file|
|
28
|
+
file.puts <<EOS
|
29
|
+
# This file gets require'ed into hk directly, so you can put whatever Ruby
|
30
|
+
# code you want here. It follows the GLI syntax, but there are additional
|
31
|
+
# helpers for making an hk-style command.
|
32
|
+
|
33
|
+
|
34
|
+
desc 'Get app info' # This shows up in `hk help`
|
35
|
+
arg_name Hk::ARG_NAME # This makes your usage string canonical, so just leave verbatim
|
36
|
+
command :info do |c| # You can also an array for multiple names
|
37
|
+
c.action do |_,_,args|
|
38
|
+
Hk.run("apps:info",args) # This will run heroku apps:info --app=<derived app name>
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# You can add as many of these as you like
|
43
|
+
|
44
|
+
SKIP_DEFAULTS=false # set this to true to NOT create the default aliases that come with hk
|
45
|
+
# Useful if you aren't a Rails developer or Postgres user
|
46
|
+
EOS
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
commands_from File.join(ENV["HOME"],".hk","commands")
|
52
|
+
|
53
|
+
skip_defaults = defined?(SKIP_DEFAULTS) && SKIP_DEFAULTS == true
|
54
|
+
unless skip_defaults
|
55
|
+
{
|
56
|
+
:logs => {
|
57
|
+
desc: "Tail logs for app",
|
58
|
+
command: "logs --tail",
|
59
|
+
},
|
60
|
+
:console => {
|
61
|
+
desc: "Get a rails console for app",
|
62
|
+
command: "run rails c",
|
63
|
+
},
|
64
|
+
:psql => {
|
65
|
+
desc: "Get a database console for app",
|
66
|
+
command: "pg:psql ",
|
67
|
+
}
|
68
|
+
}.each do |name,metadata|
|
69
|
+
desc metadata[:desc]
|
70
|
+
arg_name Hk::ARG_NAME
|
71
|
+
command name do |c|
|
72
|
+
c.action do |_,_,args|
|
73
|
+
Hk.run(metadata[:command],args)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
pre do |global,command,options,args|
|
80
|
+
$heroku = Hk::HerokuCommand.new(global[:heroku],global[:verbose],global["no-app-derivation"])
|
81
|
+
true
|
82
|
+
end
|
83
|
+
|
84
|
+
on_error do |exception|
|
85
|
+
case exception
|
86
|
+
when GLI::CustomExit
|
87
|
+
true
|
88
|
+
else
|
89
|
+
opts = Hk::GlobalOptions.option_parser
|
90
|
+
|
91
|
+
args = opts.parse_and_get_args(ARGV)
|
92
|
+
|
93
|
+
heroku = Hk::HerokuCommand.new(opts.heroku,opts.verbose,opts.no_app_derivation)
|
94
|
+
heroku.run(args[0..-2].map {|_| "'#{_}'"}.join(" "),args[-1])
|
95
|
+
false
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
exit run(ARGV)
|
data/features/hk.feature
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
Feature: Basic UI
|
2
|
+
In order to stop typing so much
|
3
|
+
And mis-spelling heroku as "heroky"
|
4
|
+
I want a configurable shortcut app
|
5
|
+
|
6
|
+
Scenario: App has a help system
|
7
|
+
When I get help for "hk"
|
8
|
+
Then the exit status should be 0
|
9
|
+
And there should be an option to specify where the heroku command is
|
10
|
+
|
11
|
+
Scenario: arbitrary heroku command derives the app name
|
12
|
+
Given I have the heroku apps "foo-production,foo-staging,bar-production"
|
13
|
+
When I run the app with "blah f-p"
|
14
|
+
Then the heroku command-line app should be executed with the args "blah --app=foo-production"
|
15
|
+
|
16
|
+
Scenario: can avoid deriving the app name
|
17
|
+
Given I have the heroku apps "foo-production,foo-staging,bar-production"
|
18
|
+
When I run the app with "-n blah --app=f-p"
|
19
|
+
Then the heroku command-line app should be executed with the args "blah --app=f-p"
|
20
|
+
|
21
|
+
Scenario: logs command is helpful
|
22
|
+
Given I have the heroku apps "foo-production,foo-staging,bar-production"
|
23
|
+
When I run the app with "logs f-p"
|
24
|
+
Then the heroku command-line app should be executed with the args "logs --tail --app=foo-production"
|
25
|
+
|
26
|
+
Scenario: console command is helpful
|
27
|
+
Given I have the heroku apps "foo-production,foo-staging,bar-production"
|
28
|
+
When I run the app with "console f-p"
|
29
|
+
Then the heroku command-line app should be executed with the args "run rails c --app=foo-production"
|
30
|
+
|
31
|
+
Scenario: Can add my own commands
|
32
|
+
Given I have the heroku apps "foo-production,foo-staging,bar-production"
|
33
|
+
And I have the custom command "info" defined to run "apps:info"
|
34
|
+
When I run the app with "info f-p"
|
35
|
+
Then the heroku command-line app should be executed with the args "apps:info --app=foo-production"
|
36
|
+
|
37
|
+
Scenario: Can bootstrap the plugins
|
38
|
+
When I run the app with "init"
|
39
|
+
Then the file ".hk/commands/commands.rb" should exist in my home directory
|
40
|
+
|
41
|
+
Scenario: Won't squash existing file
|
42
|
+
Given I run the app with "init"
|
43
|
+
When I run the app with "init"
|
44
|
+
Then the exit status should not be 0
|
45
|
+
And the stderr should contain "error: you already have commands defined in ~/.hk/commands"
|
46
|
+
|
47
|
+
Scenario: Can skip the built-in aliases
|
48
|
+
Given my plugins specify SKIP_DEFAULTS=true
|
49
|
+
When I run the app with "help"
|
50
|
+
Then I should not see help for "logs"
|
51
|
+
And I should not see help for "console"
|
52
|
+
And I should not see help for "psql"
|
@@ -0,0 +1,52 @@
|
|
1
|
+
When /^I get help for "([^"]*)"$/ do |app_name|
|
2
|
+
@app_name = app_name
|
3
|
+
step %(I run `#{app_name} help`)
|
4
|
+
end
|
5
|
+
|
6
|
+
And /^there should be an option to specify where the heroku command is$/ do
|
7
|
+
step %{the output should contain "--heroku"}
|
8
|
+
end
|
9
|
+
|
10
|
+
Given(/^I have the heroku apps "(.*?)"$/) do |app_list|
|
11
|
+
end
|
12
|
+
|
13
|
+
When(/^I run the app with "(.*?)"$/) do |app_args|
|
14
|
+
fake_heroku = File.join(File.dirname(__FILE__),'..','support','fake_heroku.rb')
|
15
|
+
step %{I run `hk --heroku=#{fake_heroku} #{app_args}`}
|
16
|
+
end
|
17
|
+
|
18
|
+
Then(/^the heroku command\-line app should be executed with the args "(.*?)"$/) do |args|
|
19
|
+
step %{the output should contain "#{args}"}
|
20
|
+
end
|
21
|
+
|
22
|
+
Given(/^I have the custom command "(.*?)" defined to run "(.*?)"$/) do |command, args|
|
23
|
+
commands_file_dir = File.join(FAKE_HOME,".hk","commands")
|
24
|
+
FileUtils.mkdir_p commands_file_dir
|
25
|
+
File.open(File.join(commands_file_dir,"commands.rb"),"w") do |file|
|
26
|
+
file.puts <<EOS
|
27
|
+
desc 'Get app info'
|
28
|
+
arg_name Hk::ARG_NAME
|
29
|
+
command "#{command}" do |c|
|
30
|
+
c.action do |_,_,args|
|
31
|
+
Hk.run("#{args}",args)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
EOS
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
Then(/^the file "(.*?)" should exist in my home directory$/) do |file_name|
|
39
|
+
File.exists?(File.join(ENV["HOME"],file_name)).should == true
|
40
|
+
end
|
41
|
+
|
42
|
+
Given(/^my plugins specify SKIP_DEFAULTS=true$/) do
|
43
|
+
commands_file_dir = File.join(FAKE_HOME,".hk","commands")
|
44
|
+
FileUtils.mkdir_p commands_file_dir
|
45
|
+
File.open(File.join(commands_file_dir,"commands.rb"),"w") do |file|
|
46
|
+
file.puts "SKIP_DEFAULTS=true"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
Then(/^I should not see help for "(.*?)"$/) do |arg1|
|
51
|
+
step %{the output should not match /#{arg1}\s+-/}
|
52
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'aruba/cucumber'
|
2
|
+
|
3
|
+
ENV['PATH'] = "#{File.expand_path(File.dirname(__FILE__) + '/../../bin')}#{File::PATH_SEPARATOR}#{ENV['PATH']}"
|
4
|
+
LIB_DIR = File.join(File.expand_path(File.dirname(__FILE__)),'..','..','lib')
|
5
|
+
FAKE_HOME = "/tmp/fake_home"
|
6
|
+
|
7
|
+
Before do
|
8
|
+
# Using "announce" causes massive warnings on 1.9.2
|
9
|
+
@puts = true
|
10
|
+
@original_rubylib = ENV['RUBYLIB']
|
11
|
+
ENV['RUBYLIB'] = LIB_DIR + File::PATH_SEPARATOR + ENV['RUBYLIB'].to_s
|
12
|
+
FileUtils.rm_rf FAKE_HOME
|
13
|
+
FileUtils.mkdir_p FAKE_HOME
|
14
|
+
@original_home = ENV['HOME']
|
15
|
+
ENV['HOME'] = FAKE_HOME
|
16
|
+
end
|
17
|
+
|
18
|
+
After do
|
19
|
+
ENV['RUBYLIB'] = @original_rubylib
|
20
|
+
ENV['HOME'] = @original_home
|
21
|
+
end
|
data/hk.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# Ensure we require the local version and not one we might have installed already
|
2
|
+
require File.join([File.dirname(__FILE__),'lib','hk','version.rb'])
|
3
|
+
spec = Gem::Specification.new do |s|
|
4
|
+
s.name = 'hk'
|
5
|
+
s.version = Hk::VERSION
|
6
|
+
s.author = 'Your Name Here'
|
7
|
+
s.email = 'your@email.address.com'
|
8
|
+
s.homepage = 'http://your.website.com'
|
9
|
+
s.platform = Gem::Platform::RUBY
|
10
|
+
s.summary = 'A description of your project'
|
11
|
+
# Add your other files here if you make them
|
12
|
+
s.files = `git ls-files`.split("\n")
|
13
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
14
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
15
|
+
s.require_paths = ["lib"]
|
16
|
+
s.has_rdoc = false
|
17
|
+
s.bindir = 'bin'
|
18
|
+
s.executables << 'hk'
|
19
|
+
s.add_development_dependency('clean_test')
|
20
|
+
s.add_development_dependency('rake')
|
21
|
+
s.add_development_dependency('rdoc')
|
22
|
+
s.add_development_dependency('aruba')
|
23
|
+
s.add_development_dependency('ronn')
|
24
|
+
s.add_runtime_dependency('gli','~> 2')
|
25
|
+
s.add_runtime_dependency('gem-man')
|
26
|
+
end
|
data/lib/hk.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'hk/version'
|
2
|
+
require 'hk/global_options'
|
3
|
+
require 'hk/heroku_runner'
|
4
|
+
require 'hk/app_lister'
|
5
|
+
require 'hk/app_name_deriver'
|
6
|
+
require 'hk/heroku_command'
|
7
|
+
module Hk
|
8
|
+
ARG_NAME = "app_name-environment"
|
9
|
+
|
10
|
+
def self.run(heroku_command_args,args)
|
11
|
+
$heroku.run(heroku_command_args,args.first)
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Hk
|
2
|
+
class AppNameDeriver
|
3
|
+
def initialize(app_lister)
|
4
|
+
@app_lister = app_lister
|
5
|
+
end
|
6
|
+
|
7
|
+
def derive(app_string)
|
8
|
+
app,environment = app_string.split(/\-/)
|
9
|
+
apps = @app_lister.list_apps
|
10
|
+
|
11
|
+
return app_string if apps.include?(app_string)
|
12
|
+
|
13
|
+
apps = apps.map { |_| _.split(/\-/)}.select { |(a,_)|
|
14
|
+
a =~ /^#{app}/
|
15
|
+
}.select { |(_,e)|
|
16
|
+
if e.nil? && environment.nil?
|
17
|
+
true
|
18
|
+
elsif e.nil?
|
19
|
+
false
|
20
|
+
elsif environment.nil?
|
21
|
+
false
|
22
|
+
else
|
23
|
+
e =~ /^#{environment}/
|
24
|
+
end
|
25
|
+
}
|
26
|
+
if apps.size == 1
|
27
|
+
apps.first.join("-")
|
28
|
+
elsif apps.size == 0
|
29
|
+
raise "No such app name matched #{app_string}"
|
30
|
+
else
|
31
|
+
raise "Ambiguous app name for #{app_string}. Matches: #{apps.map {|_| _.join("-") }.join(',')}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Hk
|
2
|
+
# Since we have to do some hacking to handle arbitrary commands,
|
3
|
+
# this serves as a central location for the global options that enable that.
|
4
|
+
class GlobalOptions
|
5
|
+
def self.declare_gli_options(app)
|
6
|
+
app.desc "Explicitly set where to find the herkou CLI app"
|
7
|
+
app.default_value "heroku"
|
8
|
+
app.arg_name "path_to_heroku"
|
9
|
+
app.flag :heroku
|
10
|
+
|
11
|
+
app.desc "Be verbose - show the heroku commands being run"
|
12
|
+
app.switch :verbose
|
13
|
+
|
14
|
+
app.desc "Do not derive the app name or append --app to the command"
|
15
|
+
app.switch [:n,"no-app-derivation"], negatable: false
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.option_parser
|
20
|
+
OptionParser.new.tap { |opts|
|
21
|
+
class << opts
|
22
|
+
def heroku=(h)
|
23
|
+
@heroku = h
|
24
|
+
end
|
25
|
+
def heroku; @heroku || "heroku"; end
|
26
|
+
def verbose=(v)
|
27
|
+
@verbose = v
|
28
|
+
end
|
29
|
+
def verbose; @verbose; end
|
30
|
+
def no_app_derivation=(v)
|
31
|
+
@no_app_derivation = v
|
32
|
+
end
|
33
|
+
def no_app_derivation; @no_app_derivation; end
|
34
|
+
def parse_and_get_args(args)
|
35
|
+
args = args.dup
|
36
|
+
self.order!(args) do |unknown_option|
|
37
|
+
args.unshift(unknown_option)
|
38
|
+
break
|
39
|
+
end
|
40
|
+
args
|
41
|
+
end
|
42
|
+
end
|
43
|
+
opts.on("--heroku HEROKU") { |path| opts.heroku = path }
|
44
|
+
opts.on("--verbose") { opts.verbose = true }
|
45
|
+
opts.on("-n","--no-app-derivation") { opts.no_app_derivation = true }
|
46
|
+
}
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Hk
|
2
|
+
class HerokuCommand
|
3
|
+
def initialize(path_to_heroku,verbose,no_app_derivation)
|
4
|
+
@heroku = Hk::HerokuRunner.new(path_to_heroku,verbose)
|
5
|
+
@app_name_deriver = if no_app_derivation
|
6
|
+
->(app_name_string) { app_name_string }
|
7
|
+
else
|
8
|
+
->(app_name_string) {
|
9
|
+
"--app=#{Hk::AppNameDeriver.new(Hk::AppLister.new(@heroku)).derive(app_name_string)}"
|
10
|
+
}
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def run(heroku_args,app_name_string)
|
15
|
+
@heroku.("#{heroku_args} #{@app_name_deriver.(app_name_string)}")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Hk
|
2
|
+
class HerokuRunner
|
3
|
+
def initialize(heroku_command,verbose)
|
4
|
+
@heroku_command = heroku_command
|
5
|
+
@verbose = verbose
|
6
|
+
end
|
7
|
+
|
8
|
+
def run(args)
|
9
|
+
command = "#{@heroku_command} #{args}"
|
10
|
+
puts command if @verbose
|
11
|
+
system(command)
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(args)
|
15
|
+
run(args)
|
16
|
+
end
|
17
|
+
|
18
|
+
def run_internal(args)
|
19
|
+
command = "#{@heroku_command} #{args}"
|
20
|
+
puts command if @verbose
|
21
|
+
`#{command}`
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/hk/version.rb
ADDED
data/lib/rake/bundler.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'cucumber'
|
2
|
+
require 'cucumber/rake/task'
|
3
|
+
|
4
|
+
CUKE_RESULTS = 'results.html'
|
5
|
+
CLEAN << CUKE_RESULTS
|
6
|
+
|
7
|
+
desc 'Run features'
|
8
|
+
Cucumber::Rake::Task.new(:features) do |t|
|
9
|
+
opts = "features --format html -o #{CUKE_RESULTS} --format progress -x"
|
10
|
+
opts += " --tags #{ENV['TAGS']}" if ENV['TAGS']
|
11
|
+
t.cucumber_opts = opts
|
12
|
+
t.fork = false
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Run features tagged as work-in-progress (@wip)'
|
16
|
+
Cucumber::Rake::Task.new('features:wip') do |t|
|
17
|
+
tag_opts = ' --tags ~@pending'
|
18
|
+
tag_opts = ' --tags @wip'
|
19
|
+
t.cucumber_opts = "features --format html -o #{CUKE_RESULTS} --format pretty -x -s#{tag_opts}"
|
20
|
+
t.fork = false
|
21
|
+
end
|
22
|
+
|
23
|
+
task :cucumber => :features
|
24
|
+
task 'cucumber:wip' => 'features:wip'
|
25
|
+
task :wip => 'features:wip'
|
data/lib/rake/man.rb
ADDED
data/lib/rake/test.rb
ADDED
data/man/hk.1
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
.\" generated with Ronn/v0.7.3
|
2
|
+
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
3
|
+
.
|
4
|
+
.TH "HK" "1" "August 2013" "" ""
|
5
|
+
.
|
6
|
+
.SH "NAME"
|
7
|
+
\fBhk\fR \- Simplify your access to Heroku on the command\-line
|
8
|
+
.
|
9
|
+
.SH "SYNOPSIS"
|
10
|
+
\fBhk **alias** _app_string_\fR
|
11
|
+
.
|
12
|
+
.P
|
13
|
+
\fBhk **any heroku invocation** _app_string_\fR
|
14
|
+
.
|
15
|
+
.SH "INSTALL"
|
16
|
+
.
|
17
|
+
.nf
|
18
|
+
|
19
|
+
$ gem install hk
|
20
|
+
.
|
21
|
+
.fi
|
22
|
+
.
|
23
|
+
.SH "DESCRIPTION"
|
24
|
+
\fBhk\fR is an alias system for Heroku\'s command\-line app that does three things:
|
25
|
+
.
|
26
|
+
.IP "\(bu" 4
|
27
|
+
Wrap complex or cumbersome commands and options into single\-word (or single\-letter) aliases (e\.g\. \fBhk logs\fR will do \fBheroku logs \-\-tail\fR)
|
28
|
+
.
|
29
|
+
.IP "\(bu" 4
|
30
|
+
Derive application names from shorter\-strings (e\.g\. \fBhk logs f\-p\fR will run \fBheroku logs \-\-tail \-\-app=foo\-production\fR)
|
31
|
+
.
|
32
|
+
.IP "\(bu" 4
|
33
|
+
Alleviates you from typing \fBheroku\fR, which is hard to type and prone to misspellings
|
34
|
+
.
|
35
|
+
.IP "" 0
|
36
|
+
.
|
37
|
+
.P
|
38
|
+
\fBhk\fR can easily be extended with whatever command aliases you would like\. It also passes through any unknown command to the underlying \fBheroku\fR command, but \fIdoes do\fR the app name derivation\.
|
39
|
+
.
|
40
|
+
.SH "COMMAND ALIASING"
|
41
|
+
Command aliasing is fairly straightforward \- a string is used to generate a more complex heroku command invocation\. You can create your own in \fB~/\.hk/commands/commands\.rb\fR (boilerplate which can be created via \fBhk init\fR)\.
|
42
|
+
.
|
43
|
+
.IP "" 4
|
44
|
+
.
|
45
|
+
.nf
|
46
|
+
|
47
|
+
desc \'Get app info\'
|
48
|
+
arg_name Hk::ARG_NAME
|
49
|
+
command :info do |c|
|
50
|
+
c\.action do |_,_,args|
|
51
|
+
Hk\.run("apps:info",args)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
.
|
55
|
+
.fi
|
56
|
+
.
|
57
|
+
.IP "" 0
|
58
|
+
.
|
59
|
+
.P
|
60
|
+
This code is the GLI DSL, so you can use that entire API if you want to, however the above is a minimal example\.
|
61
|
+
.
|
62
|
+
.P
|
63
|
+
You\'ll note that your command now shows up if you do \fBhk help\fR\.
|
64
|
+
.
|
65
|
+
.SH "APP NAME DERIVATION"
|
66
|
+
If your team is maintaining various apps on heroku, and using it for staging, it can be quite cumbersome to be constantly typing out the names of apps\. It\'s also somewhat dangerous to rely on the \fB\.git/config\fR because it obfuscates what\'s going to happen behind your current directory\.
|
67
|
+
.
|
68
|
+
.P
|
69
|
+
\fBhk\fR will derive your application name, assuming that you use a canonical naming structure that is \fBapp_name\-environment_name\fR\. \fBapp_name\fR is a logical name for your app, e\.g\. "foobar"\. \fBenvironment_name\fR is a logical name for an environment, like "staging" or "production"\.
|
70
|
+
.
|
71
|
+
.P
|
72
|
+
So, instead of typing \fB\-\-app=foobar\-production\fR, you can simply type \fBf\-p\fR\. As long as you have no other app that starts with "f", and no other environment that starts with "p" (based on the output of \fBheroku apps\fR), then \fBhk\fR will derive the name\. You can add more letters to disambiguate, so if you had an app call "frob\-production", you would use "fo\-p" for "foobar\-production" and "fr\-p" for "frob\-production"
|
73
|
+
.
|
74
|
+
.SH "OPTIONS"
|
75
|
+
.
|
76
|
+
.TP
|
77
|
+
\fB\-\-heroku PATH_TO_HEROKU\fR
|
78
|
+
Specify where the heroku command line app is\. If omitted, will just use your path
|
79
|
+
.
|
80
|
+
.TP
|
81
|
+
\fB\-\-verbose\fR
|
82
|
+
If specified, will output the heroku command being executed
|
83
|
+
.
|
84
|
+
.TP
|
85
|
+
\fB\-n\fR,\fB\-\-no\-app\-derivation\fR
|
86
|
+
If specified, will skip deriving the app and tacking on a \fB\-\-app\fR option
|
87
|
+
.
|
88
|
+
.SH "EXAMPLES"
|
89
|
+
There are three builtin aliases (which you can disable by setting SKIP_DEFAULTS=true in your customizations file): console, logs, and psql:
|
90
|
+
.
|
91
|
+
.IP "" 4
|
92
|
+
.
|
93
|
+
.nf
|
94
|
+
|
95
|
+
hk logs f\-p
|
96
|
+
# heroku logs \-\-tail \-\-app=foo\-production
|
97
|
+
|
98
|
+
hk console f\-p
|
99
|
+
# heroku run rails c \-\-app=foo\-production
|
100
|
+
|
101
|
+
hk psql f\-p
|
102
|
+
# heroku pg:psql \-\-app=foo\-production
|
103
|
+
.
|
104
|
+
.fi
|
105
|
+
.
|
106
|
+
.IP "" 0
|
107
|
+
.
|
108
|
+
.P
|
109
|
+
Unknown commands will pass through, but app derivation will still take place:
|
110
|
+
.
|
111
|
+
.IP "" 4
|
112
|
+
.
|
113
|
+
.nf
|
114
|
+
|
115
|
+
hk run rake db:migrate f\-s
|
116
|
+
# heroku run rake db:migrate \-\-app=foo\-staging
|
117
|
+
.
|
118
|
+
.fi
|
119
|
+
.
|
120
|
+
.IP "" 0
|
121
|
+
.
|
122
|
+
.P
|
123
|
+
You can also be explicit about where \fBheroku\fR is you don\'t want to rely on your PATH:
|
124
|
+
.
|
125
|
+
.IP "" 4
|
126
|
+
.
|
127
|
+
.nf
|
128
|
+
|
129
|
+
hk \-\-heroku=/sbin/herkou logs f\-p
|
130
|
+
# /sbin/heroku logs \-\-tail \-\-app=foo\-production
|
131
|
+
.
|
132
|
+
.fi
|
133
|
+
.
|
134
|
+
.IP "" 0
|
135
|
+
.
|
136
|
+
.P
|
137
|
+
And, you can skip all the magic if you like:
|
138
|
+
.
|
139
|
+
.IP "" 4
|
140
|
+
.
|
141
|
+
.nf
|
142
|
+
|
143
|
+
hk \-n \-\-heroku=/sbin/herkou pg:info \-\-app=hellblazer
|
144
|
+
# sbin/herkou pg:info \-\-app=hellblazer
|
145
|
+
.
|
146
|
+
.fi
|
147
|
+
.
|
148
|
+
.IP "" 0
|
149
|
+
.
|
150
|
+
.P
|
151
|
+
Note that because this is backed by GLI, you only need to specify the command\-name with enough characters to disambiguate it\. For example, given the three builtins, these two are equivalent:
|
152
|
+
.
|
153
|
+
.IP "" 4
|
154
|
+
.
|
155
|
+
.nf
|
156
|
+
|
157
|
+
hk logs f\-p
|
158
|
+
hk l f\-p
|
159
|
+
.
|
160
|
+
.fi
|
161
|
+
.
|
162
|
+
.IP "" 0
|
163
|
+
.
|
164
|
+
.SH "AUTHOR"
|
165
|
+
David Copeland, davec (at) naildrivin5\.com
|
166
|
+
.
|
167
|
+
.SH "COPYRIGHT"
|
168
|
+
hk is copyright(c) 2012 by David Copeland, released under the Apache license\.
|
169
|
+
.
|
170
|
+
.SH "SEE ALSO"
|
171
|
+
.
|
172
|
+
.IP "\(bu" 4
|
173
|
+
Source on github: https://github\.com/davetron5000/hk
|
174
|
+
.
|
175
|
+
.IP "" 0
|
176
|
+
|
data/man/hk.1.ronn
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
hk(1) -- Simplify your access to Heroku on the command-line
|
2
|
+
===========================================================
|
3
|
+
|
4
|
+
## SYNOPSIS
|
5
|
+
|
6
|
+
`hk **alias** _app_string_`
|
7
|
+
|
8
|
+
`hk **any heroku invocation** _app_string_`
|
9
|
+
|
10
|
+
## INSTALL
|
11
|
+
|
12
|
+
$ gem install hk
|
13
|
+
|
14
|
+
## DESCRIPTION
|
15
|
+
|
16
|
+
**hk** is an alias system for Heroku's command-line app that does three things:
|
17
|
+
|
18
|
+
* Wrap complex or cumbersome commands and options into single-word (or single-letter) aliases (e.g. `hk logs` will do `heroku logs --tail`)
|
19
|
+
* Derive application names from shorter-strings (e.g. `hk logs f-p` will run `heroku logs --tail --app=foo-production`)
|
20
|
+
* Alleviates you from typing `heroku`, which is hard to type and prone to misspellings
|
21
|
+
|
22
|
+
**hk** can easily be extended with whatever command aliases you would like. It also passes through any unknown command to the underlying `heroku` command, but *does do* the app name derivation.
|
23
|
+
|
24
|
+
## COMMAND ALIASING
|
25
|
+
|
26
|
+
Command aliasing is fairly straightforward - a string is used to generate a more complex heroku command invocation. You can create your own in `~/.hk/commands/commands.rb` (boilerplate which can be created via `hk init`).
|
27
|
+
|
28
|
+
desc 'Get app info'
|
29
|
+
arg_name Hk::ARG_NAME
|
30
|
+
command :info do |c|
|
31
|
+
c.action do |_,_,args|
|
32
|
+
Hk.run("apps:info",args)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
This code is the GLI DSL, so you can use that entire API if you want to, however the above is a minimal example.
|
37
|
+
|
38
|
+
You'll note that your command now shows up if you do `hk help`.
|
39
|
+
|
40
|
+
## APP NAME DERIVATION
|
41
|
+
|
42
|
+
If your team is maintaining various apps on heroku, and using it for staging, it can be quite cumbersome to be constantly typing out the names of apps. It's also somewhat dangerous to rely on the `.git/config` because it obfuscates what's going to happen behind your current directory.
|
43
|
+
|
44
|
+
**hk** will derive your application name, assuming that you use a canonical naming structure that is **app_name-environment_name**. **app_name** is a logical name for your app, e.g. "foobar". **environment_name** is a logical name for an environment, like "staging" or "production".
|
45
|
+
|
46
|
+
So, instead of typing `--app=foobar-production`, you can simply type `f-p`. As long as you have no other app that starts with "f", and no other environment that starts with "p" (based on the output of `heroku apps`), then **hk** will derive the name. You can add more letters to disambiguate, so if you had an app call "frob-production", you would use "fo-p" for "foobar-production" and "fr-p" for "frob-production"
|
47
|
+
|
48
|
+
## OPTIONS
|
49
|
+
|
50
|
+
* `--heroku PATH_TO_HEROKU`:
|
51
|
+
Specify where the heroku command line app is. If omitted, will just use your path
|
52
|
+
* `--verbose`:
|
53
|
+
If specified, will output the heroku command being executed
|
54
|
+
* `-n`,`--no-app-derivation`:
|
55
|
+
If specified, will skip deriving the app and tacking on a `--app` option
|
56
|
+
|
57
|
+
## EXAMPLES
|
58
|
+
|
59
|
+
There are three builtin aliases (which you can disable by setting SKIP_DEFAULTS=true in your customizations file): console, logs, and psql:
|
60
|
+
|
61
|
+
hk logs f-p
|
62
|
+
# heroku logs --tail --app=foo-production
|
63
|
+
|
64
|
+
hk console f-p
|
65
|
+
# heroku run rails c --app=foo-production
|
66
|
+
|
67
|
+
hk psql f-p
|
68
|
+
# heroku pg:psql --app=foo-production
|
69
|
+
|
70
|
+
Unknown commands will pass through, but app derivation will still take place:
|
71
|
+
|
72
|
+
hk run rake db:migrate f-s
|
73
|
+
# heroku run rake db:migrate --app=foo-staging
|
74
|
+
|
75
|
+
You can also be explicit about where `heroku` is you don't want to rely on your PATH:
|
76
|
+
|
77
|
+
hk --heroku=/sbin/herkou logs f-p
|
78
|
+
# /sbin/heroku logs --tail --app=foo-production
|
79
|
+
|
80
|
+
And, you can skip all the magic if you like:
|
81
|
+
|
82
|
+
hk -n --heroku=/sbin/herkou pg:info --app=hellblazer
|
83
|
+
# sbin/herkou pg:info --app=hellblazer
|
84
|
+
|
85
|
+
Note that because this is backed by GLI, you only need to specify the command-name with enough characters to disambiguate it. For example, given the three builtins, these two are equivalent:
|
86
|
+
|
87
|
+
|
88
|
+
hk logs f-p
|
89
|
+
hk l f-p
|
90
|
+
|
91
|
+
## AUTHOR
|
92
|
+
|
93
|
+
David Copeland, davec (at) naildrivin5.com
|
94
|
+
|
95
|
+
## COPYRIGHT
|
96
|
+
|
97
|
+
hk is copyright(c) 2012 by David Copeland, released under the Apache license.
|
98
|
+
|
99
|
+
## SEE ALSO
|
100
|
+
|
101
|
+
* Source on github: https://github.com/davetron5000/hk
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class DefaultTest < Clean::Test::TestCase
|
4
|
+
|
5
|
+
test_that "we can derive the app name when it's unambiguous" do
|
6
|
+
Given {
|
7
|
+
@existing_apps = %w(foo-production foo-staging blah-production)
|
8
|
+
}
|
9
|
+
Given :an_app_name_deriver
|
10
|
+
When {
|
11
|
+
@app_name = @app_name_deriver.derive("f-p")
|
12
|
+
}
|
13
|
+
Then {
|
14
|
+
assert_equal @app_name,"foo-production"
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
test_that "if there are no matches, we get an exception" do
|
19
|
+
Given {
|
20
|
+
@existing_apps = %w(foo-production foo-staging blah-production)
|
21
|
+
}
|
22
|
+
Given :an_app_name_deriver
|
23
|
+
When {
|
24
|
+
@code = ->() { @app_name_deriver.derive("asdfasdf") }
|
25
|
+
}
|
26
|
+
Then {
|
27
|
+
exception = assert_raises(RuntimeError,&@code)
|
28
|
+
assert_match exception.message,/No such app/
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
test_that "if there are multiple matches, we get an exception" do
|
33
|
+
Given {
|
34
|
+
@existing_apps = %w(foo-production foo-staging foobar-production)
|
35
|
+
}
|
36
|
+
Given :an_app_name_deriver
|
37
|
+
When {
|
38
|
+
@code = ->() { @app_name_deriver.derive("f-p") }
|
39
|
+
}
|
40
|
+
Then {
|
41
|
+
exception = assert_raises(RuntimeError,&@code)
|
42
|
+
assert_match exception.message,/Ambiguous app name/
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
test_that "an exact match always succeeds" do
|
47
|
+
Given {
|
48
|
+
@existing_apps = %w(foo-production foobar-production)
|
49
|
+
}
|
50
|
+
Given :an_app_name_deriver
|
51
|
+
When {
|
52
|
+
@app_name = @app_name_deriver.derive("foo-production")
|
53
|
+
}
|
54
|
+
Then {
|
55
|
+
assert_equal @app_name,"foo-production"
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
test_that "a match without the environment works" do
|
60
|
+
Given {
|
61
|
+
@existing_apps = %w(foo-production foobar)
|
62
|
+
}
|
63
|
+
Given :an_app_name_deriver
|
64
|
+
When {
|
65
|
+
@app_name = @app_name_deriver.derive("f")
|
66
|
+
}
|
67
|
+
Then {
|
68
|
+
assert_equal @app_name,"foobar"
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def an_app_name_deriver
|
75
|
+
@app_name_deriver = Hk::AppNameDeriver.new(FakeLister.new(@existing_apps))
|
76
|
+
end
|
77
|
+
|
78
|
+
class FakeLister
|
79
|
+
def initialize(apps)
|
80
|
+
@apps = apps
|
81
|
+
end
|
82
|
+
def list_apps(*)
|
83
|
+
@apps
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,232 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hk
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Your Name Here
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-08-12 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: clean_test
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rdoc
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: aruba
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: ronn
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: gli
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ~>
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '2'
|
102
|
+
type: :runtime
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ~>
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '2'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: gem-man
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
description:
|
127
|
+
email: your@email.address.com
|
128
|
+
executables:
|
129
|
+
- !binary |-
|
130
|
+
aGs=
|
131
|
+
extensions: []
|
132
|
+
extra_rdoc_files: []
|
133
|
+
files:
|
134
|
+
- !binary |-
|
135
|
+
LmdpdGlnbm9yZQ==
|
136
|
+
- !binary |-
|
137
|
+
LnJ1YnktZ2Vtc2V0
|
138
|
+
- !binary |-
|
139
|
+
LnJ1YnktdmVyc2lvbg==
|
140
|
+
- !binary |-
|
141
|
+
R2VtZmlsZQ==
|
142
|
+
- !binary |-
|
143
|
+
R2VtZmlsZS5sb2Nr
|
144
|
+
- !binary |-
|
145
|
+
UkVBRE1FLm1k
|
146
|
+
- !binary |-
|
147
|
+
UmFrZWZpbGU=
|
148
|
+
- !binary |-
|
149
|
+
YmluL2hr
|
150
|
+
- !binary |-
|
151
|
+
ZmVhdHVyZXMvaGsuZmVhdHVyZQ==
|
152
|
+
- !binary |-
|
153
|
+
ZmVhdHVyZXMvc3RlcF9kZWZpbml0aW9ucy9oa19zdGVwcy5yYg==
|
154
|
+
- !binary |-
|
155
|
+
ZmVhdHVyZXMvc3VwcG9ydC9lbnYucmI=
|
156
|
+
- !binary |-
|
157
|
+
ZmVhdHVyZXMvc3VwcG9ydC9mYWtlX2hlcm9rdS5yYg==
|
158
|
+
- !binary |-
|
159
|
+
aGsuZ2Vtc3BlYw==
|
160
|
+
- !binary |-
|
161
|
+
bGliL2hrLnJi
|
162
|
+
- !binary |-
|
163
|
+
bGliL2hrL2FwcF9saXN0ZXIucmI=
|
164
|
+
- !binary |-
|
165
|
+
bGliL2hrL2FwcF9uYW1lX2Rlcml2ZXIucmI=
|
166
|
+
- !binary |-
|
167
|
+
bGliL2hrL2dsb2JhbF9vcHRpb25zLnJi
|
168
|
+
- !binary |-
|
169
|
+
bGliL2hrL2hlcm9rdV9jb21tYW5kLnJi
|
170
|
+
- !binary |-
|
171
|
+
bGliL2hrL2hlcm9rdV9ydW5uZXIucmI=
|
172
|
+
- !binary |-
|
173
|
+
bGliL2hrL3ZlcnNpb24ucmI=
|
174
|
+
- !binary |-
|
175
|
+
bGliL3Jha2UvYnVuZGxlci5yYg==
|
176
|
+
- !binary |-
|
177
|
+
bGliL3Jha2UvY3VjdW1iZXIucmI=
|
178
|
+
- !binary |-
|
179
|
+
bGliL3Jha2UvbWFuLnJi
|
180
|
+
- !binary |-
|
181
|
+
bGliL3Jha2UvdGVzdC5yYg==
|
182
|
+
- !binary |-
|
183
|
+
bWFuL2hrLjE=
|
184
|
+
- !binary |-
|
185
|
+
bWFuL2hrLjEucm9ubg==
|
186
|
+
- !binary |-
|
187
|
+
dGVzdC9hcHBfbmFtZV9kZXJpdmVyX3Rlc3QucmI=
|
188
|
+
- !binary |-
|
189
|
+
dGVzdC90ZXN0X2hlbHBlci5yYg==
|
190
|
+
homepage: http://your.website.com
|
191
|
+
licenses: []
|
192
|
+
post_install_message:
|
193
|
+
rdoc_options: []
|
194
|
+
require_paths:
|
195
|
+
- lib
|
196
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
197
|
+
none: false
|
198
|
+
requirements:
|
199
|
+
- - ! '>='
|
200
|
+
- !ruby/object:Gem::Version
|
201
|
+
version: '0'
|
202
|
+
segments:
|
203
|
+
- 0
|
204
|
+
hash: -3261507201375033656
|
205
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
206
|
+
none: false
|
207
|
+
requirements:
|
208
|
+
- - ! '>='
|
209
|
+
- !ruby/object:Gem::Version
|
210
|
+
version: '0'
|
211
|
+
segments:
|
212
|
+
- 0
|
213
|
+
hash: -3261507201375033656
|
214
|
+
requirements: []
|
215
|
+
rubyforge_project:
|
216
|
+
rubygems_version: 1.8.25
|
217
|
+
signing_key:
|
218
|
+
specification_version: 3
|
219
|
+
summary: A description of your project
|
220
|
+
test_files:
|
221
|
+
- !binary |-
|
222
|
+
ZmVhdHVyZXMvaGsuZmVhdHVyZQ==
|
223
|
+
- !binary |-
|
224
|
+
ZmVhdHVyZXMvc3RlcF9kZWZpbml0aW9ucy9oa19zdGVwcy5yYg==
|
225
|
+
- !binary |-
|
226
|
+
ZmVhdHVyZXMvc3VwcG9ydC9lbnYucmI=
|
227
|
+
- !binary |-
|
228
|
+
ZmVhdHVyZXMvc3VwcG9ydC9mYWtlX2hlcm9rdS5yYg==
|
229
|
+
- !binary |-
|
230
|
+
dGVzdC9hcHBfbmFtZV9kZXJpdmVyX3Rlc3QucmI=
|
231
|
+
- !binary |-
|
232
|
+
dGVzdC90ZXN0X2hlbHBlci5yYg==
|