schubert-minglr 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/Rakefile +2 -0
  2. data/VERSION.yml +2 -2
  3. data/bin/minglr +11 -11
  4. data/bin/mtx +1 -1
  5. data/lib/minglr.rb +18 -10
  6. data/lib/minglr/action.rb +75 -0
  7. data/lib/minglr/config_parser.rb +49 -0
  8. data/lib/minglr/extensions/array.rb +23 -0
  9. data/lib/minglr/input_cache.rb +3 -3
  10. data/lib/minglr/options_parser.rb +79 -0
  11. data/lib/minglr/resources/attachment.rb +46 -0
  12. data/lib/minglr/resources/base.rb +42 -0
  13. data/lib/minglr/resources/card.rb +107 -0
  14. data/lib/minglr/resources/project.rb +25 -0
  15. data/lib/minglr/resources/property_definition.rb +12 -0
  16. data/lib/minglr/resources/transition_execution.rb +6 -0
  17. data/lib/minglr/resources/user.rb +25 -0
  18. data/minglr.gemspec +30 -28
  19. data/minglrconfig.sample +19 -0
  20. data/test/extensions/array_test.rb +41 -0
  21. data/test/resources/attachment_test.rb +40 -0
  22. data/test/resources/base_test.rb +45 -0
  23. data/test/resources/card_test.rb +89 -0
  24. data/test/resources/project_test.rb +26 -0
  25. data/test/resources/property_definition_test.rb +25 -0
  26. data/test/resources/user_test.rb +39 -0
  27. data/test/test_helper.rb +15 -5
  28. metadata +27 -15
  29. data/lib/minglr/attachment.rb +0 -7
  30. data/lib/minglr/card.rb +0 -2
  31. data/lib/minglr/mingle_resource.rb +0 -5
  32. data/lib/minglr/minglr_action.rb +0 -200
  33. data/lib/minglr/minglr_config_parser.rb +0 -44
  34. data/lib/minglr/minglr_options_parser.rb +0 -70
  35. data/lib/minglr/property_definition.rb +0 -2
  36. data/lib/minglr/transition_execution.rb +0 -2
  37. data/lib/minglr/user.rb +0 -2
  38. data/test/attachment_test.rb +0 -24
  39. data/test/minglr_resource_test.rb +0 -24
@@ -0,0 +1,107 @@
1
+ module Resources
2
+
3
+ class Card < Base
4
+
5
+ def self.create(options = {}, status_property = nil)
6
+ options.merge!({status_property.to_sym => "New"}) if status_property
7
+ card = self.new(options)
8
+ if card.save
9
+ card.reload
10
+ puts "Card #{card.number} created"
11
+ else
12
+ warn "Unable to create card"
13
+ end
14
+ end
15
+
16
+ def self.move(card_number, options = {}, config = {})
17
+ if card_to_move = find(card_number)
18
+ transition_options = { :card => card_number }
19
+ transition_options.merge!({ :comment => options[:comment]}) if options[:comment]
20
+ current_status = card_to_move.send(config[:status_property]) if config[:status_property]
21
+ next_transition = nil
22
+
23
+ card_type = card_to_move.card_type_name.downcase
24
+ case card_type
25
+ when /defect/
26
+ status_states = config.select do |key, value|
27
+ key.to_s =~ /^defect/
28
+ end
29
+ when /task/
30
+ status_states = config.select do |key, value|
31
+ key.to_s =~ /^task_state_/
32
+ end
33
+ when /story/
34
+ status_states = config.select do |key, value|
35
+ key.to_s =~ /^story_state/
36
+ end
37
+ else
38
+ puts "No transitions defined for card of type #{card_to_move.card_type_name}"
39
+ end
40
+ status_states = status_states.collect {|state| state.last }.collect {|state| state.split(">").collect { |value| value.strip } }
41
+ next_transition = status_states.select {|state| state.first.downcase == current_status.downcase }.first.last
42
+ transition_options.merge!({ :transition => next_transition })
43
+
44
+ if response = TransitionExecution.create(transition_options)
45
+ if response.attributes["status"] == "completed"
46
+ puts "Moved card from #{current_status} to #{next_transition}"
47
+ end
48
+ end
49
+ else
50
+ warn "No card #{card_number} found to move"
51
+ end
52
+ end
53
+
54
+ def self.print_all(options = [], status_property = nil)
55
+ attributes = [:number, :card_type_name, status_property, :name].compact
56
+ cards = Resources::Card.find(:all)
57
+ cards.send(:extend, Minglr::Extensions::Array)
58
+ cards = cards.filter(attributes, options)
59
+ if cards.any?
60
+ print_collection(cards, attributes)
61
+ else
62
+ warn "No cards found"
63
+ end
64
+ end
65
+
66
+ def self.print_card(card_number, status_property = nil)
67
+ attributes = [:number, :card_type_name, status_property, :name, :description].compact
68
+ if card = find(card_number)
69
+ puts card.to_s(status_property)
70
+ else
71
+ warn "No card ##{card_number} found"
72
+ end
73
+ end
74
+
75
+ def self.update(card_number, options = {})
76
+ if card_to_update = find(card_number)
77
+ options.each do |attribute, value|
78
+ card_to_update.send("#{attribute.to_s}=".to_sym, value)
79
+ end
80
+ card_to_update.save
81
+ puts "Card #{card_to_update.number} updated\n\n"
82
+ puts card.to_s
83
+ else
84
+ warn "Unable to update card #{card_number}"
85
+ end
86
+ end
87
+
88
+ def to_s(status_property = nil)
89
+ attachments = Resources::Attachment.find(:all, :params => { :card_number => number })
90
+ attachments = attachments.collect do |attachment|
91
+ "* #{attachment.file_name}: #{Resources::Base.site + attachment.url}"
92
+ end
93
+ output = <<-EOS
94
+ Number: #{number}
95
+ Name: #{name}
96
+ Type: #{card_type_name}
97
+ Status: #{send(status_property) if status_property}
98
+ Description: #{description}
99
+
100
+ Attachments:
101
+ #{attachments.join("\n")}
102
+ EOS
103
+ output
104
+ end
105
+
106
+ end
107
+ end
@@ -0,0 +1,25 @@
1
+ module Resources
2
+
3
+ class Project < Base
4
+
5
+ def self.configure
6
+ self.prefix = self.prefix.split("/")[0...-1].join("/")
7
+ self.site = self.prefix
8
+ end
9
+
10
+ def self.print_all(options = [], status_property = nil)
11
+ attributes = [:name, :description]
12
+ projects = find(:all)
13
+ projects.send(:extend, Minglr::Extensions::Array)
14
+ projects = projects.filter(attributes, options)
15
+
16
+ if projects.any?
17
+ print_collection projects, attributes
18
+ else
19
+ warn "No projects found"
20
+ end
21
+ end
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,12 @@
1
+ module Resources
2
+
3
+ class PropertyDefinition < Base
4
+
5
+ def self.project_options
6
+ properties = find(:all)
7
+ properties.collect { |property| [property.column_name.to_sym, property.name] }
8
+ end
9
+
10
+ end
11
+
12
+ end
@@ -0,0 +1,6 @@
1
+ module Resources
2
+
3
+ class TransitionExecution < Base
4
+ end
5
+
6
+ end
@@ -0,0 +1,25 @@
1
+ module Resources
2
+
3
+ class User < Base
4
+
5
+ def self.print_all(options = [])
6
+ attributes = [:login, :name, :email]
7
+ users = find(:all).collect! { |user| user.user }
8
+ users.send(:extend, Minglr::Extensions::Array)
9
+ users = users.filter(attributes, options)
10
+ if users.any?
11
+ print_collection users, attributes, :right
12
+ else
13
+ warn "No users in project"
14
+ end
15
+ end
16
+
17
+ def self.find_user_id_for_user(user)
18
+ if user = Resources::User.find(:all).select { |user| user.user.login == user }.first
19
+ user.user_id
20
+ end
21
+ end
22
+
23
+ end
24
+
25
+ end
data/minglr.gemspec CHANGED
@@ -1,12 +1,12 @@
1
- # -*- encoding: utf-8 -*-
2
-
3
1
  Gem::Specification.new do |s|
4
2
  s.name = %q{minglr}
5
- s.version = "1.1.0"
3
+ s.version = "1.2.0"
4
+
5
+ s.specification_version = 2 if s.respond_to? :specification_version=
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Michael Schubert", "Stephen Chu", "Chris O'Meara"]
9
- s.date = %q{2009-07-09}
9
+ s.date = %q{2009-07-26}
10
10
  s.description = %q{* This gem provides two executable binaries to interact with Mingle (http://mingle.thoughtworks.com/mingle-agile-project-management) through its API. It also has sample interactive Rake task on how to facilitate easy card movements when a card enters/exits the development queue. * mtx is a binary that facilities transition changes for use on rake tasks * minglr is a more interactive tool that provides a quick interface for many common uses}
11
11
  s.email = %q{michael@schubert.cx}
12
12
  s.executables = ["mtx", "minglr"]
@@ -25,23 +25,30 @@ Gem::Specification.new do |s|
25
25
  "bin/minglr",
26
26
  "bin/mtx",
27
27
  "lib/minglr.rb",
28
- "lib/minglr/attachment.rb",
29
- "lib/minglr/card.rb",
28
+ "lib/minglr/action.rb",
29
+ "lib/minglr/config_parser.rb",
30
+ "lib/minglr/extensions/array.rb",
30
31
  "lib/minglr/input_cache.rb",
31
- "lib/minglr/mingle_resource.rb",
32
- "lib/minglr/minglr_action.rb",
33
- "lib/minglr/minglr_config_parser.rb",
34
- "lib/minglr/minglr_options_parser.rb",
35
32
  "lib/minglr/mtx_options_parser.rb",
36
- "lib/minglr/property_definition.rb",
37
- "lib/minglr/transition_execution.rb",
38
- "lib/minglr/user.rb",
33
+ "lib/minglr/options_parser.rb",
34
+ "lib/minglr/resources/attachment.rb",
35
+ "lib/minglr/resources/base.rb",
36
+ "lib/minglr/resources/card.rb",
37
+ "lib/minglr/resources/project.rb",
38
+ "lib/minglr/resources/property_definition.rb",
39
+ "lib/minglr/resources/transition_execution.rb",
40
+ "lib/minglr/resources/user.rb",
39
41
  "minglr.gemspec",
40
42
  "minglrconfig.sample",
41
43
  "tasks/commit.sample.rake",
42
44
  "tasks/svn.sample.rake",
43
- "test/attachment_test.rb",
44
- "test/minglr_resource_test.rb",
45
+ "test/extensions/array_test.rb",
46
+ "test/resources/attachment_test.rb",
47
+ "test/resources/base_test.rb",
48
+ "test/resources/card_test.rb",
49
+ "test/resources/project_test.rb",
50
+ "test/resources/property_definition_test.rb",
51
+ "test/resources/user_test.rb",
45
52
  "test/test_helper.rb"
46
53
  ]
47
54
  s.has_rdoc = true
@@ -49,21 +56,16 @@ Gem::Specification.new do |s|
49
56
  s.post_install_message = %q{PostInstall.txt}
50
57
  s.rdoc_options = ["--charset=UTF-8"]
51
58
  s.require_paths = ["lib"]
52
- s.rubygems_version = %q{1.3.1}
59
+ s.rubygems_version = %q{1.0.1}
53
60
  s.summary = %q{command line user tool for Mingle (http://mingle.thoughtworks.com/mingle-agile-project-management)}
54
61
  s.test_files = [
55
- "test/attachment_test.rb",
56
- "test/minglr_resource_test.rb",
62
+ "test/extensions/array_test.rb",
63
+ "test/resources/attachment_test.rb",
64
+ "test/resources/base_test.rb",
65
+ "test/resources/card_test.rb",
66
+ "test/resources/project_test.rb",
67
+ "test/resources/property_definition_test.rb",
68
+ "test/resources/user_test.rb",
57
69
  "test/test_helper.rb"
58
70
  ]
59
-
60
- if s.respond_to? :specification_version then
61
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
62
- s.specification_version = 2
63
-
64
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
65
- else
66
- end
67
- else
68
- end
69
71
  end
data/minglrconfig.sample CHANGED
@@ -16,3 +16,22 @@
16
16
  task_state_3 = Dev In Progress > Story from Dev in Progress to Dev Complete
17
17
  story_checkout = story_state_1
18
18
  task_checkout = story_state_2
19
+
20
+ # Mingle Project Templates
21
+ # [blank]
22
+ # url = http://localhost:9090/projects/blank
23
+ #
24
+ # [agilehybrid]
25
+ # url = http://localhost:9090/projects/agilehybrid
26
+ # status_property = cp_status
27
+ #
28
+ # [scrum]
29
+ # url = http://localhost:9090/projects/scrum
30
+ # status_property = cp_status
31
+ #
32
+ # [storytracker]
33
+ # url = http://localhost:9090/projects/storytracker
34
+ # status_property = cp_status
35
+ #
36
+ # [xp]
37
+ # url = http://localhost:9090/projects/xp
@@ -0,0 +1,41 @@
1
+ require 'test_helper'
2
+
3
+ module Minglr
4
+ module Extensions
5
+
6
+ class ArrayTest < Test::Unit::TestCase
7
+
8
+ context Array do
9
+
10
+ context "filter" do
11
+
12
+ setup do
13
+ class TestObject
14
+ attr_accessor :name
15
+ end
16
+ @test1 = TestObject.new
17
+ @test2 = TestObject.new
18
+ @test1.name = "test1"
19
+ @test2.name = "test2"
20
+ @collection = [@test1, @test2]
21
+ @collection.send(:extend, Minglr::Extensions::Array)
22
+ end
23
+
24
+ should "include elements matching words in attributes" do
25
+ assert_equal [@test1], @collection.filter([:name], ["1"])
26
+ assert_equal [@test1, @test2], @collection.filter([:name], ["test"])
27
+ end
28
+
29
+ should "deal with empty words and attributes" do
30
+ assert_equal [@test1, @test2], @collection.filter([], [])
31
+ assert_equal [@test1, @test2], @collection.filter([:name], [])
32
+ assert_equal [], @collection.filter([], ["1"])
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,40 @@
1
+ require 'test_helper'
2
+
3
+ module Resources
4
+
5
+ class AttachmentTest < Test::Unit::TestCase
6
+
7
+ context Attachment do
8
+
9
+ context "configure" do
10
+
11
+ should "append to the site url" do
12
+ options = { :username => "user",
13
+ :password => "pass",
14
+ :url => "proto://somehost.com:1234/projects/my_project" }
15
+ Base.configure(options)
16
+ Attachment.configure
17
+ assert_equal "/projects/my_project/cards/1/", Attachment.prefix(:card_number => 1)
18
+ end
19
+
20
+ end
21
+
22
+ context "fetch" do
23
+
24
+ should_eventually "download all found attachments for a given card number" do
25
+ end
26
+
27
+ end
28
+
29
+ context "attach" do
30
+
31
+ should_eventually "upload file for a given card number" do
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+
40
+ end
@@ -0,0 +1,45 @@
1
+ require 'test_helper'
2
+
3
+ module Resources
4
+
5
+ class BaseTest < Test::Unit::TestCase
6
+
7
+ context Base do
8
+
9
+ context "configure" do
10
+
11
+ should "combine options to build url" do
12
+ options = { :username => "user",
13
+ :password => "pass",
14
+ :url => "proto://somehost.com:1234/projects/my_project" }
15
+ Base.configure(options)
16
+ assert_equal "proto://user:pass@somehost.com:1234/projects/my_project",
17
+ Base.site.to_s
18
+ end
19
+
20
+ end
21
+
22
+ context "warn" do
23
+
24
+ should "prepend message with warning" do
25
+ Base.expects(:puts).with("Warning: test")
26
+ Base.warn("test")
27
+ end
28
+
29
+ end
30
+
31
+ context "print_collection" do
32
+
33
+ should_eventually "print values of attributes of objects separated by dashes and aligning columns of values" do
34
+ end
35
+
36
+ should_eventually "allow for right adjusted values" do
37
+ end
38
+
39
+ end
40
+
41
+ end
42
+
43
+ end
44
+
45
+ end
@@ -0,0 +1,89 @@
1
+ require 'test_helper'
2
+
3
+ module Resources
4
+
5
+ class CardTest < Test::Unit::TestCase
6
+
7
+ context Card do
8
+
9
+ context "create" do
10
+
11
+ should_eventually "create a card with options passed in" do
12
+ end
13
+
14
+ should_eventually "create a card with the status of new if status property is available" do
15
+ end
16
+
17
+ should_eventually "warn if it is unable to create the card" do
18
+ end
19
+
20
+ end
21
+
22
+ context "move" do
23
+
24
+ should "move card from one state to the next as defined" do
25
+ end
26
+
27
+ should "warn if card cannot be found" do
28
+ end
29
+
30
+ end
31
+
32
+ context "print_all" do
33
+
34
+ should "warn if there are no cards" do
35
+ Card.expects(:find).with(:all).returns([])
36
+ Card.expects(:warn).with("No cards found")
37
+ Card.print_all
38
+ end
39
+
40
+ should "print the cards found with format" do
41
+ card1 = stub("Card", :number => 1, :card_type_name => "Story", :name => "Some Story")
42
+ card2 = stub("Card", :number => 2, :card_type_name => "Task", :name => "Some Task")
43
+ Card.expects(:find).with(:all).returns([card1, card2])
44
+ Card.expects(:puts).with("1 - Story - Some Story")
45
+ Card.expects(:puts).with("2 - Task - Some Task ")
46
+ Card.print_all
47
+ end
48
+
49
+ should "print cards with status property if available" do
50
+ card1 = stub("Card", :number => 1, :card_type_name => "Story", :name => "Some Story", :cp_status => "Ready")
51
+ Card.expects(:find).with(:all).returns([card1])
52
+ Card.expects(:puts).with("1 - Story - Ready - Some Story")
53
+ Card.print_all([], "cp_status")
54
+ end
55
+
56
+ end
57
+
58
+ context "print_card" do
59
+
60
+ should_eventually "print the details for a given card" do
61
+ end
62
+
63
+ end
64
+
65
+ context "update" do
66
+
67
+ should_eventually "update a card with the options passed in" do
68
+ end
69
+
70
+ should_eventually "print out the details of the card after updating" do
71
+ end
72
+
73
+ should_eventually "warn if it is not able to find the card" do
74
+ end
75
+
76
+ end
77
+
78
+ context "to_s" do
79
+
80
+ should_eventually "format the details of a given card including attachments" do
81
+ end
82
+
83
+ end
84
+
85
+ end
86
+
87
+ end
88
+
89
+ end