mingle4r 0.4.5 → 0.4.6
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +5 -0
- data/README.rdoc +312 -0
- data/TODO.txt +16 -6
- data/VERSION +1 -0
- data/lib/mingle4r/api/project.rb +24 -39
- data/lib/mingle4r/mingle_client.rb +22 -31
- metadata +7 -7
- data/README +0 -310
- data/lib/mingle4r/version.rb +0 -11
data/History.txt
CHANGED
data/README.rdoc
ADDED
@@ -0,0 +1,312 @@
|
|
1
|
+
== mingle4r
|
2
|
+
|
3
|
+
http://github.com/arusarka/mingle4r/tree/master
|
4
|
+
|
5
|
+
== Description:
|
6
|
+
|
7
|
+
This gem is a wrapper around active resource to access the rest api exposed by mingle
|
8
|
+
(http://studios.thoughtworks.com/mingle-agile-project-management).It provides a easy
|
9
|
+
way to communicate with mingle. For the library to work you need to enable basic authentication
|
10
|
+
(not enabled by default) in Mingle. See below to enable basic authentication in Mingle.
|
11
|
+
The typical use-case for this gem is to help someone getting started with writing code
|
12
|
+
to integrate with Mingle.
|
13
|
+
|
14
|
+
However if you are planning to connect and work with mingle from the terminal, then there
|
15
|
+
is another gem mingle-mingle which you should look at. This library provides a very easy
|
16
|
+
api to write code to work with mingle (see the examples below) but thats it.
|
17
|
+
|
18
|
+
=== Enable basic authentication in Mingle
|
19
|
+
|
20
|
+
1. Go to Mingle DataDir
|
21
|
+
2. Open YAML file <Mingle DataDir>/config/auth_config.yml
|
22
|
+
3. Set 'basic_authentication_enabled' to 'true' (without the quotes) if it is not so
|
23
|
+
|
24
|
+
== Features/Problems:
|
25
|
+
|
26
|
+
It gives you access to projects in the mingle instance, cards under the project and also
|
27
|
+
attachments for a particular card.
|
28
|
+
|
29
|
+
== Synopsis:
|
30
|
+
|
31
|
+
This library is a wrapper around active resource to interact with Mingle easily. So before
|
32
|
+
using this gem a good idea would be to get familiar with active resource and the mingle apis.
|
33
|
+
If you have a mingle server running somewhere you can check the different apis at <server address>/help/mingle_api.html or goto http://www.thoughtworks-studios.com/mingle/3.0/help/mingle_api.html
|
34
|
+
|
35
|
+
A lot of examples are given below to get you started.
|
36
|
+
|
37
|
+
The api now supports only mingle 3. Mingle 2 is no longer supported. If you need to connect
|
38
|
+
to both Mingle 2 and Mingle 3 then try 0.3.0 of the gem.
|
39
|
+
|
40
|
+
In all the documentation below you can replace Mingle4r::MingleClient with MingleClient.
|
41
|
+
Its an alias for easy use.
|
42
|
+
|
43
|
+
=== Getting all the projects for a particular instance
|
44
|
+
|
45
|
+
Suppose you want to connect to the mingle instance hosted at http://localhost:8080 where the
|
46
|
+
username is 'testuser' and password is 'password'.
|
47
|
+
|
48
|
+
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
49
|
+
projs = m_c.projects => array of active resource objects
|
50
|
+
|
51
|
+
=== Getting a particular project
|
52
|
+
|
53
|
+
Before you access a particular project you need to set the project id for the mingle client
|
54
|
+
object. You can do that in two ways. Supposing you are trying to access a project with an
|
55
|
+
identifier of 'great_mingle_project'
|
56
|
+
|
57
|
+
WARNING : project identifier and project name are different. If you named your project as
|
58
|
+
'Great Mingle Project' it's identifier is by default 'great_mingle_project'. To be sure what
|
59
|
+
the identifier of a project is you should look at the url in mingle in the particular project
|
60
|
+
you are trying to access. It should be something like 'http://localhost:8080/projects/great_mingle_project'
|
61
|
+
|
62
|
+
1. Set at initialize time
|
63
|
+
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password',
|
64
|
+
'great_mingle_project')
|
65
|
+
m_c.project => active resource object
|
66
|
+
|
67
|
+
2. Set an attribute later
|
68
|
+
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
69
|
+
m_c.proj_id = 'great_mingle_project'
|
70
|
+
project = m_c.project
|
71
|
+
|
72
|
+
=== Validate credentials
|
73
|
+
|
74
|
+
m_c.valid_credentials? => returns true or false
|
75
|
+
|
76
|
+
=== Getting cards for a particular project
|
77
|
+
|
78
|
+
Get a mingle client object. Then call the cards method.
|
79
|
+
|
80
|
+
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
81
|
+
m_c.proj_id = 'great_mingle_project'
|
82
|
+
m_c.cards => array of activeresource objects
|
83
|
+
|
84
|
+
Alternatively you can also do
|
85
|
+
m_c.project.cards => array of activeresource objects
|
86
|
+
|
87
|
+
=== Getting a singe card
|
88
|
+
|
89
|
+
m_c.find_card(42) => card activeresource object
|
90
|
+
|
91
|
+
Alternatively you can also do
|
92
|
+
m_c.project.find_card(42)
|
93
|
+
|
94
|
+
=== Filtering cards
|
95
|
+
|
96
|
+
Mingle allows a lighweight implementation of sql called mql through which you can filter
|
97
|
+
cards. Look at http://www.thoughtworks-studios.com/mingle/3.0/help/mql_reference.html for
|
98
|
+
reference. However when using this feature you should only give the condition not the
|
99
|
+
properties you want out of mingle.
|
100
|
+
|
101
|
+
m_c.filter_cards('Type IS Story') => returns a list card objects
|
102
|
+
|
103
|
+
Do not do this (it simply *won't work*) :
|
104
|
+
m_c.filter_cards('SELECT number, type WHERE Type IS Story')
|
105
|
+
|
106
|
+
If you want to execute a generic mql look at the 'MQL Execution' section
|
107
|
+
|
108
|
+
=== Getting custom properties for a card
|
109
|
+
|
110
|
+
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
111
|
+
m_c.proj_id = 'great_mingle_project'
|
112
|
+
card = m_c.cards.first
|
113
|
+
card.custom_properties => returns an array of hashes, {property name => property value}
|
114
|
+
|
115
|
+
However this gives only custom properties, not all the properties.
|
116
|
+
|
117
|
+
=== Getting a particular property
|
118
|
+
|
119
|
+
gets the value of a property. The property name given should be the same as seen in Mingle.
|
120
|
+
Type, name, description and number of a card can be accessed directly. For any other custom
|
121
|
+
property use the method below.
|
122
|
+
|
123
|
+
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
124
|
+
m_c.proj_id = 'great_mingle_project'
|
125
|
+
card = m_c.cards.first
|
126
|
+
card.property_value('Status')
|
127
|
+
|
128
|
+
=== Setting a particular property
|
129
|
+
|
130
|
+
sets the value of the property. The property name given should be the same as in Mingle.
|
131
|
+
Type, name and description should be set directly when creating or updating a card.
|
132
|
+
In case of a custom property use the following method. The value given should be one of
|
133
|
+
the values that Mingle accepts in case of a managed list
|
134
|
+
|
135
|
+
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
136
|
+
m_c.proj_id = 'great_mingle_project'
|
137
|
+
defect_card = m_c.find_cards('Type IS Defect').first
|
138
|
+
defect_card.property_value('Status', 'Closed')
|
139
|
+
defect_card.save
|
140
|
+
|
141
|
+
In case of properties of type 'Tree Relatioship property' or 'Card'(properties which link
|
142
|
+
to another card) you can should set the property by giving the number of the card. For e.g.
|
143
|
+
|
144
|
+
story_card = m_c.projects.cards.find {|c| c.type == 'Story'}.first
|
145
|
+
story_card.property_value('Feature', 12)
|
146
|
+
story_card.save
|
147
|
+
|
148
|
+
In case of properties of type 'Team member' you can either use the user id (not the name or
|
149
|
+
the login id, you would have to look at the xml to get the id) or more simply the user name.
|
150
|
+
For e.g.
|
151
|
+
|
152
|
+
story_card.property_value('Assignee', 'James Bond')
|
153
|
+
story_card.save
|
154
|
+
|
155
|
+
=== Creating a card
|
156
|
+
|
157
|
+
MingleClient provides a handy method to create a new card.
|
158
|
+
|
159
|
+
task = m_c.new_card
|
160
|
+
task.name = 'set up Cruise build'
|
161
|
+
task.type = 'task'
|
162
|
+
task.description = 'a basic cruise build needs to be set up so that we can start working'
|
163
|
+
task.save
|
164
|
+
|
165
|
+
Alternatively you can also do:
|
166
|
+
Mingle4r::API::Card.site = 'http://localhost:8080/projects/agile/'
|
167
|
+
Mingle4r::API::Card.user = 'foo'
|
168
|
+
Mingle4r::API::Card.password = 'bar'
|
169
|
+
|
170
|
+
task = Mingle4r::API::Card.new , rest of the steps are same as above
|
171
|
+
|
172
|
+
Do not do it like this:
|
173
|
+
|
174
|
+
task = m_c.new_card :name => 'set up Cruise build', :type => 'task',
|
175
|
+
:description => 'a basic cruise build needs to be set up so that we can start working'
|
176
|
+
task.save => It simply won't work, there is a workaround but rather use as described above.
|
177
|
+
|
178
|
+
=== Getting a particular version of a card
|
179
|
+
|
180
|
+
Mingle maintains the different versions of a card. It always shows the latest version
|
181
|
+
by default. However if you want to access a different version you can do so in the
|
182
|
+
following ways.
|
183
|
+
|
184
|
+
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
185
|
+
m_c.proj_id = 'great_mingle_project'
|
186
|
+
defect_card = m_c.find_card(20)
|
187
|
+
|
188
|
+
supposing the latest version of the card is 42
|
189
|
+
|
190
|
+
1. Get the previous version
|
191
|
+
defect_card.version(:previous) # return version 41
|
192
|
+
|
193
|
+
2. Get the next version
|
194
|
+
defect_card.version(:next) # returns version 42 since it is the latest version
|
195
|
+
|
196
|
+
3. Get an arbitrary version
|
197
|
+
defect_card.version(21) # returns version 21
|
198
|
+
|
199
|
+
=== Getting all comments for a card
|
200
|
+
|
201
|
+
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
202
|
+
m_c.proj_id = 'great_mingle_project'
|
203
|
+
defect_card = m_c.find_cards('Type IS Defect').first
|
204
|
+
defect_cards.comments
|
205
|
+
|
206
|
+
=== Adding comment to a particular card
|
207
|
+
|
208
|
+
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
209
|
+
m_c.proj_id = 'great_mingle_project'
|
210
|
+
defect_card = m_c.find_card(420)
|
211
|
+
defect_card.add_comment('Not able to reproduce')
|
212
|
+
|
213
|
+
=== Attachments
|
214
|
+
|
215
|
+
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
216
|
+
m_c.proj_id = 'great_mingle_project'
|
217
|
+
defect_card = m_c.find_cards('Type IS Defect').first
|
218
|
+
defect_card.attachments
|
219
|
+
|
220
|
+
1. Downloading a particular attachment
|
221
|
+
attachment = defect_card.attachments.first
|
222
|
+
attachment.download('page.css')
|
223
|
+
|
224
|
+
2. Uploading an attachment
|
225
|
+
defect_card.upload_attachment('page-screenshot.jpg')
|
226
|
+
|
227
|
+
=== Murmurs
|
228
|
+
|
229
|
+
1. Get the murmurs for a project
|
230
|
+
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
231
|
+
m_c.proj_id = 'great_mingle_project'
|
232
|
+
project = m_c.project
|
233
|
+
project.murmurs
|
234
|
+
|
235
|
+
2. Get the murmurs associated with a card
|
236
|
+
card = m_c.cards.first
|
237
|
+
card.murmurs
|
238
|
+
|
239
|
+
3. post a murmur(hooray!)
|
240
|
+
project.post_murmur('my first murmur, I am excited!')
|
241
|
+
|
242
|
+
=== Get all transitions for a card
|
243
|
+
|
244
|
+
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
245
|
+
m_c.proj_id = 'great_mingle_project'
|
246
|
+
defect_card = m_c.cards.first
|
247
|
+
|
248
|
+
defect_card.transitions # array of active resource objects
|
249
|
+
|
250
|
+
=== Execute a transition on a card
|
251
|
+
|
252
|
+
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
253
|
+
m_c.proj_id = 'great_mingle_project'
|
254
|
+
defect_card = m_c.find_cards('Type IS Defect').first
|
255
|
+
|
256
|
+
defect_card.execute_transition(
|
257
|
+
'comment' => comment for the transition, required only if the transition requires a comment
|
258
|
+
'Property Name as in Mingle exactly' => 'Property value to set for the property', required only
|
259
|
+
if the transition requires to be set manually, multiple properties might need to be set.
|
260
|
+
)
|
261
|
+
|
262
|
+
=== MQL execution
|
263
|
+
|
264
|
+
mingle allows you to write an arbitrary MQL query and returns the results. This gem
|
265
|
+
allows you to do that in a simpler way. If you want to know more about MQL go to http://www.thoughtworks-studios.com/mingle/3.0/help/mql_reference.html.
|
266
|
+
|
267
|
+
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
268
|
+
m_c.proj_id = 'great_mingle_project'
|
269
|
+
m_c.project.execute_mql('SELECT name, "Added in Iteration" WHERE Type = Story')
|
270
|
+
=> returns an array of hash
|
271
|
+
|
272
|
+
== Requirements:
|
273
|
+
|
274
|
+
1) active_resource gem, it would be automatically taken care of
|
275
|
+
during gem install.
|
276
|
+
|
277
|
+
== Limitations:
|
278
|
+
|
279
|
+
updating a property on the card which is a link to another card does not work. So for now
|
280
|
+
only use it for other properties
|
281
|
+
|
282
|
+
== Install:
|
283
|
+
|
284
|
+
since github no longer archives gems, I am hosting the gem at gemcutter. So you would need to
|
285
|
+
add http://gemcutter.org to your gem sources : gem sources -a 'http://gemcutter.org'. Then do
|
286
|
+
|
287
|
+
gem install mingle4r
|
288
|
+
|
289
|
+
== License:
|
290
|
+
|
291
|
+
(The MIT License)
|
292
|
+
|
293
|
+
Copyright (c) 2010 Arusarka Haldar
|
294
|
+
|
295
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
296
|
+
a copy of this software and associated documentation files (the
|
297
|
+
'Software'), to deal in the Software without restriction, including
|
298
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
299
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
300
|
+
permit persons to whom the Software is furnished to do so, subject to
|
301
|
+
the following conditions:
|
302
|
+
|
303
|
+
The above copyright notice and this permission notice shall be
|
304
|
+
included in all copies or substantial portions of the Software.
|
305
|
+
|
306
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
307
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
308
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
309
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
310
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
311
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
312
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/TODO.txt
CHANGED
@@ -1,21 +1,31 @@
|
|
1
1
|
will be fixed/implemented very soon
|
2
2
|
-----------------------------------
|
3
3
|
|
4
|
-
* write documentation about updating card properties of type 'Card', 'Tree Relationship property'
|
5
|
-
and 'Team member'
|
6
4
|
* complete manual QA to ensure/prioritize what needs to be done for card object
|
7
|
-
*
|
5
|
+
* fix global users and users associated with a project
|
8
6
|
|
9
7
|
will be implemented, but not very important for now
|
10
8
|
----------------------------------------------------
|
11
9
|
|
10
|
+
* make the gemspec spec to autodiscover new files in some directories
|
11
|
+
* use a http connection class
|
12
|
+
* test if attachment download works with https
|
13
|
+
* get rid of active resource
|
12
14
|
* update documentation - write about executing transitions directly on the transition
|
13
|
-
* write tests for project class
|
14
15
|
* implement card_types for a project
|
15
|
-
*
|
16
|
+
* investigate setting custom properties at card creation time
|
17
|
+
* provide a block to set up a new card in MingleClient::new_card
|
16
18
|
|
17
19
|
will be done when I've no other work
|
18
20
|
------------------------------------
|
19
21
|
|
20
22
|
* clarify in docs difference between custom properties and native properties
|
21
|
-
* should transtions give the list of properties to be changed directly
|
23
|
+
* should transtions give the list of properties to be changed directly
|
24
|
+
|
25
|
+
What should be done regarding
|
26
|
+
-----------------------------
|
27
|
+
|
28
|
+
* performance fixes - should MingleClient::cards return all cards?
|
29
|
+
* what is the difference between mingle client and project object? mingle client seems to be delegating a
|
30
|
+
lot of methods to project
|
31
|
+
* should MingleClient::projects method reuse the class of @project?
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.4.6
|
data/lib/mingle4r/api/project.rb
CHANGED
@@ -4,47 +4,64 @@ module Mingle4r
|
|
4
4
|
module InstanceMethods
|
5
5
|
# returns the cards for the project.
|
6
6
|
def cards
|
7
|
-
set_attributes_for(Card)
|
7
|
+
set_attributes_for(Card)
|
8
8
|
Card.find_without_pagination(:all)
|
9
9
|
end
|
10
10
|
|
11
11
|
# returns the users for the project.
|
12
12
|
def users
|
13
|
-
set_attributes_for(User)
|
13
|
+
set_attributes_for(User)
|
14
14
|
User.find(:all)
|
15
15
|
end
|
16
16
|
|
17
17
|
# returns the wikis for the project.
|
18
18
|
def wikis
|
19
|
-
set_attributes_for(Wiki)
|
19
|
+
set_attributes_for(Wiki)
|
20
20
|
Wiki.find(:all)
|
21
21
|
end
|
22
22
|
|
23
23
|
# returns the property definitions for the project.
|
24
24
|
def property_definitions
|
25
|
-
set_attributes_for(PropertyDefinition)
|
25
|
+
set_attributes_for(PropertyDefinition)
|
26
26
|
PropertyDefinition.find(:all)
|
27
27
|
end
|
28
28
|
|
29
29
|
# returns the murmurs for the project.
|
30
30
|
def murmurs
|
31
|
-
set_attributes_for(Murmur)
|
31
|
+
set_attributes_for(Murmur)
|
32
32
|
Murmur.find(:all)
|
33
33
|
end
|
34
34
|
|
35
35
|
# posts a murmur
|
36
36
|
def post_murmur(str)
|
37
|
-
set_attributes_for(Murmur)
|
37
|
+
set_attributes_for(Murmur)
|
38
38
|
murmur = Murmur.new(:body => str.to_s)
|
39
39
|
murmur.save
|
40
40
|
end
|
41
41
|
|
42
42
|
# executes an mql
|
43
43
|
def execute_mql(query)
|
44
|
-
set_attributes_for(ExecuteMql)
|
44
|
+
set_attributes_for(ExecuteMql)
|
45
45
|
ExecuteMql.query(query)
|
46
46
|
end
|
47
47
|
|
48
|
+
#finds a single card
|
49
|
+
def find_card(number)
|
50
|
+
set_attributes_for(Card)
|
51
|
+
Card.find(number)
|
52
|
+
end
|
53
|
+
|
54
|
+
#returns a filtered list of cards
|
55
|
+
def filter_cards(filter_str)
|
56
|
+
set_attributes_for(Card)
|
57
|
+
Card.apply_filter(filter_str)
|
58
|
+
end
|
59
|
+
|
60
|
+
def new_card
|
61
|
+
set_attributes_for(Card)
|
62
|
+
Card.new
|
63
|
+
end
|
64
|
+
|
48
65
|
private
|
49
66
|
def set_attributes_for(klass)
|
50
67
|
resource_site = File.join(self.class.site.to_s, "projects/#{self.identifier}")
|
@@ -52,40 +69,8 @@ module Mingle4r
|
|
52
69
|
klass.site = resource_site
|
53
70
|
klass.user = self.class.user
|
54
71
|
klass.password = self.class.password
|
55
|
-
setter_method = klass.name.demodulize.underscore + '_class_set'
|
56
|
-
send(setter_method, true)
|
57
72
|
klass
|
58
73
|
end
|
59
|
-
|
60
|
-
def user_class_set(val = nil)
|
61
|
-
return @user_class_set unless val
|
62
|
-
@user_class_set = val
|
63
|
-
end
|
64
|
-
|
65
|
-
def card_class_set(val = nil)
|
66
|
-
return @card_class_set unless val
|
67
|
-
@card_class_set = val
|
68
|
-
end
|
69
|
-
|
70
|
-
def wiki_class_set(val = nil)
|
71
|
-
return @wiki_class_set unless val
|
72
|
-
@wiki_class_set = val
|
73
|
-
end
|
74
|
-
|
75
|
-
def property_definition_class_set(val = nil)
|
76
|
-
return @property_definition_class_set unless val
|
77
|
-
@property_definition_class_set = val
|
78
|
-
end
|
79
|
-
|
80
|
-
def murmur_class_set(val = nil)
|
81
|
-
return @murmur_class_set unless val
|
82
|
-
@murmur_class_set = val
|
83
|
-
end
|
84
|
-
|
85
|
-
def execute_mql_class_set(val = nil)
|
86
|
-
return @execute_mql_class_set unless val
|
87
|
-
@execute_mql_class_set = val
|
88
|
-
end
|
89
74
|
end # module InstanceMethods
|
90
75
|
|
91
76
|
extend Mingle4r::CommonClassMethods
|
@@ -7,48 +7,38 @@ module Mingle4r
|
|
7
7
|
@user = user
|
8
8
|
@password = password
|
9
9
|
@proj_id = proj_id
|
10
|
-
|
10
|
+
setup_project_class
|
11
11
|
end
|
12
12
|
|
13
13
|
def site=(site)
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
set_resource_attributes()
|
20
|
-
end
|
14
|
+
@site = site
|
15
|
+
user, password = decode_uri(site)
|
16
|
+
@user = user if user
|
17
|
+
@password = password if password
|
18
|
+
setup_project_class
|
21
19
|
@site
|
22
20
|
end
|
23
21
|
|
24
22
|
def user=(user)
|
25
|
-
|
26
|
-
|
27
|
-
set_resource_attributes()
|
28
|
-
end
|
23
|
+
@user = user
|
24
|
+
setup_project_class
|
29
25
|
@user
|
30
26
|
end
|
31
27
|
|
32
28
|
def password=(password)
|
33
|
-
|
34
|
-
|
35
|
-
set_resource_attributes()
|
36
|
-
end
|
29
|
+
@password = password
|
30
|
+
setup_project_class
|
37
31
|
@password
|
38
32
|
end
|
39
33
|
|
40
34
|
def proj_id=(proj_id)
|
41
|
-
|
42
|
-
|
43
|
-
set_resource_attributes()
|
44
|
-
end
|
35
|
+
@proj_id = proj_id
|
36
|
+
setup_project_class
|
45
37
|
@proj_id
|
46
38
|
end
|
47
39
|
|
48
40
|
def valid_credentials?
|
49
|
-
|
50
|
-
API::Project.user = user
|
51
|
-
API::Project.password = password
|
41
|
+
setup_project_class
|
52
42
|
begin
|
53
43
|
API::Project.find(:all)
|
54
44
|
true
|
@@ -67,17 +57,13 @@ module Mingle4r
|
|
67
57
|
API::Project.find(:all)
|
68
58
|
end
|
69
59
|
|
70
|
-
def
|
71
|
-
|
60
|
+
def method_missing(meth_id, *args, &block)
|
61
|
+
project.send(meth_id, *args, &block)
|
72
62
|
end
|
73
63
|
|
74
64
|
private
|
75
|
-
def
|
76
|
-
|
77
|
-
set_attributes(API::User)
|
78
|
-
end
|
79
|
-
|
80
|
-
def set_attributes(klass)
|
65
|
+
def setup_project_class
|
66
|
+
klass = API::Project
|
81
67
|
klass.site = base_url
|
82
68
|
klass.user = @user
|
83
69
|
klass.password = @password
|
@@ -86,6 +72,11 @@ module Mingle4r
|
|
86
72
|
def base_url
|
87
73
|
File.join(@site.to_s, '/api/v2/')
|
88
74
|
end
|
75
|
+
|
76
|
+
def decode_uri(site)
|
77
|
+
uri = URI.parse(site)
|
78
|
+
[uri.user, uri.password]
|
79
|
+
end
|
89
80
|
end
|
90
81
|
end
|
91
82
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mingle4r
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 3
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 4
|
9
|
-
-
|
10
|
-
version: 0.4.
|
9
|
+
- 6
|
10
|
+
version: 0.4.6
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- asur
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-06-
|
18
|
+
date: 2010-06-27 00:00:00 +05:30
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -39,14 +39,13 @@ executables: []
|
|
39
39
|
extensions: []
|
40
40
|
|
41
41
|
extra_rdoc_files:
|
42
|
-
- README
|
42
|
+
- README.rdoc
|
43
43
|
files:
|
44
44
|
- lib/mingle4r.rb
|
45
45
|
- lib/mingle_resource.rb
|
46
46
|
- lib/mingle4r/common_class_methods.rb
|
47
47
|
- lib/mingle4r/helpers.rb
|
48
48
|
- lib/mingle4r/mingle_client.rb
|
49
|
-
- lib/mingle4r/version.rb
|
50
49
|
- lib/mingle4r/card_format.rb
|
51
50
|
- lib/mingle4r/api/card.rb
|
52
51
|
- lib/mingle4r/api/card/attachment.rb
|
@@ -60,7 +59,8 @@ files:
|
|
60
59
|
- lib/mingle4r/api/wiki.rb
|
61
60
|
- MIT-LICENSE
|
62
61
|
- History.txt
|
63
|
-
- README
|
62
|
+
- README.rdoc
|
63
|
+
- VERSION
|
64
64
|
- TODO.txt
|
65
65
|
has_rdoc: true
|
66
66
|
homepage: http://github.com/arusarka/mingle4r/
|
data/README
DELETED
@@ -1,310 +0,0 @@
|
|
1
|
-
== mingle4r
|
2
|
-
|
3
|
-
http://github.com/arusarka/mingle4r/tree/master
|
4
|
-
|
5
|
-
== DESCRIPTION:
|
6
|
-
|
7
|
-
This gem is a wrapper around active resource to access the rest api exposed by mingle
|
8
|
-
(http://studios.thoughtworks.com/mingle-agile-project-management).It provides a easy
|
9
|
-
way to communicate with mingle. For the library to work you need to enable basic authentication
|
10
|
-
(not enabled by default) in Mingle. See below to enable basic authentication in Mingle.
|
11
|
-
The typical use-case for this gem is to help someone getting started with writing code
|
12
|
-
to integrate with Mingle.
|
13
|
-
|
14
|
-
However if you are planning to connect and work with mingle from the terminal, then there
|
15
|
-
is another gem mingle-mingle which you should look at. This library provides a very easy
|
16
|
-
api to write code to work with mingle (see the examples below) but thats it.
|
17
|
-
|
18
|
-
Enable basic authentication in Mingle
|
19
|
-
-------------------------------------
|
20
|
-
|
21
|
-
1) Go to Mingle DataDir
|
22
|
-
|
23
|
-
2) Open YAML file <Mingle DataDir>/config/auth_config.yml
|
24
|
-
|
25
|
-
3) Set 'basic_authentication_enabled' to 'true' (without the quotes) if it is not so
|
26
|
-
|
27
|
-
== FEATURES/PROBLEMS:
|
28
|
-
|
29
|
-
It gives you access to projects in the mingle instance, cards under the project and also
|
30
|
-
attachments for a particular card.
|
31
|
-
|
32
|
-
== SYNOPSIS:
|
33
|
-
|
34
|
-
The api now supports only mingle 3. Mingle 2 is no longer supported. If you need to connect
|
35
|
-
to both Mingle 2 and Mingle 3 then try 0.3.0 of the gem. To see the api for mingle 3, check
|
36
|
-
the api documentation for the mingle instance(located at <mingle instance host>/help/index)
|
37
|
-
|
38
|
-
In all the documentation below you can replace Mingle4r::MingleClient with MingleClient.
|
39
|
-
Its an alias for easy use.
|
40
|
-
|
41
|
-
Getting all the projects for a particular instance
|
42
|
-
--------------------------------------------------
|
43
|
-
|
44
|
-
Suppose you want to connect to the mingle instance hosted at http://localhost:8080 where the
|
45
|
-
username is 'testuser' and password is 'password'.
|
46
|
-
|
47
|
-
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
48
|
-
projs = m_c.projects
|
49
|
-
|
50
|
-
projs is an array of active resource objects
|
51
|
-
|
52
|
-
Getting a particular project
|
53
|
-
----------------------------
|
54
|
-
|
55
|
-
Before you access a particular project you need to set the project id for the mingle client
|
56
|
-
object. You can do that in two ways. Supposing you are trying to access a project with an
|
57
|
-
identifier of 'great_mingle_project'
|
58
|
-
|
59
|
-
WARNING : project identifier and project name are different. If you named your project as
|
60
|
-
'Great Mingle Project' it's identifier is by default 'great_mingle_project'. To be sure what
|
61
|
-
the identifier of a project is you should look at the url in mingle in the particular project
|
62
|
-
you are trying to access. It should be something like 'http://localhost:8080/projects/great_mingle_project'
|
63
|
-
|
64
|
-
1) Set at initialize time
|
65
|
-
|
66
|
-
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password',
|
67
|
-
'great_mingle_project')
|
68
|
-
m_c.project
|
69
|
-
|
70
|
-
2) Set an attribute later
|
71
|
-
|
72
|
-
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
73
|
-
m_c.proj_id = 'great_mingle_project'
|
74
|
-
project = m_c.project
|
75
|
-
|
76
|
-
project is a single activeresource object
|
77
|
-
|
78
|
-
Getting cards for a particular project
|
79
|
-
--------------------------------------
|
80
|
-
|
81
|
-
Get a mingle client object initialized as in SECTION B. Then call the cards method.
|
82
|
-
|
83
|
-
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
84
|
-
m_c.proj_id = 'great_mingle_project'
|
85
|
-
m_c.project.cards
|
86
|
-
|
87
|
-
cards will be an array of activeresoure objects.
|
88
|
-
|
89
|
-
Getting custom properties for a card
|
90
|
-
------------------------------------
|
91
|
-
|
92
|
-
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
93
|
-
m_c.proj_id = 'great_mingle_project'
|
94
|
-
card = m_c.project.cards[0]
|
95
|
-
card.custom_properties => returns an array of hashes, {property name => property value}
|
96
|
-
|
97
|
-
However this gives only custom properties, not all the properties.
|
98
|
-
|
99
|
-
Getting a particular property
|
100
|
-
-----------------------------
|
101
|
-
|
102
|
-
gets the value of a property. The property name given should be the same as seen in Mingle.
|
103
|
-
Type, name, description and number of a card can be accessed directly. For any other custom
|
104
|
-
property use the method below.
|
105
|
-
|
106
|
-
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
107
|
-
m_c.proj_id = 'great_mingle_project'
|
108
|
-
card = m_c.project.cards[0]
|
109
|
-
card.property_value('Status')
|
110
|
-
|
111
|
-
Setting a particular property
|
112
|
-
-----------------------------
|
113
|
-
|
114
|
-
sets the value of the property. The property name given should be the same as in Mingle.
|
115
|
-
Type, name and description should be set directly when creating or updating a card.
|
116
|
-
In case of a custom property use the following method. The value given should be one of
|
117
|
-
the values that Mingle accepts in case of a managed list
|
118
|
-
|
119
|
-
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
120
|
-
m_c.proj_id = 'great_mingle_project'
|
121
|
-
defect_card = m_c.project.cards.first
|
122
|
-
defect_card.property_value('Status', 'Closed')
|
123
|
-
defect_card.save
|
124
|
-
|
125
|
-
In case of properties of type 'Tree Relatioship property' or 'Card'(properties which link
|
126
|
-
to another card) you can should set the property by giving the number of the card. For e.g.
|
127
|
-
|
128
|
-
story_card = m_c.projects.cards.find {|c| c.type == 'Story'}.first
|
129
|
-
story_card.property_value('Feature', 12)
|
130
|
-
story_card.save
|
131
|
-
|
132
|
-
In case of properties of type 'Team member' you can either use the user id (not the name or
|
133
|
-
the login id, you would have to look at the xml to get the id) or more simply the user name.
|
134
|
-
For e.g.
|
135
|
-
|
136
|
-
story_card.property_value('Assignee', 'James Bond')
|
137
|
-
story_card.save
|
138
|
-
|
139
|
-
Creating a card
|
140
|
-
---------------
|
141
|
-
|
142
|
-
Mingle4r::API::Card is the ActiveResource class which handles interaction with cards.
|
143
|
-
task = Mingle4r::API::Card.new
|
144
|
-
task.name = 'set up Cruise build'
|
145
|
-
task.type = 'task'
|
146
|
-
task.description = 'a basic cruise build needs to be set up so that we can start working'
|
147
|
-
task.save
|
148
|
-
|
149
|
-
Do not do it like this:
|
150
|
-
|
151
|
-
task = Mingle4r::API::new :name => 'set up Cruise build', :type => 'task',
|
152
|
-
:description => 'a basic cruise build needs to be set up so that we can start working'
|
153
|
-
task.save => It simply won't work, there is a workaround but rather use as described above.
|
154
|
-
|
155
|
-
Adding comment to a particular card
|
156
|
-
-----------------------------------
|
157
|
-
|
158
|
-
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
159
|
-
m_c.proj_id = 'great_mingle_project'
|
160
|
-
defect_card = m_c.project.cards[0]
|
161
|
-
defect_card.add_comment('Not able to reproduce')
|
162
|
-
|
163
|
-
Getting a particular version of a card
|
164
|
-
--------------------------------------
|
165
|
-
|
166
|
-
Mingle maintains the different versions of a card. It always shows the latest version
|
167
|
-
by default. However if you want to access a different version you can do so in the
|
168
|
-
following ways.
|
169
|
-
|
170
|
-
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
171
|
-
m_c.proj_id = 'great_mingle_project'
|
172
|
-
defect_card = m_c.project.cards.first
|
173
|
-
supposing the latest version of the card is 42
|
174
|
-
|
175
|
-
1) Get the previous version
|
176
|
-
---------------------------
|
177
|
-
|
178
|
-
defect_card.version(:previous) # return version 41
|
179
|
-
|
180
|
-
2) Get the next version
|
181
|
-
-----------------------
|
182
|
-
|
183
|
-
defect_card.version(:next) # returns version 42 since it is the latest version
|
184
|
-
|
185
|
-
3) Get an arbitrary version
|
186
|
-
---------------------------
|
187
|
-
|
188
|
-
defect_card.version(21) # returns version 21
|
189
|
-
|
190
|
-
Getting all comments for a card
|
191
|
-
-------------------------------
|
192
|
-
|
193
|
-
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
194
|
-
m_c.proj_id = 'great_mingle_project'
|
195
|
-
defect_card = m_c.project.cards.first
|
196
|
-
defect_cards.comments
|
197
|
-
|
198
|
-
Attachments
|
199
|
-
-----------
|
200
|
-
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
201
|
-
m_c.proj_id = 'great_mingle_project'
|
202
|
-
defect_card = m_c.project.cards.first
|
203
|
-
defect_card.attachments
|
204
|
-
|
205
|
-
1) Downloading a particular attachment
|
206
|
-
--------------------------------------
|
207
|
-
|
208
|
-
attachment = defect_card.attachments.first
|
209
|
-
attachment.download('page.css')
|
210
|
-
|
211
|
-
2) Uploading an attachment
|
212
|
-
--------------------------
|
213
|
-
|
214
|
-
defect_card.upload_attachment('page-screenshot.jpg')
|
215
|
-
|
216
|
-
Murmurs
|
217
|
-
-------
|
218
|
-
|
219
|
-
1) Get the murmurs for a project
|
220
|
-
--------------------------------
|
221
|
-
|
222
|
-
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
223
|
-
m_c.proj_id = 'great_mingle_project'
|
224
|
-
project = m_c.project
|
225
|
-
project.murmurs
|
226
|
-
|
227
|
-
2) Get the murmurs associated with a card
|
228
|
-
-----------------------------------------
|
229
|
-
|
230
|
-
card = project.cards.first
|
231
|
-
card.murmurs
|
232
|
-
|
233
|
-
3) post a murmur(hooray!)
|
234
|
-
-------------------------
|
235
|
-
project.post_murmur('my first murmur, I am excited!')
|
236
|
-
|
237
|
-
Get all transitions for a card
|
238
|
-
------------------------------
|
239
|
-
|
240
|
-
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
241
|
-
m_c.proj_id = 'great_mingle_project'
|
242
|
-
defect_card = m_c.project.cards.first
|
243
|
-
|
244
|
-
defect_card.transitions # array of active resource objects
|
245
|
-
|
246
|
-
Execute a transition on a card
|
247
|
-
------------------------------
|
248
|
-
|
249
|
-
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
250
|
-
m_c.proj_id = 'great_mingle_project'
|
251
|
-
defect_card = m_c.project.cards.first
|
252
|
-
|
253
|
-
defect_card.execute_transition(
|
254
|
-
'comment' => comment for the transition, required only if the transition requires a comment
|
255
|
-
'Property Name as in Mingle exactly' => 'Property value to set for the property', required only
|
256
|
-
if the transition requires to be set manually, multiple properties might need to be set.
|
257
|
-
)
|
258
|
-
|
259
|
-
MQL execution
|
260
|
-
-------------
|
261
|
-
|
262
|
-
mingle allows you to write an arbitrary MQL query and returns the results. This gem
|
263
|
-
allows you to do that in a simpler way. If you want to know more about MQL go to http://www.thoughtworks-studios.com/mingle/3.0/help/mql_reference.html.
|
264
|
-
|
265
|
-
m_c = Mingle4r::MingleClient.new('http://localhost:8080', 'testuser', 'password')
|
266
|
-
m_c.proj_id = 'great_mingle_project'
|
267
|
-
m_c.project.execute_mql('SELECT name, "Added in Iteration" WHERE Type = Story')
|
268
|
-
=> returns an array of hash
|
269
|
-
|
270
|
-
== REQUIREMENTS:
|
271
|
-
|
272
|
-
1) active_resource gem, it would be automatically taken care of
|
273
|
-
during gem install.
|
274
|
-
|
275
|
-
== LIMITATIONS:
|
276
|
-
|
277
|
-
updating a property on the card which is a link to another card does not work. So for now
|
278
|
-
only use it for other properties
|
279
|
-
|
280
|
-
== INSTALL:
|
281
|
-
|
282
|
-
since github no longer archives gems, I am hosting the gem at gemcutter. So you would need to
|
283
|
-
add http://gemcutter.org to your gem sources : gem sources -a 'http://gemcutter.org'. Then do
|
284
|
-
|
285
|
-
gem install mingle4r
|
286
|
-
|
287
|
-
== LICENSE:
|
288
|
-
|
289
|
-
(The MIT License)
|
290
|
-
|
291
|
-
Copyright (c) 2010 Arusarka Haldar
|
292
|
-
|
293
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
294
|
-
a copy of this software and associated documentation files (the
|
295
|
-
'Software'), to deal in the Software without restriction, including
|
296
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
297
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
298
|
-
permit persons to whom the Software is furnished to do so, subject to
|
299
|
-
the following conditions:
|
300
|
-
|
301
|
-
The above copyright notice and this permission notice shall be
|
302
|
-
included in all copies or substantial portions of the Software.
|
303
|
-
|
304
|
-
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
305
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
306
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
307
|
-
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
308
|
-
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
309
|
-
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
310
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|