you_track 0.3.0 → 0.4.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 955e0cbeff48652b234859b7f9dcd451ace204bb
4
- data.tar.gz: 3f06505e3d48a2f81810fc57e3dd2f598d7fe374
3
+ metadata.gz: d654b31db68a4ca3c3cfa398cccf07eced13ec79
4
+ data.tar.gz: 26c79fb2b4900eed1001c615799231edaaf09616
5
5
  SHA512:
6
- metadata.gz: d0f07989847a8b6fce2b885e2434d23df4835f247ddae23bbf37d3551e978d15e77b809732de59be01f00b7ec9c8da43ea86f8d69bb4e13c2248f7e9f9042f7f
7
- data.tar.gz: 05cba23274ba3d4f655ae550b2d039ed2fc20d014458655fef93420bad47aca7407d129f141e954c320e77c8f1d1a8f9209549bce6ac04899e61b10910257208
6
+ metadata.gz: 0950583b556fc92462e59f7609ec3e98da2645552b9e51377398362036d68694f67445260a78038c2e80cfa93a29d9f4940c02f624bb563d5fc061eec66c9a7b
7
+ data.tar.gz: 13d02d870e5e9f5c5dbef8d4c1eb78c0780b393c5515af8afb0cee1fae465f1ea69438dab008ec1f5f412e4bc8273272589b61a46d86bbfd61b4af22f6c292d7
@@ -7,20 +7,8 @@ class YouTrack::Client::Mock
7
7
  :issues => {},
8
8
  :comments => {},
9
9
  :users => {},
10
- :projects => {
11
- "YTD" => {
12
- "name" => "You Track Dev",
13
- "shortName" => "YTD",
14
- "versions" => [],
15
- "assignees" => {},
16
- "isImporting" => "false",
17
- "description" => "Fake project for YouTrack development",
18
- }
19
- },
10
+ :projects => {},
20
11
  :custom_fields => {
21
- "YTD" => [
22
- {"name" => "Fix versions", "url" => "https://foo.bar/rest/admin/project/YTD/customfield/Fix%20versions"}
23
- ]
24
12
  }
25
13
  }
26
14
  }
@@ -38,7 +26,7 @@ class YouTrack::Client::Mock
38
26
 
39
27
  def url_for(path, options={})
40
28
  URI.parse(
41
- File.join(self.url.to_s, "/rest", path.to_s)
29
+ File.join(self.url.to_s, "/rest", URI.escape(path.to_s))
42
30
  ).tap do |uri|
43
31
  if query = options[:query]
44
32
  uri.query = Faraday::NestedParamsEncoder.encode(query)
@@ -67,7 +55,7 @@ class YouTrack::Client::Mock
67
55
  url = options[:url] || url_for(path, query: params)
68
56
 
69
57
  request_headers = {"Accept" => "application/xml"}
70
- response_headers = {"Content-Type" => "application/xml"}
58
+ response_headers = {"Content-Type" => "application/xml"}.merge(options[:response_headers] || {})
71
59
 
72
60
  # request phase
73
61
  # * :method - :get, :post, ...
@@ -8,4 +8,8 @@ class YouTrack::Client::Model
8
8
  end
9
9
  }
10
10
  end
11
+
12
+ def require_admin!
13
+ raise YouTrack::NotAnAdminError unless service.current_user.admin?
14
+ end
11
15
  end
@@ -5,9 +5,9 @@ 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, type: :array
8
+ attribute :custom_fields, default: [], parser: lambda { |v, _| Hash[v] }
9
9
  attribute :description
10
- attribute :project, alias: "projectShortName"
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"
@@ -33,7 +33,7 @@ class YouTrack::Client::Issue < YouTrack::Client::Model
33
33
  end
34
34
 
35
35
  def state
36
- custom_fields.detect { |f| f[0] == 'State' }.last
36
+ custom_fields["State"]
37
37
  end
38
38
 
39
39
  def state=(new_state)
@@ -41,29 +41,40 @@ class YouTrack::Client::Issue < YouTrack::Client::Model
41
41
  self.reload
42
42
  end
43
43
 
44
+ def project=(project)
45
+ self.project_id = (project.is_a?(YouTrack::Client::Project) ? project.identity : project)
46
+ end
47
+
44
48
  def project
45
- service.projects.get(self.attributes[:project])
49
+ requires :project_id
50
+
51
+ service.projects.get(self.project_id)
46
52
  end
47
53
 
48
54
  def save
49
55
  if new_record?
50
- requires :project, :summary
56
+ requires :summary, :project_id
51
57
 
52
- service.create_issue(
53
- "project" => self.attributes[:project],
58
+ response = service.create_issue(
59
+ "project" => self.project_id,
54
60
  "summary" => self.summary,
55
61
  "description" => self.description,
56
62
  "attachments" => self.attachments,
57
63
  "permittedGroups" => self.permitted_group,
58
64
  )
59
65
 
60
- merge_attributes(project.issues.detect { |s| s.summary == summary }.attributes) # hacky, but the create request returns nothing
66
+ merge_attributes(
67
+ :id => File.basename(response.headers["Location"]),
68
+ )
69
+
70
+ reload
61
71
  else
62
72
  requires :identity
73
+
63
74
  service.update_issue(
64
75
  "id" => self.identity,
65
76
  "summary" => self.summary,
66
- "description" => self.description
77
+ "description" => self.description,
67
78
  )
68
79
  self.reload
69
80
  end
@@ -3,7 +3,9 @@ class YouTrack::Client::Issues < YouTrack::Client::Collection
3
3
  model YouTrack::Client::Issue
4
4
 
5
5
  def all(project, filters={})
6
- service.issues.load(service.get_issues(project, filters).body)
6
+ project_id = (project.respond_to?(:identity) ? project.identity : project)
7
+
8
+ load(service.get_issues(project_id, filters).body)
7
9
  end
8
10
 
9
11
  def get(identity)
@@ -1,33 +1,70 @@
1
1
  class YouTrack::Client::Project < YouTrack::Client::Model
2
2
  identity :id, aliases: ["shortName"]
3
3
 
4
- attribute :versions, type: :array
4
+ attribute :versions, type: :array, default: []
5
5
  attribute :name
6
6
  attribute :description
7
7
  attribute :is_importing, type: :boolean, aliases: ["isImporting"]
8
8
  attribute :assignees
9
9
 
10
+ attr_accessor :starting_number, :lead, :prefix
11
+
10
12
  def issues
11
- service.issues.all(self.id)
13
+ service.issues.all(self.identity)
12
14
  end
13
15
 
14
16
  def custom_fields
15
17
  service.get_project_custom_fields(self.id).body
16
18
  end
17
19
 
20
+ def save
21
+ if new_record?
22
+ requires :name, :prefix
23
+
24
+ starting_number = self.starting_number || 1
25
+ lead = self.lead || service.current_user
26
+
27
+ lead_id = (lead.is_a?(YouTrack::Client::User) ? lead.identity : lead)
28
+
29
+ service.create_project(
30
+ "projectId" => self.prefix,
31
+ "projectName" => self.name,
32
+ "startingNumber" => starting_number,
33
+ "projectLeadLogin" => lead_id,
34
+ "description" => self.description,
35
+ )
36
+
37
+ merge_attributes(
38
+ :identity => self.prefix,
39
+ )
40
+ else
41
+ raise NotImplementedError
42
+ end
43
+ end
44
+
18
45
  def add_version(version)
19
- raise YouTrack::NotAnAdminError unless service.current_user.admin?
46
+ require_admin!
20
47
 
21
48
  unless versions.include?(version)
22
49
  service.add_project_fix_version('project' => self.id, 'version' => version)
50
+ self.versions << version
23
51
  end
52
+
53
+ self.versions
54
+ end
55
+
56
+ def reload
57
+ merge_attributes(collection.reload.get(self.identity).attributes)
24
58
  end
25
59
 
26
60
  def remove_version(version)
27
- raise YouTrack::NotAnAdminError unless service.current_user.admin?
61
+ require_admin!
28
62
 
29
63
  if versions.include?(version)
30
64
  service.remove_project_fix_version('project' => self.id, 'version' => version)
65
+ self.versions.delete(version)
31
66
  end
67
+
68
+ self.versions
32
69
  end
33
70
  end
@@ -2,10 +2,10 @@ class YouTrack::Client::Projects < YouTrack::Client::Collection
2
2
  model YouTrack::Client::Project
3
3
 
4
4
  def all
5
- service.projects.load(service.get_projects.body)
5
+ load(service.get_projects.body)
6
6
  end
7
7
 
8
8
  def get(identity)
9
- all.detect { |p| p.id == identity }
9
+ find { |p| p.identity == identity }
10
10
  end
11
11
  end
@@ -48,7 +48,7 @@ class YouTrack::Client::Real
48
48
  raise RuntimeError, "Missing required options: #{missing.inspect}" unless missing.empty?
49
49
  end
50
50
 
51
- def request(options={})
51
+ def authenticate!
52
52
  # @note first request gets the cookie
53
53
  if !@authenticated && !@authenticating
54
54
 
@@ -65,6 +65,10 @@ class YouTrack::Client::Real
65
65
  @authenticated = true
66
66
  }
67
67
  end
68
+ end
69
+
70
+ def request(options={})
71
+ authenticate!
68
72
 
69
73
  method = options[:method] || :get
70
74
  query = options[:query]
@@ -3,4 +3,19 @@ class YouTrack::Client::Request
3
3
  service.data.fetch(collection)[id] ||
4
4
  service.response(status: 404, body: {"error" => "#{collection.to_s.gsub(/s\Z/, "").capitalize} not found."})
5
5
  end
6
+
7
+ def require_parameters(_params, *_requirements)
8
+ params = Cistern::Hash.stringify_keys(_params)
9
+ requirements = _requirements.map(&:to_s)
10
+
11
+ requirements.each do |requirement|
12
+ unless !params[requirement].nil?
13
+ response(
14
+ :status => 400,
15
+ :body => {"error" => "Bad Request"})
16
+ end
17
+ end
18
+ values = params.values_at(*requirements)
19
+ values.size == 1 ? values.first : values
20
+ end
6
21
  end
@@ -11,9 +11,8 @@ class YouTrack::Client::AddProjectFixVersion < YouTrack::Client::Request
11
11
 
12
12
  def mock(params={})
13
13
  project = find(:projects, params.delete("project"))
14
- version = params.delete("version")
15
14
 
16
- project["versions"] << version
15
+ project["versions"] << params.delete("version")
17
16
 
18
17
  service.response
19
18
  end
@@ -40,6 +40,9 @@ class YouTrack::Client::CreateIssue < YouTrack::Client::Request
40
40
  service.data[:issues][identity] = issue
41
41
 
42
42
  service.response(
43
+ :response_headers => {
44
+ "Location" => service.url_for("/issue/#{identity}"),
45
+ },
43
46
  :status => 201,
44
47
  )
45
48
  end
@@ -0,0 +1,41 @@
1
+ # https://confluence.jetbrains.com/display/YTD6/PUT+Project
2
+ class YouTrack::Client::CreateProject < YouTrack::Client::Request
3
+ def self.accepted_attributes
4
+ # "projectId", # string required Unique identifier of a project to be created. This short name will be used as prefix in issue IDs for this project.
5
+ @_accepted_attributes ||= [
6
+ "projectName", # string required Full name of a new project. Must be unique.
7
+ "startingNumber", # integer required Number to assign to the next manually created issue.
8
+ "projectLeadLogin", # string required Login name of a user to be assigned as a project leader.
9
+ "description", # string Optional description of the new project.
10
+ ]
11
+ end
12
+
13
+ def real(params)
14
+ service.request(
15
+ :path => "/admin/project/#{params.fetch("projectId")}",
16
+ :method => :put,
17
+ :params => Cistern::Hash.slice(params, *self.class.accepted_attributes),
18
+ )
19
+ end
20
+
21
+ def mock(params)
22
+ identity = params.fetch("projectId")
23
+
24
+ service.data[:projects][identity] = {
25
+ "isImporting" => "false",
26
+ "lead" => params.fetch("projectLeadLogin"), # @todo check user login
27
+ "shortName" => identity,
28
+ "name" => params.fetch("projectName"),
29
+ "startingNumber" => params.fetch("startingNumber"),
30
+ "sub" => { "value" => "No subsystem" },
31
+ "versions" => [],
32
+ }.merge(Cistern::Hash.slice(params, "description"))
33
+
34
+ # @hack
35
+ service.data[:custom_fields][identity] = [
36
+ {"name" => "Fix versions", "url" => service.url_for("/admin/project/#{identity}/customfield/Fix versions")}
37
+ ]
38
+
39
+ service.response(status: 201)
40
+ end
41
+ end
@@ -15,6 +15,10 @@ class YouTrack::Client::GetIssues < YouTrack::Client::Request
15
15
  issues.delete_if.with_index { |x,i| i < (filters["after"].to_i - 1) }
16
16
  end
17
17
 
18
+ max = filters["max"] || 10
19
+
20
+ issues.slice!(max)
21
+
18
22
  service.response(
19
23
  :body => issues
20
24
  )
@@ -1,4 +1,9 @@
1
1
  class YouTrack::Client::GetProjects < YouTrack::Client::Request
2
+
3
+ def self.attributes
4
+ @_attributes ||= %w[name shortName isImporting subsystems assignees versions]
5
+ end
6
+
2
7
  def real
3
8
  service.request(
4
9
  :path => "/project/all",
@@ -9,7 +14,7 @@ class YouTrack::Client::GetProjects < YouTrack::Client::Request
9
14
 
10
15
  def mock
11
16
  service.response(
12
- :body => service.data[:projects].values
17
+ :body => service.data[:projects].values.map { |p| Cistern::Hash.slice(p, *self.class.attributes) }
13
18
  )
14
19
  end
15
20
  end
@@ -19,6 +19,7 @@ requests = %w(
19
19
  add_project_fix_version
20
20
  apply_issue_command
21
21
  create_issue
22
+ create_project
22
23
  get_admin_user
23
24
  get_current_user
24
25
  get_issue
@@ -1,3 +1,3 @@
1
1
  module YouTrack
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
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.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Lane
@@ -146,6 +146,7 @@ files:
146
146
  - lib/you_track/client/requests/add_project_fix_version.rb
147
147
  - lib/you_track/client/requests/apply_issue_command.rb
148
148
  - lib/you_track/client/requests/create_issue.rb
149
+ - lib/you_track/client/requests/create_project.rb
149
150
  - lib/you_track/client/requests/get_admin_user.rb
150
151
  - lib/you_track/client/requests/get_current_user.rb
151
152
  - lib/you_track/client/requests/get_issue.rb