crab 0.1.7 → 0.1.8
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/.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
|