minglr 1.3.11

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.
Files changed (45) hide show
  1. data/.document +5 -0
  2. data/.gitignore +3 -0
  3. data/LICENSE +20 -0
  4. data/PostInstall.txt +1 -0
  5. data/README.rdoc +87 -0
  6. data/Rakefile +90 -0
  7. data/VERSION.yml +4 -0
  8. data/bin/minglr +29 -0
  9. data/bin/mtx +14 -0
  10. data/cucumber.yml +2 -0
  11. data/features/cards.feature +27 -0
  12. data/features/step_definitions/minglr_steps.rb +34 -0
  13. data/features/step_definitions/shared_steps.rb +69 -0
  14. data/features/users.feature +6 -0
  15. data/lib/minglr.rb +34 -0
  16. data/lib/minglr/action.rb +85 -0
  17. data/lib/minglr/config_parser.rb +51 -0
  18. data/lib/minglr/extensions/array.rb +23 -0
  19. data/lib/minglr/mtx/input_cache.rb +24 -0
  20. data/lib/minglr/mtx/options_parser.rb +58 -0
  21. data/lib/minglr/options_parser.rb +82 -0
  22. data/lib/minglr/resources/attachment.rb +51 -0
  23. data/lib/minglr/resources/base.rb +42 -0
  24. data/lib/minglr/resources/card.rb +117 -0
  25. data/lib/minglr/resources/project.rb +25 -0
  26. data/lib/minglr/resources/property_definition.rb +12 -0
  27. data/lib/minglr/resources/transition_execution.rb +6 -0
  28. data/lib/minglr/resources/user.rb +19 -0
  29. data/minglr.gemspec +120 -0
  30. data/minglrconfig.sample +37 -0
  31. data/tasks/commit.sample.rake +86 -0
  32. data/tasks/svn.sample.rake +27 -0
  33. data/test/action_test.rb +75 -0
  34. data/test/commands_test.rb +111 -0
  35. data/test/config_parser_test.rb +116 -0
  36. data/test/extensions/array_test.rb +41 -0
  37. data/test/options_parser_test.rb +74 -0
  38. data/test/resources/attachment_test.rb +90 -0
  39. data/test/resources/base_test.rb +58 -0
  40. data/test/resources/card_test.rb +199 -0
  41. data/test/resources/project_test.rb +44 -0
  42. data/test/resources/property_definition_test.rb +25 -0
  43. data/test/resources/user_test.rb +32 -0
  44. data/test/test_helper.rb +31 -0
  45. metadata +219 -0
@@ -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,19 @@
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
+ end
18
+
19
+ end
@@ -0,0 +1,120 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{minglr}
8
+ s.version = "1.3.11"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Michael Schubert", "Stephen Chu", "Chris O'Meara"]
12
+ s.date = %q{2009-09-17}
13
+ 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}
14
+ s.email = %q{michael@schubert.cx}
15
+ s.executables = ["mtx", "minglr"]
16
+ s.extra_rdoc_files = [
17
+ "LICENSE",
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ ".document",
22
+ ".gitignore",
23
+ "LICENSE",
24
+ "PostInstall.txt",
25
+ "README.rdoc",
26
+ "Rakefile",
27
+ "VERSION.yml",
28
+ "bin/minglr",
29
+ "bin/mtx",
30
+ "cucumber.yml",
31
+ "features/cards.feature",
32
+ "features/step_definitions/minglr_steps.rb",
33
+ "features/step_definitions/shared_steps.rb",
34
+ "features/users.feature",
35
+ "lib/minglr.rb",
36
+ "lib/minglr/action.rb",
37
+ "lib/minglr/config_parser.rb",
38
+ "lib/minglr/extensions/array.rb",
39
+ "lib/minglr/mtx/input_cache.rb",
40
+ "lib/minglr/mtx/options_parser.rb",
41
+ "lib/minglr/options_parser.rb",
42
+ "lib/minglr/resources/attachment.rb",
43
+ "lib/minglr/resources/base.rb",
44
+ "lib/minglr/resources/card.rb",
45
+ "lib/minglr/resources/project.rb",
46
+ "lib/minglr/resources/property_definition.rb",
47
+ "lib/minglr/resources/transition_execution.rb",
48
+ "lib/minglr/resources/user.rb",
49
+ "minglr.gemspec",
50
+ "minglrconfig.sample",
51
+ "tasks/commit.sample.rake",
52
+ "tasks/svn.sample.rake",
53
+ "test/action_test.rb",
54
+ "test/commands_test.rb",
55
+ "test/config_parser_test.rb",
56
+ "test/extensions/array_test.rb",
57
+ "test/options_parser_test.rb",
58
+ "test/resources/attachment_test.rb",
59
+ "test/resources/base_test.rb",
60
+ "test/resources/card_test.rb",
61
+ "test/resources/project_test.rb",
62
+ "test/resources/property_definition_test.rb",
63
+ "test/resources/user_test.rb",
64
+ "test/test_helper.rb"
65
+ ]
66
+ s.homepage = %q{http://github.com/schubert/minglr}
67
+ s.post_install_message = %q{PostInstall.txt}
68
+ s.rdoc_options = ["--charset=UTF-8"]
69
+ s.require_paths = ["lib"]
70
+ s.rubygems_version = %q{1.3.5}
71
+ s.summary = %q{command line user tool for Mingle (http://mingle.thoughtworks.com/mingle-agile-project-management)}
72
+ s.test_files = [
73
+ "test/action_test.rb",
74
+ "test/commands_test.rb",
75
+ "test/config_parser_test.rb",
76
+ "test/extensions/array_test.rb",
77
+ "test/options_parser_test.rb",
78
+ "test/resources/attachment_test.rb",
79
+ "test/resources/base_test.rb",
80
+ "test/resources/card_test.rb",
81
+ "test/resources/project_test.rb",
82
+ "test/resources/property_definition_test.rb",
83
+ "test/resources/user_test.rb",
84
+ "test/test_helper.rb"
85
+ ]
86
+
87
+ if s.respond_to? :specification_version then
88
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
89
+ s.specification_version = 3
90
+
91
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
92
+ s.add_runtime_dependency(%q<httpclient>, [">= 0"])
93
+ s.add_runtime_dependency(%q<activeresource>, [">= 2.3.0"])
94
+ s.add_runtime_dependency(%q<activesupport>, [">= 2.3.0"])
95
+ s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
96
+ s.add_development_dependency(%q<mocha>, [">= 0"])
97
+ s.add_development_dependency(%q<relevance-rcov>, [">= 0"])
98
+ s.add_development_dependency(%q<cucumber>, [">= 0"])
99
+ s.add_development_dependency(%q<redgreen>, [">= 0"])
100
+ else
101
+ s.add_dependency(%q<httpclient>, [">= 0"])
102
+ s.add_dependency(%q<activeresource>, [">= 2.3.0"])
103
+ s.add_dependency(%q<activesupport>, [">= 2.3.0"])
104
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
105
+ s.add_dependency(%q<mocha>, [">= 0"])
106
+ s.add_dependency(%q<relevance-rcov>, [">= 0"])
107
+ s.add_dependency(%q<cucumber>, [">= 0"])
108
+ s.add_dependency(%q<redgreen>, [">= 0"])
109
+ end
110
+ else
111
+ s.add_dependency(%q<httpclient>, [">= 0"])
112
+ s.add_dependency(%q<activeresource>, [">= 2.3.0"])
113
+ s.add_dependency(%q<activesupport>, [">= 2.3.0"])
114
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
115
+ s.add_dependency(%q<mocha>, [">= 0"])
116
+ s.add_dependency(%q<relevance-rcov>, [">= 0"])
117
+ s.add_dependency(%q<cucumber>, [">= 0"])
118
+ s.add_dependency(%q<redgreen>, [">= 0"])
119
+ end
120
+ end
@@ -0,0 +1,37 @@
1
+ [global]
2
+ default = someproject
3
+ username = yourusername
4
+
5
+ [someproject]
6
+ url = http://your.mingle.host.com/mingle/projects/someproject
7
+ username = yourusername
8
+ password = YOURMINGLEPASSWORD
9
+ delete_property = cp_story_status
10
+ delete_state = Deleted
11
+ status_property = cp_story_status
12
+ story_state_1 = Ready For Development > Sign Up for Story
13
+ story_state_2 = Dev In Progress > Dev Complete
14
+ task_state_1 = New > New to ready for Dev for Task
15
+ task_state_2 = Ready for Development > Dev in Progress
16
+ task_state_3 = Dev In Progress > Story from Dev in Progress to Dev Complete
17
+ story_checkout = story_state_1
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,86 @@
1
+ require 'minglr'
2
+
3
+ desc "Run this if you have new code to check in"
4
+ task :check_in => %w( minglr:dev_complete:prepare
5
+ svn:add
6
+ svn:rm
7
+ svn:up
8
+ svn:conflict_check
9
+ db:migrate
10
+ test
11
+ svn:ci
12
+ minglr:dev_complete:transition )
13
+
14
+ namespace :minglr do
15
+ task :prepare do
16
+ @host_port = 'mingle-host:8080' # REPLACE WITH YOUR MINGLE HOST AND PORT
17
+ @project = 'project_4808' # REPLACE WITH YOUR MINGLE PROJECT IDENTIFIER
18
+ end
19
+
20
+ namespace :dev_complete do
21
+ desc "Gather inputs to execute a 'Development Complete' card transition."
22
+ task :prepare => 'minglr:prepare' do
23
+ @transition = 'Transition Uno' # REPLACE WITH THE TRANSITION YOU WANT TO EXECUTE
24
+ @username = prompt 'Please enter your Mingle username', :cache_key => 'username'
25
+ @password = prompt 'Please enter your Mingle password', :secure => true
26
+ @card = prompt 'Please enter a Mingle card number', :cache_key => 'card'
27
+ @commit_message = prompt 'Please enter a commit message', :cache_key => 'commit_message'
28
+ @comment = prompt 'Please enter a comment for the transition', :cache_key => 'transition_comment'
29
+ @properties = ['Actual Effort', 'Property Dos'].inject([]) do |memo, property_name|
30
+ memo << [ %Q|"#{escape(property_name)}"|,
31
+ %Q|"#{prompt(%Q{Please enter the value for the property "#{property_name}"}, :cache_key => property_name)}"|]
32
+ memo
33
+ end.flatten.join(',')
34
+ @story_complete = prompt('Is the story complete? (y/N)', :cache_key => 'story_complete').to_s.downcase == 'y'
35
+ end
36
+
37
+ desc "Executes a 'Development Complete' card transition."
38
+ task :transition => 'minglr:dev_complete:prepare' do
39
+ if @story_complete
40
+ cmd = %Q|#{Minglr::ROOT}/bin/mtx --username "#{@username}" --password "#{@password}" --card "#{@card}" --comment "#{@comment}" --transition "#{@transition}" --properties #{@properties} --host_port "#{@host_port}" --project "#{@project}"|
41
+ `#{cmd}`
42
+ raise "Minglr transition failed with exit status #{$?}." unless $?.success?
43
+ end
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def prompt(message, options = { :secure => false })
50
+ require 'rubygems'
51
+ begin
52
+ require 'password' rescue Exception
53
+ rescue Exception
54
+ @clear_text_password = true
55
+ end
56
+
57
+ user_input = if options[:secure]
58
+ if @clear_text_password
59
+ puts "NOTE: You do not have the 'rb-password' port installed. Perform 'sudo port install rb-password' to avoid your password shown in clear text as you type below."
60
+ print "#{message}: "
61
+ $stdin.gets.chop
62
+ else
63
+ Password.get "#{message}: "
64
+ end
65
+ else
66
+ print "#{message}"
67
+ if cache = MTX::InputCache.get(options[:cache_key])
68
+ print " [#{cache}]"
69
+ end
70
+ print ": "
71
+ $stdin.gets.chop
72
+ end
73
+
74
+ if !options[:secure] && cache_key = options.delete(:cache_key)
75
+ user_input = MTX::InputCache.get(cache_key) if user_input.blank?
76
+ MTX::InputCache.put(cache_key, user_input)
77
+ end
78
+
79
+ user_input = escape(user_input)
80
+ end
81
+
82
+ def escape(user_input)
83
+ user_input.gsub(/["]/, %q{\"}) if user_input
84
+ end
85
+
86
+ end
@@ -0,0 +1,27 @@
1
+ namespace :svn do
2
+ desc "Updates your local WC"
3
+ task :up do
4
+ `svn up`
5
+ end
6
+
7
+ desc "Adds new local WC files"
8
+ task :add do
9
+ `svn st | grep '^?' | xargs svn add`
10
+ end
11
+
12
+ desc "Removes deleted local WC files"
13
+ task :rm do
14
+ `svn st | grep '^!' | xargs svn rm`
15
+ end
16
+
17
+ desc "Check-in your local WC changes"
18
+ task :ci do
19
+ `svn ci -m "#{@commit_message || ENV['commit_message']}"`
20
+ end
21
+
22
+ desc "Checks if your WC has merge conflicts."
23
+ task :conflict_check do
24
+ `svn st | awk '{ if( $1 == "C" ) exit 1}'`
25
+ raise 'You have conflicts!' unless $?.success?
26
+ end
27
+ end
@@ -0,0 +1,75 @@
1
+ require 'test_helper'
2
+
3
+ module Minglr
4
+
5
+ class ActionTest < Test::Unit::TestCase
6
+
7
+ context Action do
8
+
9
+ context "valid_actions" do
10
+
11
+ should "return an array of valid actions" do
12
+ valid_actions = ["users", "cards", "card", "move", "update", "attach", "projects", "create", "fetch"].sort
13
+ assert_equal [], (valid_actions - Action.valid_actions)
14
+ end
15
+
16
+ end
17
+
18
+ context "valid_action?" do
19
+
20
+ should "return true if action is a valid action" do
21
+ assert_equal true, Action.valid_action?("move")
22
+ end
23
+
24
+ should "return false if action is not a valid action" do
25
+ assert_equal false, Action.valid_action?("frobble")
26
+ end
27
+
28
+ end
29
+
30
+ context "execute" do
31
+
32
+ should "ignore the first option if no project is specified" do
33
+ action = :someaction
34
+ options = ["someaction", "option2"]
35
+ flag_options = { :foo => "bar" }
36
+ config = { :foo => "bar" }
37
+
38
+ Minglr::Action::Commands.expects(:send).with(action, ["option2"], flag_options, config)
39
+ Action.execute(action, options, flag_options, config)
40
+ end
41
+
42
+ should "ignore the first two options if project is specified" do
43
+ action = :someaction
44
+ options = ["someproject", "someaction", "option2"]
45
+ flag_options = { :foo => "bar" }
46
+ config = { :foo => "bar" }
47
+
48
+ Minglr::Action::Commands.expects(:send).with(action, ["option2"], flag_options, config)
49
+ Action.execute(action, options, flag_options, config)
50
+ end
51
+
52
+ should "send the action to commands" do
53
+ action = "someaction"
54
+ options = ["option1", "option2"]
55
+ flag_options = { :foo => "bar" }
56
+ config = { :foo => "bar" }
57
+
58
+ Minglr::Action::Commands.expects(:send).with(action, options, flag_options, config)
59
+ Action.execute(action, options, flag_options, config)
60
+ end
61
+
62
+ should "rescue and print an error if the resource can't be found" do
63
+ Action.expects(:puts).with("Failed with MyError for URL '#{Resources::Base.site}' ...")
64
+ Minglr::Action::Commands.expects(:send).raises(ActiveResource::ResourceNotFound, stub("Response", :code => "MyError"))
65
+
66
+ Action.execute("someaction", ["someaction"])
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+
73
+ end
74
+
75
+ end
@@ -0,0 +1,111 @@
1
+ require 'test_helper'
2
+
3
+ module Minglr
4
+
5
+ class CommandsTest < Test::Unit::TestCase
6
+
7
+ context Action::Commands do
8
+
9
+ setup do
10
+ @options = []
11
+ @flag_options = {}
12
+ @config = { :status_property => "cp_status", :username => "user", :password => "password" }
13
+ end
14
+
15
+ context "attach" do
16
+
17
+ should "parse card number and file number as options and call resource" do
18
+ @options << "1"
19
+ @flag_options[:file_attachment] = "file"
20
+
21
+ Resources::Attachment.expects(:attach).with("1", "file", "user", "password")
22
+ Action::Commands.attach(@options, @flag_options, @config)
23
+ end
24
+
25
+ end
26
+
27
+ context "card" do
28
+
29
+ should "parse card number and call resource" do
30
+ @options << "1"
31
+
32
+ Resources::Card.expects(:print_card).with("1", "cp_status")
33
+ Action::Commands.card(@options, @flag_options, @config)
34
+ end
35
+
36
+ end
37
+
38
+ context "cards" do
39
+
40
+ should "call resource" do
41
+ Resources::Card.expects(:print_all).with(@options, "cp_status")
42
+ Action::Commands.cards(@options, @flag_options, @config)
43
+ end
44
+
45
+ end
46
+
47
+ context "create" do
48
+
49
+ should "call resource" do
50
+ Resources::Card.expects(:create).with(@flag_options, "cp_status")
51
+ Action::Commands.create(@options, @flag_options, @config)
52
+ end
53
+
54
+ end
55
+
56
+ context "fetch" do
57
+
58
+ should "parse card number and call resource" do
59
+ @options << "1"
60
+
61
+ Resources::Attachment.expects(:fetch).with("1", "user", "password")
62
+ Action::Commands.fetch(@options, @flag_options, @config)
63
+ end
64
+
65
+ end
66
+
67
+ context "move" do
68
+
69
+ should "parse card number and call resource" do
70
+ @options << "1"
71
+
72
+ Resources::Card.expects(:move).with("1", @flag_options, @config)
73
+ Action::Commands.move(@options, @flag_options, @config)
74
+ end
75
+
76
+ end
77
+
78
+ context "projects" do
79
+
80
+ should "call resource" do
81
+ Resources::Project.expects(:print_all).with(@options, "cp_status")
82
+ Action::Commands.projects(@options, @flag_options, @config)
83
+ end
84
+
85
+ end
86
+
87
+ context "update" do
88
+
89
+ should "parse card number and call resource" do
90
+ @options << "1"
91
+
92
+ Resources::Card.expects(:update).with("1", @flag_options)
93
+ Action::Commands.update(@options, @flag_options, @config)
94
+ end
95
+
96
+ end
97
+
98
+ context "users" do
99
+
100
+ should "call resource" do
101
+ Resources::User.expects(:print_all).with(@options)
102
+ Action::Commands.users(@options, @flag_options, @config)
103
+ end
104
+
105
+ end
106
+
107
+ end
108
+
109
+ end
110
+
111
+ end