crab 0.1.7 → 0.1.8
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/README.md +0 -1
- data/Rakefile +19 -4
- data/bin/crab-add +19 -0
- data/bin/crab-change +61 -0
- data/bin/crab-create +19 -0
- data/bin/crab-del +22 -0
- data/bin/crab-delete +22 -0
- data/bin/crab-find +27 -0
- data/bin/crab-login +25 -0
- data/bin/crab-move +26 -0
- data/bin/crab-mv +26 -0
- data/bin/crab-project +35 -0
- data/bin/crab-pull +28 -0
- data/bin/crab-remove +22 -0
- data/bin/crab-rm +22 -0
- data/bin/crab-show +20 -0
- data/bin/crab-tc +79 -0
- data/bin/crab-testcase +79 -0
- data/bin/crab-truncate +8 -0
- data/bin/crab-up +61 -0
- data/bin/crab-update +61 -0
- data/crab.gemspec +2 -0
- data/features/move-in-rally.feature +15 -0
- data/features/steps/rally_steps.rb +13 -5
- data/features/subcommand-help.feature +10 -10
- data/lib/crab.rb +0 -12
- data/lib/crab/cli.rb +7 -3
- data/lib/crab/utilities.rb +18 -1
- data/lib/crab/version.rb +1 -1
- metadata +43 -14
- data/lib/crab/commands/create.rb +0 -27
- data/lib/crab/commands/delete.rb +0 -31
- data/lib/crab/commands/find.rb +0 -36
- data/lib/crab/commands/login.rb +0 -30
- data/lib/crab/commands/move.rb +0 -46
- data/lib/crab/commands/project.rb +0 -46
- data/lib/crab/commands/pull.rb +0 -37
- data/lib/crab/commands/show.rb +0 -25
- data/lib/crab/commands/testcase.rb +0 -101
- data/lib/crab/commands/update.rb +0 -80
data/lib/crab/commands/create.rb
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
module Crab::Commands
|
2
|
-
|
3
|
-
class Create
|
4
|
-
|
5
|
-
def initialize(global_opts, args)
|
6
|
-
@global_opts = global_opts
|
7
|
-
@args = args
|
8
|
-
@cmd_opts = Trollop::options do
|
9
|
-
banner "crab create: create a new story in Rally
|
10
|
-
|
11
|
-
Usage: crab [options] create name [options]"
|
12
|
-
end
|
13
|
-
@rally = Crab::Rally.new
|
14
|
-
end
|
15
|
-
|
16
|
-
def run
|
17
|
-
name = @args.join(" ")
|
18
|
-
Trollop::die "Please specify a name for the story" if name.blank?
|
19
|
-
|
20
|
-
@rally.connect
|
21
|
-
story = @rally.create_story :name => name
|
22
|
-
|
23
|
-
puts "#{story.formatted_id}: #{story.name} (#{story.state})"
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
27
|
-
end
|
data/lib/crab/commands/delete.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
module Crab::Commands
|
2
|
-
|
3
|
-
class Delete
|
4
|
-
|
5
|
-
def initialize(global_opts, args)
|
6
|
-
@global_opts = global_opts
|
7
|
-
@args = args
|
8
|
-
|
9
|
-
@cmd_opts = Trollop::options do
|
10
|
-
banner "crab delete: delete an existing story in Rally
|
11
|
-
|
12
|
-
Usage: crab [options] delete story [options]"
|
13
|
-
end
|
14
|
-
|
15
|
-
@rally = Crab::Rally.new
|
16
|
-
end
|
17
|
-
|
18
|
-
def run
|
19
|
-
story_id = @args.join(" ")
|
20
|
-
Trollop::die "Story ID must be specified" if story_id.blank?
|
21
|
-
|
22
|
-
@rally.connect
|
23
|
-
story = @rally.find_story_with_id story_id
|
24
|
-
|
25
|
-
story.delete
|
26
|
-
|
27
|
-
puts "Story #{story_id} deleted."
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|
31
|
-
end
|
data/lib/crab/commands/find.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
module Crab::Commands
|
2
|
-
|
3
|
-
class Find
|
4
|
-
|
5
|
-
include Crab::Utilities
|
6
|
-
|
7
|
-
def initialize(global_opts, args)
|
8
|
-
@global_opts = global_opts
|
9
|
-
@args = args
|
10
|
-
|
11
|
-
@cmd_opts = Trollop::options do
|
12
|
-
banner "crab find: find a story in Rally
|
13
|
-
|
14
|
-
Usage: crab [options] find [options] [text]"
|
15
|
-
opt :project, "Project to use (required unless set by 'crab project')", :short => "-p", :type => String
|
16
|
-
end
|
17
|
-
|
18
|
-
@rally = Crab::Rally.new
|
19
|
-
end
|
20
|
-
|
21
|
-
def run
|
22
|
-
pattern = @args.map(&:strip).reject(&:empty?)
|
23
|
-
project_name = valid_project_name(@cmd_opts)
|
24
|
-
|
25
|
-
@rally.connect
|
26
|
-
|
27
|
-
project = @rally.find_project(project_name)
|
28
|
-
|
29
|
-
Trollop::die "Project #{@cmd_opts[:project].inspect} not found" if project.nil?
|
30
|
-
|
31
|
-
@rally.find_stories(project, pattern).each do |story|
|
32
|
-
puts "#{story.formatted_id}: #{story.name} (#{story.state})"
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
data/lib/crab/commands/login.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
module Crab::Commands
|
2
|
-
|
3
|
-
class Login
|
4
|
-
|
5
|
-
include Crab::Utilities
|
6
|
-
|
7
|
-
def initialize(global_opts, args)
|
8
|
-
@global_opts = global_opts
|
9
|
-
@cmd_opts = Trollop::options do
|
10
|
-
banner "crab login: logs into Rally
|
11
|
-
|
12
|
-
Usage: crab [options] login"
|
13
|
-
opt :username, "Username", :type => String, :short => "-u"
|
14
|
-
opt :password, "Password", :type => String, :short => "-p"
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def run
|
19
|
-
username = @cmd_opts[:username_given] ? @cmd_opts[:username] : ask("Username: ")
|
20
|
-
password = @cmd_opts[:password_given] ? @cmd_opts[:password] : ask("Password: ") {|q| q.echo = false }
|
21
|
-
|
22
|
-
File.open(credentials_file, 'w') do |file|
|
23
|
-
file.puts username
|
24
|
-
file.puts password
|
25
|
-
end
|
26
|
-
|
27
|
-
puts "Logged in as #{username}"
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
data/lib/crab/commands/move.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
module Crab::Commands
|
2
|
-
|
3
|
-
class Move
|
4
|
-
|
5
|
-
include Crab::Utilities
|
6
|
-
|
7
|
-
def initialize(global_opts, args)
|
8
|
-
@global_opts = global_opts
|
9
|
-
@args = args
|
10
|
-
|
11
|
-
@cmd_opts = Trollop::options do
|
12
|
-
banner "crab move: move a story from one status to the next (or previous)
|
13
|
-
|
14
|
-
Usage: crab [options] move story [options]"
|
15
|
-
opt :back, "Move story backwards (from accepted to completed, for example)"
|
16
|
-
end
|
17
|
-
|
18
|
-
@rally = Crab::Rally.new
|
19
|
-
end
|
20
|
-
|
21
|
-
def run
|
22
|
-
story_id = @args.join(" ")
|
23
|
-
Trollop::die "No story given" if story_id.empty?
|
24
|
-
|
25
|
-
@rally.connect
|
26
|
-
|
27
|
-
story = @rally.find_story_with_id story_id
|
28
|
-
state = state_from(story.state)
|
29
|
-
|
30
|
-
story.update :schedule_state => (@cmd_opts[:back] ? state_before(state) : state_after(state))
|
31
|
-
|
32
|
-
puts "#{story.formatted_id}: #{story.name} (#{story.state})"
|
33
|
-
end
|
34
|
-
|
35
|
-
def state_before(state)
|
36
|
-
i = (Crab::Story::VALID_STATES.index(state) || 0) - 1
|
37
|
-
Crab::Story::VALID_STATES[i < 0 ? 0 : i]
|
38
|
-
end
|
39
|
-
|
40
|
-
def state_after(state)
|
41
|
-
i = (Crab::Story::VALID_STATES.index(state) || 0) + 1
|
42
|
-
max = Crab::Story::VALID_STATES.size
|
43
|
-
Crab::Story::VALID_STATES[i >= max ? max -1 : i]
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
module Crab::Commands
|
2
|
-
class Project
|
3
|
-
|
4
|
-
def self.current_project_name
|
5
|
-
if File.exists? ".crab/project"
|
6
|
-
File.read(".crab/project").strip
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
def initialize(global_opts, args)
|
11
|
-
@global_opts = global_opts
|
12
|
-
@args = args
|
13
|
-
|
14
|
-
@cmd_opts = Trollop::options do
|
15
|
-
banner "crab project: persistently select project to work with in Rally
|
16
|
-
|
17
|
-
Usage: crab [options] project name"
|
18
|
-
end
|
19
|
-
|
20
|
-
@rally = Crab::Rally.new
|
21
|
-
end
|
22
|
-
|
23
|
-
def run
|
24
|
-
current_project_name = self.class.current_project_name
|
25
|
-
if current_project_name.present?
|
26
|
-
puts current_project_name
|
27
|
-
|
28
|
-
elsif @args.reject {|arg| arg.blank? }.empty?
|
29
|
-
puts "No project currently selected."
|
30
|
-
|
31
|
-
else
|
32
|
-
name = @args.join(" ").strip
|
33
|
-
|
34
|
-
@rally.connect
|
35
|
-
|
36
|
-
project = @rally.find_project name
|
37
|
-
Trollop::die "#{name.inspect} is not a valid project" if project.nil?
|
38
|
-
|
39
|
-
FileUtils.mkdir_p ".crab"
|
40
|
-
File.open(".crab/project", "w") do |file|
|
41
|
-
file.puts project.name
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
data/lib/crab/commands/pull.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
module Crab::Commands
|
2
|
-
|
3
|
-
class Pull
|
4
|
-
|
5
|
-
def initialize(global_opts, args)
|
6
|
-
@global_opts = global_opts
|
7
|
-
@story_numbers = args
|
8
|
-
|
9
|
-
@cmd_opts = Trollop::options do
|
10
|
-
banner "crab pull: pulls stories from Rally and writes them out as Cucumber features
|
11
|
-
|
12
|
-
Usage: crab [options] pull story1 [story2 ...]"
|
13
|
-
opt :language, "Language to generate Cucumber features in (ISO code)", :default => "en", :short => "-l"
|
14
|
-
end
|
15
|
-
|
16
|
-
@rally = Crab::Rally.new
|
17
|
-
end
|
18
|
-
|
19
|
-
def run
|
20
|
-
@rally.connect
|
21
|
-
|
22
|
-
@story_numbers.each do |story_number|
|
23
|
-
story = @rally.find_story_with_id story_number
|
24
|
-
Trollop::die "Could not find story with ID #{story_number}" if story.nil?
|
25
|
-
|
26
|
-
puts "#{story.formatted_id}: #{story.full_file_name}"
|
27
|
-
|
28
|
-
FileUtils.mkdir_p File.dirname(story.full_file_name)
|
29
|
-
FileUtils.touch story.full_file_name
|
30
|
-
|
31
|
-
File.open(story.full_file_name, "w") do |file|
|
32
|
-
file.write Crab::CucumberFeature.new(@cmd_opts[:language]).generate_from story
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
data/lib/crab/commands/show.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
module Crab::Commands
|
2
|
-
|
3
|
-
class Show
|
4
|
-
def initialize(global_opts, args)
|
5
|
-
@global_opts = global_opts
|
6
|
-
@cmd_opts = Trollop::options do
|
7
|
-
banner "crab show: displays a story in Rally as a Cucumber feature
|
8
|
-
|
9
|
-
Usage: crab [options] show story"
|
10
|
-
opt :language, "Language to display Cucumber features in (ISO code)", :default => "en", :short => "-l"
|
11
|
-
end
|
12
|
-
|
13
|
-
@story_id = args.first
|
14
|
-
@rally = Crab::Rally.new
|
15
|
-
end
|
16
|
-
|
17
|
-
def run
|
18
|
-
@rally.connect
|
19
|
-
|
20
|
-
story = @rally.find_story_with_id @story_id
|
21
|
-
|
22
|
-
puts Crab::CucumberFeature.new(@cmd_opts[:language]).generate_from story
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,101 +0,0 @@
|
|
1
|
-
module Crab::Commands
|
2
|
-
|
3
|
-
class Testcase
|
4
|
-
|
5
|
-
def initialize(global_opts, args)
|
6
|
-
@global_opts = global_opts
|
7
|
-
@args = args
|
8
|
-
@rally = Crab::Rally.new
|
9
|
-
|
10
|
-
@cmd_opts = Trollop::options do
|
11
|
-
banner "crab testcase: manage test cases in a story (add, update, delete)
|
12
|
-
|
13
|
-
Usage: crab [options] testcase add story name [options]
|
14
|
-
crab [options] testcase update testcase [options]
|
15
|
-
crab [options] testcase delete testcase [options]"
|
16
|
-
|
17
|
-
stop_on %w{add update delete}
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def run
|
22
|
-
sub = ARGV.shift
|
23
|
-
case sub
|
24
|
-
when "add"
|
25
|
-
opts = Trollop::options do
|
26
|
-
banner "crab testcase add: add a test case to a story in Rally"
|
27
|
-
opt :priority, "Priority (one of: #{Crab::TestCase::PRIORITIES.join(" ")}", :default => "important", :short => '-p'
|
28
|
-
opt :risk, "Risk (one of: #{Crab::TestCase::RISKS.join(" ")})", :default => "medium", :short => '-r'
|
29
|
-
opt :method, "Method (one of: #{Crab::TestCase::METHODS.join(" ")})", :default => "automated", :short => '-m'
|
30
|
-
opt :type, "Type (one of: #{Crab::TestCase::TYPES.join(" ")})", :default => "acceptance", :short => '-t'
|
31
|
-
opt :pre, "Pre-conditions", :default => "N/A"
|
32
|
-
opt :post, "Post-conditions", :default => "N/A"
|
33
|
-
opt :desc, "Description", :default => "N/A", :short => '-d'
|
34
|
-
end
|
35
|
-
|
36
|
-
story_id = ARGV.shift
|
37
|
-
name = ARGV.join(" ")
|
38
|
-
add(story_id, name, opts)
|
39
|
-
|
40
|
-
when "update"
|
41
|
-
opts = Trollop::options do
|
42
|
-
banner "crab testcase update: update a test case in Rally"
|
43
|
-
opt :priority, "Priority (one of: #{Crab::TestCase::PRIORITIES.join(" ")}", :default => "important", :short => '-p'
|
44
|
-
opt :risk, "Risk (one of: #{Crab::TestCase::RISKS.join(" ")})", :default => "medium", :short => '-r'
|
45
|
-
opt :method, "Method (one of: #{Crab::TestCase::METHODS.join(" ")})", :default => "automated", :short => '-m'
|
46
|
-
opt :type, "Type (one of: #{Crab::TestCase::TYPES.join(" ")})", :default => "acceptance", :short => '-t'
|
47
|
-
opt :pre, "Pre-conditions", :default => "N/A"
|
48
|
-
opt :post, "Post-conditions", :default => "N/A"
|
49
|
-
opt :desc, "Description", :default => "N/A", :short => '-d'
|
50
|
-
end
|
51
|
-
|
52
|
-
tc_id = ARGV.shift
|
53
|
-
update(tc_id, opts)
|
54
|
-
|
55
|
-
when "delete"
|
56
|
-
Trollop::options do
|
57
|
-
banner "crab testcase delete: delete a test case in Rally"
|
58
|
-
end
|
59
|
-
|
60
|
-
tc_id = ARGV.shift
|
61
|
-
delete(tc_id)
|
62
|
-
|
63
|
-
else
|
64
|
-
Trollop::die "Unknown subcommand#{' ' + sub.inspect if sub}"
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def add(story_id, name, opts)
|
69
|
-
@rally.connect
|
70
|
-
tc = @rally.create_test_case(story_id, name, sanitize_options(opts))
|
71
|
-
|
72
|
-
puts "#{tc.story.formatted_id}/#{tc.formatted_id}: #{tc.name} (#{tc.tags.join(" ")})"
|
73
|
-
end
|
74
|
-
|
75
|
-
def update(tc_id, opts)
|
76
|
-
@rally.connect
|
77
|
-
tc = @rally.find_test_case(tc_id)
|
78
|
-
tc.update(sanitize_options(opts))
|
79
|
-
puts "#{tc.story.formatted_id}/#{tc.formatted_id}: #{tc.name} (#{tc.tags.join(" ")})"
|
80
|
-
end
|
81
|
-
|
82
|
-
def delete(tc_id)
|
83
|
-
@rally.connect
|
84
|
-
tc = @rally.find_test_case(tc_id)
|
85
|
-
tc.delete
|
86
|
-
puts "Test case #{tc_id} deleted."
|
87
|
-
end
|
88
|
-
|
89
|
-
def sanitize_options(opts, creating=true)
|
90
|
-
result = {}
|
91
|
-
result[:priority] = opts[:priority].capitalize if creating || opts[:priority_given]
|
92
|
-
result[:risk] = opts[:risk].capitalize if creating || opts[:risk_given]
|
93
|
-
result[:method] = opts[:method].capitalize if creating || opts[:method_given]
|
94
|
-
result[:type] = opts[:type].capitalize if creating || opts[:type_given]
|
95
|
-
result[:pre_conditions] = opts[:pre] if creating || opts[:pre_given]
|
96
|
-
result[:post_conditions] = opts[:post] if creating || opts[:post_given]
|
97
|
-
result[:description] = opts[:desc] if creating || opts[:desc_given]
|
98
|
-
result
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
data/lib/crab/commands/update.rb
DELETED
@@ -1,80 +0,0 @@
|
|
1
|
-
module Crab::Commands
|
2
|
-
|
3
|
-
class Update
|
4
|
-
|
5
|
-
include Crab::Utilities
|
6
|
-
|
7
|
-
def initialize(global_opts, args)
|
8
|
-
@global_opts = global_opts
|
9
|
-
@args = args
|
10
|
-
|
11
|
-
@cmd_opts = Trollop::options do
|
12
|
-
banner "crab update: update a story in Rally
|
13
|
-
|
14
|
-
Usage: crab [options] update story [options]"
|
15
|
-
opt :name, "Name (title)", :type => String, :short => "-n"
|
16
|
-
opt :state, "State (one of: #{Crab::Story::VALID_STATES.join(" ")})", :type => String, :short => "-t"
|
17
|
-
opt :estimate, "Estimate", :type => :int, :short => "-e"
|
18
|
-
opt :iteration, "Iteration", :type => String, :short => "-i"
|
19
|
-
opt :release, "Release", :type => String, :short => "-r"
|
20
|
-
opt :blocked, "Blocked", :short => "-b"
|
21
|
-
opt :unblocked, "Unblocked", :short => "-u"
|
22
|
-
opt :parent, "Parent", :type => String, :short => "-p"
|
23
|
-
end
|
24
|
-
|
25
|
-
@rally = Crab::Rally.new
|
26
|
-
end
|
27
|
-
|
28
|
-
def run
|
29
|
-
opts = validate_and_fix_up_arguments
|
30
|
-
|
31
|
-
@rally.connect
|
32
|
-
|
33
|
-
story = @rally.find_story_with_id @args.first
|
34
|
-
opts = validate_and_fix_up_arguments_with_rally(story, opts)
|
35
|
-
|
36
|
-
story.update opts
|
37
|
-
|
38
|
-
puts "#{story.formatted_id}: #{story.name} (#{story.state})"
|
39
|
-
end
|
40
|
-
|
41
|
-
def validate_and_fix_up_arguments
|
42
|
-
Trollop::die "No story given" if @args.empty?
|
43
|
-
Trollop::die "Nothing to update. Please provide some options" unless @cmd_opts.any? {|k, v| k.to_s =~ /_given$/ }
|
44
|
-
|
45
|
-
opts = {}
|
46
|
-
opts[:name] = @cmd_opts[:name] if @cmd_opts[:name_given]
|
47
|
-
opts[:schedule_state] = state_from(@cmd_opts[:state]) if @cmd_opts[:state_given]
|
48
|
-
|
49
|
-
if @cmd_opts[:estimate_given]
|
50
|
-
opts[:plan_estimate] = @cmd_opts[:estimate] # nobody is going to remember "Plan Estimate", really
|
51
|
-
end
|
52
|
-
|
53
|
-
opts[:blocked] = @cmd_opts[:blocked] if @cmd_opts[:blocked_given]
|
54
|
-
opts[:blocked] = !@cmd_opts[:unblocked] if @cmd_opts[:unblocked_given]
|
55
|
-
|
56
|
-
opts
|
57
|
-
end
|
58
|
-
|
59
|
-
def validate_and_fix_up_arguments_with_rally(story, opts)
|
60
|
-
if @cmd_opts[:iteration_given]
|
61
|
-
opts[:iteration] = @rally.find_iteration_by_name @cmd_opts[:iteration]
|
62
|
-
Trollop::die "Unknown iteration \"#{@cmd_opts[:iteration]}\"" if opts[:iteration].nil?
|
63
|
-
end
|
64
|
-
|
65
|
-
if @cmd_opts[:release_given]
|
66
|
-
opts[:release] = @rally.find_release_by_name @cmd_opts[:release]
|
67
|
-
Trollop::die "Unknown release \"#{@cmd_opts[:release]}\"" if opts[:release].nil?
|
68
|
-
end
|
69
|
-
|
70
|
-
if @cmd_opts[:parent_given]
|
71
|
-
opts[:parent] = @rally.find_story_with_id(@cmd_opts[:parent]).rally_object
|
72
|
-
Trollop::die "Unknown story \"#{@cmd_opts[:parent]}\"" if opts[:parent].nil?
|
73
|
-
end
|
74
|
-
|
75
|
-
opts[:name] = story.name if opts[:name].blank?
|
76
|
-
opts
|
77
|
-
end
|
78
|
-
|
79
|
-
end
|
80
|
-
end
|