you_track 0.4.4 → 0.4.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/you_track/client/mock.rb +103 -4
- data/lib/you_track/client/models/issue.rb +20 -4
- data/lib/you_track/client/request.rb +4 -0
- data/lib/you_track/client/requests/apply_issue_command.rb +28 -14
- data/lib/you_track/client/requests/create_issue.rb +22 -8
- data/lib/you_track/client/requests/create_project.rb +1 -4
- data/lib/you_track/client/requests/get_project_custom_fields.rb +13 -1
- data/lib/you_track/client/requests/update_issue.rb +24 -10
- data/lib/you_track/parser.rb +2 -1
- data/lib/you_track/parser/base.rb +1 -3
- data/lib/you_track/parser/issue_parser.rb +17 -3
- data/lib/you_track/parser/state_bundle_parser.rb +16 -0
- data/lib/you_track/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2e542dac4f944908887f1a006dcc1d8de569fbf1
|
4
|
+
data.tar.gz: 75a5823009d83ff8bcdf82461c4cea7c6c057a9e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 41e1aaef65378c7e7994db4e34c2890dcea9a7607e093c5fa0516ce72f96cce4a87cf5caf2b787905d27b033ada25b6b18756c4f3119c8aa8f4d0a8957f4234c
|
7
|
+
data.tar.gz: 582abf84d61d51abfbfaf56de41041e7a68e4aadf87d740771097cfdfac8cfbe806ab18bd01d7c59ec345e7974c3b83295add502249cd7687e530c8d7166973f
|
@@ -4,11 +4,110 @@ class YouTrack::Client::Mock
|
|
4
4
|
def self.data
|
5
5
|
@data ||= Hash.new { |h,k|
|
6
6
|
h[k] = {
|
7
|
-
:issues
|
8
|
-
:comments
|
9
|
-
:users
|
10
|
-
:projects
|
7
|
+
:issues => {},
|
8
|
+
:comments => {},
|
9
|
+
:users => {},
|
10
|
+
:projects => {},
|
11
|
+
:project_custom_fields => {},
|
12
|
+
:bundles => {
|
13
|
+
"States" => {
|
14
|
+
"type" => "state",
|
15
|
+
"name" => "States",
|
16
|
+
"values" => [
|
17
|
+
{"resolved" => "false", "value" => "Submitted"},
|
18
|
+
{"resolved" => "false", "value" => "Open"},
|
19
|
+
{"resolved" => "false", "value" => "In Progress"},
|
20
|
+
{"resolved" => "false", "value" => "To be discussed"},
|
21
|
+
{"resolved" => "false", "value" => "Reopened"},
|
22
|
+
{"resolved" => "true", "value" => "Can't Reproduce"},
|
23
|
+
{"resolved" => "true", "value" => "Duplicate"},
|
24
|
+
{"resolved" => "true", "value" => "Fixed"},
|
25
|
+
{"resolved" => "true", "value" => "Won't fix"},
|
26
|
+
{"resolved" => "true", "value" => "Incomplete"},
|
27
|
+
{"resolved" => "true", "value" => "Obsolete"},
|
28
|
+
{"resolved" => "true", "value" => "Verified"},
|
29
|
+
{"resolved" => "false", "value" => "New"}
|
30
|
+
]
|
31
|
+
}
|
32
|
+
},
|
11
33
|
:custom_fields => {
|
34
|
+
"Type" => {
|
35
|
+
"name" => "Type",
|
36
|
+
"isPrivate" => false,
|
37
|
+
"visibleByDefault" => true,
|
38
|
+
"autoAttached" => true,
|
39
|
+
"type" => "enum[1]",
|
40
|
+
"attachBundlePolicy" => 0,
|
41
|
+
"defaultBundle" => "Types",
|
42
|
+
},
|
43
|
+
"Priority" => {
|
44
|
+
"name" => "Priority",
|
45
|
+
"isPrivate" => false,
|
46
|
+
"visibleByDefault" => true,
|
47
|
+
"autoAttached" => true,
|
48
|
+
"type" => "enum[1]",
|
49
|
+
"attachBundlePolicy" => 0,
|
50
|
+
"defaultBundle" => "Priorties",
|
51
|
+
},
|
52
|
+
"State" => {
|
53
|
+
"name" => "State",
|
54
|
+
"isPrivate" => false,
|
55
|
+
"visibleByDefault" => true,
|
56
|
+
"autoAttached" => true,
|
57
|
+
"type" => "state[1]",
|
58
|
+
"attachBundlePolicy" => 0,
|
59
|
+
"defaultBundle" => "States",
|
60
|
+
},
|
61
|
+
"Subsystem" => {
|
62
|
+
"name" => "Subsystem",
|
63
|
+
"isPrivate" => false,
|
64
|
+
"visibleByDefault" => true,
|
65
|
+
"autoAttached" => true,
|
66
|
+
"type" => "ownedField[1]",
|
67
|
+
"attachBundlePolicy" => 1,
|
68
|
+
"defaultBundle" => "Subsystems",
|
69
|
+
},
|
70
|
+
"Fixed in build" => {
|
71
|
+
"name" => "Fixed in build",
|
72
|
+
"isPrivate" => false,
|
73
|
+
"visibleByDefault" => true,
|
74
|
+
"autoAttached" => true,
|
75
|
+
"type" => "build[1]",
|
76
|
+
"attachBundlePolicy" => 1,
|
77
|
+
"defaultBundle" => "Builds",
|
78
|
+
},
|
79
|
+
"Assignee" => {
|
80
|
+
"name" => "Assignee",
|
81
|
+
"isPrivate" => false,
|
82
|
+
"visibleByDefault" => true,
|
83
|
+
"autoAttached" => true,
|
84
|
+
"type" => "user[1]",
|
85
|
+
},
|
86
|
+
"Affected versions" => {
|
87
|
+
"name" => "Affected versions",
|
88
|
+
"isPrivate" => false,
|
89
|
+
"visibleByDefault" => true,
|
90
|
+
"autoAttached" => true,
|
91
|
+
"type" => "version[*]",
|
92
|
+
"attachBundlePolicy" => 1,
|
93
|
+
"defaultBundle" => "Versions",
|
94
|
+
},
|
95
|
+
"Fix versions" => {
|
96
|
+
"name" => "Fix Versions",
|
97
|
+
"isPrivate" => false,
|
98
|
+
"visibleByDefault" => true,
|
99
|
+
"autoAttached" => true,
|
100
|
+
"type" => "version[*]",
|
101
|
+
"attachBundlePolicy" => 1,
|
102
|
+
"defaultBundle" => "Versions",
|
103
|
+
},
|
104
|
+
"Due Date" => {
|
105
|
+
"name" => "Due Date",
|
106
|
+
"isPrivate" => false,
|
107
|
+
"visibleByDefault" => true,
|
108
|
+
"autoAttached" => true,
|
109
|
+
"type" => "date",
|
110
|
+
},
|
12
111
|
}
|
13
112
|
}
|
14
113
|
}
|
@@ -5,12 +5,13 @@ class YouTrack::Client::Issue < YouTrack::Client::Model
|
|
5
5
|
attribute :comment_count, alias: "commentsCount", type: :integer
|
6
6
|
attribute :comments, type: :array
|
7
7
|
attribute :created_at, alias: "created", parser: ms_time
|
8
|
-
attribute :custom_fields, default:
|
8
|
+
attribute :custom_fields, default: {}, parser: lambda { |v, _| Hash[v] }
|
9
9
|
attribute :description
|
10
10
|
attribute :project_id, alias: "projectShortName"
|
11
11
|
attribute :project_index, alias: "numberInProject", type: :integer
|
12
12
|
attribute :reporter, alias: "reporterFullName"
|
13
13
|
attribute :reporter_username, alias: "reporterName"
|
14
|
+
attribute :resolved, parser: ms_time
|
14
15
|
attribute :summary
|
15
16
|
attribute :tags, alias: "tag", type: :array
|
16
17
|
attribute :updated_at, alias: "updated", parser: ms_time
|
@@ -20,9 +21,6 @@ class YouTrack::Client::Issue < YouTrack::Client::Model
|
|
20
21
|
|
21
22
|
attr_accessor :permitted_group
|
22
23
|
|
23
|
-
# CREATE https://confluence.jetbrains.com/display/YTD6/Create+New+Issue
|
24
|
-
# UPDATE https://confluence.jetbrains.com/display/YTD6/Update+an+Issue
|
25
|
-
|
26
24
|
def comments
|
27
25
|
service.comments.load(service.get_issue_comments(self.identity).body)
|
28
26
|
end
|
@@ -32,6 +30,24 @@ class YouTrack::Client::Issue < YouTrack::Client::Model
|
|
32
30
|
comments.detect { |c| c.text == comment }
|
33
31
|
end
|
34
32
|
|
33
|
+
def assignee=(user)
|
34
|
+
user_id = user.is_a?(YouTrack::Client::User) ? user.identity : user
|
35
|
+
service.apply_issue_command("id" => self.identity, "command" => "Assignee #{user_id}")
|
36
|
+
self.reload
|
37
|
+
end
|
38
|
+
|
39
|
+
def assignee
|
40
|
+
if user_id = self.custom_fields["Assignee"]
|
41
|
+
service.users.new(
|
42
|
+
service.get_user(user_id).body
|
43
|
+
)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def resolved?
|
48
|
+
!! self.resolved
|
49
|
+
end
|
50
|
+
|
35
51
|
def state
|
36
52
|
custom_fields["State"]
|
37
53
|
end
|
@@ -1,36 +1,50 @@
|
|
1
1
|
class YouTrack::Client::ApplyIssueCommand < YouTrack::Client::Request
|
2
|
-
|
3
|
-
id = params.delete("id")
|
2
|
+
include YouTrack::Client::ParameterRequest
|
4
3
|
|
4
|
+
def identity
|
5
|
+
params.fetch("id")
|
6
|
+
end
|
7
|
+
|
8
|
+
def real
|
5
9
|
service.request(
|
6
|
-
:path => "/issue/#{
|
10
|
+
:path => "/issue/#{identity}/execute",
|
7
11
|
:query => params,
|
8
12
|
:method => :post,
|
9
13
|
)
|
10
14
|
end
|
11
15
|
|
12
|
-
def mock
|
13
|
-
|
14
|
-
issue = find(:issues, id)
|
16
|
+
def mock
|
17
|
+
issue = find(:issues, identity)
|
15
18
|
comment_id = "#{Cistern::Mock.random_numbers(2)}-#{Cistern::Mock.random_numbers(5)}"
|
16
19
|
|
17
|
-
if params["comment"]
|
18
|
-
|
20
|
+
if comment = params["comment"]
|
21
|
+
service.data[:comments][comment_id] = {
|
19
22
|
"id" => comment_id,
|
20
23
|
"author" => service.username,
|
21
24
|
"deleted" => false,
|
22
|
-
"text" =>
|
25
|
+
"text" => comment,
|
23
26
|
"shownForIssuer" => false,
|
24
|
-
"created" =>
|
25
|
-
"issueId" =>
|
27
|
+
"created" => ms_time,
|
28
|
+
"issueId" => identity,
|
26
29
|
}
|
27
|
-
service.data[:comments][comment_id] = comment
|
28
30
|
end
|
29
31
|
|
30
32
|
if params["command"]
|
31
33
|
commands = params["command"].split.each_slice(2).map { |a| [a[0], a[1]] }
|
32
|
-
commands.each do |
|
33
|
-
|
34
|
+
commands.each do |field, value|
|
35
|
+
prototype = service.data[:custom_fields].fetch(field)
|
36
|
+
|
37
|
+
bundle_value = if bundle = service.data[:bundles][prototype["defaultBundle"]]
|
38
|
+
bundle["values"].find { |v| v["value"] == value }
|
39
|
+
else # @fixme explode
|
40
|
+
{}
|
41
|
+
end
|
42
|
+
|
43
|
+
if bundle_value["resolved"] == "true"
|
44
|
+
issue["resolved"] = ms_time(Time.now)
|
45
|
+
end
|
46
|
+
|
47
|
+
issue["custom_fields"].find { |name, _| name == field }[1] = value
|
34
48
|
end
|
35
49
|
end
|
36
50
|
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# https://confluence.jetbrains.com/display/YTD6/Create+New+Issue
|
1
2
|
class YouTrack::Client::CreateIssue < YouTrack::Client::Request
|
2
3
|
def real(params)
|
3
4
|
service.request(
|
@@ -12,31 +13,44 @@ class YouTrack::Client::CreateIssue < YouTrack::Client::Request
|
|
12
13
|
|
13
14
|
issue = Cistern::Hash.slice(params, "project", "description", "summary")
|
14
15
|
|
15
|
-
|
16
|
+
project_id = issue["projectShortName"] = issue.delete("project")
|
17
|
+
find(:projects, project_id)
|
16
18
|
|
17
19
|
index = service.data[:issues].size + 1
|
18
|
-
project_index = service.data[:issues].values.select { |i| i["projectShortName"] ==
|
20
|
+
project_index = service.data[:issues].values.select { |i| i["projectShortName"] == project_id }.size
|
19
21
|
|
20
|
-
identity = "#{
|
22
|
+
identity = "#{project_id}-#{index}"
|
21
23
|
|
22
24
|
issue.merge!(
|
23
25
|
"id" => identity,
|
24
26
|
"tag" => "",
|
25
27
|
"numberInProject" => project_index,
|
26
|
-
"created" => Time.now
|
27
|
-
"updated" => Time.now
|
28
|
+
"created" => ms_time(Time.now),
|
29
|
+
"updated" => ms_time(Time.now),
|
28
30
|
"updaterName" => service.username,
|
29
31
|
"updaterFullName" => service.username.capitalize,
|
30
32
|
"reporterName" => service.username,
|
31
33
|
"reporterFullName" => service.username.capitalize,
|
32
34
|
"commentsCount" => "0",
|
33
35
|
"votes" => "0",
|
34
|
-
"custom_fields" => [
|
35
|
-
["State", "Open"],
|
36
|
-
], # @fixme need these
|
37
36
|
"attachments" => [],
|
37
|
+
"custom_fields" => [],
|
38
38
|
)
|
39
39
|
|
40
|
+
service.data[:project_custom_fields][project_id].each { |prototype|
|
41
|
+
default = if bundle = service.data[:bundles][prototype["defaultBundle"]]
|
42
|
+
bundle["values"][prototype["attachBundlePolicy"].to_i]
|
43
|
+
else
|
44
|
+
{}
|
45
|
+
end
|
46
|
+
|
47
|
+
if default["resolved"] == "true"
|
48
|
+
issue["resolved"] = ms_time(Time.now)
|
49
|
+
end
|
50
|
+
|
51
|
+
issue["custom_fields"] << [ prototype["name"], default["value"] ]
|
52
|
+
}
|
53
|
+
|
40
54
|
service.data[:issues][identity] = issue
|
41
55
|
|
42
56
|
service.response(
|
@@ -31,10 +31,7 @@ class YouTrack::Client::CreateProject < YouTrack::Client::Request
|
|
31
31
|
"versions" => [],
|
32
32
|
}.merge(Cistern::Hash.slice(params, "description"))
|
33
33
|
|
34
|
-
|
35
|
-
service.data[:custom_fields][identity] = [
|
36
|
-
{"name" => "Fix versions", "url" => service.url_for("/admin/project/#{identity}/customfield/Fix versions")}
|
37
|
-
]
|
34
|
+
service.data[:project_custom_fields][identity] = service.data[:custom_fields].values.select { |v| v["autoAttached"] }
|
38
35
|
|
39
36
|
service.response(status: 201)
|
40
37
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
# https://confluence.jetbrains.com/display/YTD6/GET+Project+Custom+Fields
|
1
2
|
class YouTrack::Client::GetProjectCustomFields < YouTrack::Client::Request
|
2
3
|
def real(id)
|
3
4
|
service.request(
|
@@ -7,6 +8,17 @@ class YouTrack::Client::GetProjectCustomFields < YouTrack::Client::Request
|
|
7
8
|
end
|
8
9
|
|
9
10
|
def mock(id)
|
10
|
-
|
11
|
+
prototypes = find(:project_custom_fields, id)
|
12
|
+
|
13
|
+
body = prototypes.inject([]) { |r,p|
|
14
|
+
name = p.fetch("name")
|
15
|
+
|
16
|
+
r << {
|
17
|
+
"name" => name,
|
18
|
+
"url" => service.url_for("/admin/project/#{id}/#{name}"),
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
service.response(body: body)
|
11
23
|
end
|
12
24
|
end
|
@@ -1,19 +1,33 @@
|
|
1
|
+
# https://confluence.jetbrains.com/display/YTD6/Update+an+Issue
|
1
2
|
class YouTrack::Client::UpdateIssue < YouTrack::Client::Request
|
2
|
-
|
3
|
-
|
3
|
+
include YouTrack::Client::ParameterRequest
|
4
|
+
|
5
|
+
def self.accepted_attributes
|
6
|
+
# issueID # string ID of an issue that should be updated.
|
7
|
+
@_accepted_attributes ||= [
|
8
|
+
"summary", # string New summary for the specified issue.
|
9
|
+
"description", # string Updated description for the specified issue.
|
10
|
+
]
|
11
|
+
end
|
12
|
+
|
13
|
+
def identity
|
14
|
+
params.fetch("id")
|
15
|
+
end
|
16
|
+
|
17
|
+
def accepted_attributes
|
18
|
+
Cistern::Hash.slice(params, *self.class.accepted_attributes)
|
19
|
+
end
|
20
|
+
|
21
|
+
def real
|
4
22
|
service.request(
|
5
|
-
:path => "/issue/#{id}",
|
23
|
+
:path => "/issue/#{params.fetch("id")}",
|
6
24
|
:method => :post,
|
7
|
-
:query =>
|
25
|
+
:query => accepted_attributes,
|
8
26
|
)
|
9
27
|
end
|
10
28
|
|
11
|
-
def mock
|
12
|
-
|
13
|
-
issue = find(:issues, id)
|
14
|
-
|
15
|
-
issue.merge!(params)
|
16
|
-
service.data[:issues][id] = issue
|
29
|
+
def mock
|
30
|
+
find(:issues, identity).merge!(accepted_attributes)
|
17
31
|
|
18
32
|
service.response
|
19
33
|
end
|
data/lib/you_track/parser.rb
CHANGED
@@ -6,6 +6,15 @@ class YouTrack::Parser::IssueParser < YouTrack::Parser::Base
|
|
6
6
|
}
|
7
7
|
end
|
8
8
|
|
9
|
+
def parse_user_fields(user_fields)
|
10
|
+
user_fields.inject({}) { |r, a|
|
11
|
+
outer_value = a["value"]
|
12
|
+
value = outer_value.delete("__content__")
|
13
|
+
|
14
|
+
r.merge(a["name"] => {"value" => value}.merge(outer_value))
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
9
18
|
def parse
|
10
19
|
results = raw["issue"].dup
|
11
20
|
|
@@ -16,9 +25,14 @@ class YouTrack::Parser::IssueParser < YouTrack::Parser::Base
|
|
16
25
|
custom_fields = fields - attachments
|
17
26
|
|
18
27
|
results.merge!(parse_fields(standard_fields))
|
19
|
-
|
20
|
-
|
21
|
-
|
28
|
+
|
29
|
+
user_fields = custom_fields.select { |k| k["xsi:type"] == "MultiUserField" }
|
30
|
+
|
31
|
+
custom_fields -= user_fields
|
32
|
+
|
33
|
+
results["custom_fields"] = parse_fields(custom_fields).merge(parse_user_fields(user_fields))
|
34
|
+
results["attachments"] = parse_attachments(attachments)
|
35
|
+
results["comments"] = results.delete("comment")
|
22
36
|
|
23
37
|
results
|
24
38
|
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class YouTrack::Parser::StateBundleParser < YouTrack::Parser::Base
|
2
|
+
def parse
|
3
|
+
bundle = raw["stateBundle"]
|
4
|
+
|
5
|
+
states = bundle.delete("state")
|
6
|
+
|
7
|
+
bundle["states"] = states.inject([]) { |r,h|
|
8
|
+
r << {
|
9
|
+
"resolved" => h["isResolved"],
|
10
|
+
"value" => h["__content__"],
|
11
|
+
}
|
12
|
+
}
|
13
|
+
|
14
|
+
bundle
|
15
|
+
end
|
16
|
+
end
|
data/lib/you_track/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: you_track
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josh Lane
|
@@ -166,6 +166,7 @@ files:
|
|
166
166
|
- lib/you_track/parser/issues_parser.rb
|
167
167
|
- lib/you_track/parser/project_custom_fields_parser.rb
|
168
168
|
- lib/you_track/parser/projects_parser.rb
|
169
|
+
- lib/you_track/parser/state_bundle_parser.rb
|
169
170
|
- lib/you_track/parser/user_parser.rb
|
170
171
|
- lib/you_track/version.rb
|
171
172
|
- you_track.gemspec
|