youtrack_client 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: bf83ce5a8edbb921abd47bbeed0298949224101d6ad492b0d8016c5298e6fb9e
4
+ data.tar.gz: 479af90f64ccb10ebd5ac1cb7931b12c2704dbf9ac75e1437f2d61fcd4a17bc2
5
+ SHA512:
6
+ metadata.gz: 429008de43454915497287709edc27ee985d4f232afa6de71f907069859e518ab7c87a94af4d3a67d6ada2f922cf77a552e2340ddafba7bd2f85314f29b4b332
7
+ data.tar.gz: '08a34367fa8ef12fbd5a87272e5d6fa86134a832ad6a8ac4a985e1436cc5b8363e3cb01357e3dc139706d5ded1707e617631f1332d233a87dec10a88a3ad478f'
@@ -0,0 +1,24 @@
1
+ name: 🛡 Specs
2
+
3
+ on: [push]
4
+
5
+ jobs:
6
+ specs:
7
+ name: Specs
8
+ runs-on: ubuntu-latest
9
+
10
+ steps:
11
+ - name: Checkout
12
+ uses: actions/checkout@v2
13
+ with:
14
+ fetch-depth: 1
15
+
16
+ - name: Set up Ruby
17
+ uses: ruby/setup-ruby@v1
18
+ with:
19
+ ruby-version: '2.7.6'
20
+ bundler-cache: true
21
+
22
+ - name: Run specs
23
+ run: |
24
+ bundle exec rspec
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ .idea
11
+ # rspec failure tracking
12
+ .rspec_status
13
+ .ruby-version
14
+ .ruby-gemset
15
+ *.gem
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ ### Changelog
2
+
3
+ All notable changes to this project will be documented in this file. Dates are displayed in UTC.
4
+
5
+ #### v1.0.0
6
+
7
+ - initial release
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ gem 'rake'
6
+
7
+ group :development, :test do
8
+ gem 'rspec'
9
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 Shane Hofstetter
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,112 @@
1
+ ![logo](https://user-images.githubusercontent.com/13404717/59300590-da2b6600-8c8f-11e9-82b2-ab3dc856ffdb.jpeg)
2
+
3
+ # youtrack-rest-client
4
+
5
+ Ruby client for the [Youtrack REST API](https://www.jetbrains.com/help/youtrack/standalone/youtrack-rest-api-reference.html)
6
+
7
+ ## Usage
8
+
9
+ ## Installation
10
+
11
+ TBD
12
+
13
+ ### Authentication
14
+
15
+ **With your permanent token (
16
+ see [Manage-Permanent-Token](https://www.jetbrains.com/help/youtrack/incloud/Manage-Permanent-Token.html)):**
17
+
18
+ ```ruby
19
+ require 'youtrack'
20
+
21
+ # 1. create an instance, pass your youtrack instance url and access token
22
+ youtrack = Youtrack::Client.new(base_url: "https://example.myjetbrains.com", token: "perm:your-token")
23
+
24
+ # 2. make requests!
25
+ youtrack.users.current.email
26
+ ```
27
+
28
+ ### [Users](https://www.jetbrains.com/help/youtrack/incloud/api-entity-User.html)
29
+
30
+ ```ruby
31
+
32
+ # get the current user
33
+ youtrack.users.current
34
+
35
+ # get all users
36
+ youtrack.users.all
37
+
38
+ # search users
39
+ youtrack.users.all("query" => "admin")
40
+
41
+ # get a user by id
42
+ youtrack.users.by_id('1-1')
43
+
44
+ ```
45
+
46
+ ### [Projects](https://www.jetbrains.com/help/youtrack/incloud/api-entity-Project.html)
47
+
48
+ ```ruby
49
+
50
+ # get all projects
51
+ youtrack.projects.all
52
+
53
+ # search projects
54
+ youtrack.projects.all(query: "DEMO")
55
+
56
+ # get a project by its id
57
+ youtrack.projects.by_id('0-0')
58
+
59
+ ```
60
+
61
+ ### [Issues](https://www.jetbrains.com/help/youtrack/incloud/api-entity-Issue.html)
62
+
63
+ ```ruby
64
+ # search/list issues
65
+ youtrack.issues.search('project: T1')
66
+ ```
67
+
68
+ ```ruby
69
+ # get issue by id
70
+ youtrack.issues.by_id('T1-2')
71
+ ```
72
+
73
+ ```ruby
74
+ # delete an issue
75
+ youtrack.issues.delete('2-2')
76
+ ```
77
+
78
+ ```ruby
79
+ # create a new issue
80
+ youtrack.issues.create({
81
+ summary: 'lorem ipsum',
82
+ description: 'created using rest api',
83
+ project: {
84
+ id: '0-0'
85
+ }
86
+ })
87
+ # you can also pass a model instance
88
+ youtrack.issues.create(Youtrack::Models::Issue.new(summary: "demo issue",
89
+ description: "demo issue description",
90
+ project: client.projects.by_id("0-0")))
91
+
92
+
93
+ ```
94
+
95
+ ### [Commands](https://www.jetbrains.com/help/youtrack/incloud/api-entity-CommandList.html)
96
+
97
+ ```ruby
98
+ # execute command for issue(s)
99
+ youtrack.issues.command("State Open", client.issues.search("DEMO-12"))
100
+ # pass the ids directly
101
+ youtrack.issues.command("State Open", %w[T1-1 T1-2 T1-3])
102
+ ```
103
+
104
+ ## Contributing
105
+
106
+ If you encounter any missing features or bugs, you're welcome to open an Issue! PRs are welcome too ;-)
107
+
108
+ 1. Fork it ( https://github.com/shanehofstetter/youtrack-rest-client-ruby/fork )
109
+ 2. Create your feature branch (git checkout -b my-new-feature)
110
+ 3. Commit your changes (git commit -am 'Add some feature')
111
+ 4. Push to the branch (git push origin my-new-feature)
112
+ 5. Create a new Pull Request
@@ -0,0 +1,78 @@
1
+ require 'rest-client'
2
+ require "active_support"
3
+ require 'active_support/core_ext'
4
+
5
+ module Youtrack
6
+ class Client
7
+ attr_reader :base_url, :token
8
+
9
+ def initialize(base_url:, token:)
10
+ @base_url = normalize_base_url(base_url)
11
+ @token = token
12
+ RestClient.log = $stdout if ENV["DEBUG"]
13
+ end
14
+
15
+ def users
16
+ @users ||= Resources::Users.new(client: self)
17
+ end
18
+
19
+ def issues
20
+ @issues ||= Resources::Issues.new(client: self)
21
+ end
22
+
23
+ def projects
24
+ @projects ||= Resources::Projects.new(client: self)
25
+ end
26
+
27
+ def get(path, options = {})
28
+ execute(:get, path, options)
29
+ end
30
+
31
+ def post(path, payload, options = {})
32
+ execute(:post, path, options.merge(payload: payload))
33
+ end
34
+
35
+ def delete(path, options = {})
36
+ execute(:delete, path, options)
37
+ end
38
+
39
+ def execute(method, path, options = {})
40
+ RestClient::Request.execute(
41
+ method: method,
42
+ url: request_url(path),
43
+ headers: default_headers
44
+ .merge(options.delete(:headers) || {})
45
+ .merge(params: options.delete(:params) || {}),
46
+ **options
47
+ )
48
+ rescue RestClient::Exception => e
49
+ if e.http_body.present?
50
+ e.message = e.http_body
51
+ end
52
+ raise e
53
+ end
54
+
55
+ private
56
+
57
+ def default_headers
58
+ {
59
+ "Authorization" => "Bearer #{token}",
60
+ 'Content-Type' => :json
61
+ }
62
+ end
63
+
64
+ def request_url(path)
65
+ [base_url, path].join("")
66
+ end
67
+
68
+ def normalize_base_url(base_url)
69
+ if base_url.match(/\/$/)
70
+ base_url = base_url[0..-2]
71
+ end
72
+ unless base_url.match(/api$/i)
73
+ base_url += "/api"
74
+ end
75
+ base_url
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,114 @@
1
+ module Youtrack
2
+ module Models
3
+ class Base
4
+
5
+ class Field
6
+ attr_accessor :name, :extended, :model, :type
7
+
8
+ def initialize(name:, extended: nil, model: nil, type: nil)
9
+ @name = name
10
+ @extended = extended
11
+ @model = model
12
+ @type = type
13
+ end
14
+
15
+ def extended?
16
+ extended
17
+ end
18
+
19
+ def to_query
20
+ if model.present?
21
+ model_fields = model.minimal_fields
22
+ "#{name}(#{model_fields.map(&:to_query).join(",")})"
23
+ else
24
+ name
25
+ end
26
+ end
27
+
28
+ def to_s
29
+ "Field name=#{name} extended=#{extended} model=#{model} type=#{type}"
30
+ end
31
+
32
+ def attr_name
33
+ name.underscore
34
+ end
35
+ end
36
+
37
+ class << self
38
+ attr_reader :fields
39
+
40
+ def all_fields
41
+ fields
42
+ end
43
+
44
+ def minimal_fields
45
+ fields.reject(&:extended?)
46
+ end
47
+
48
+ def field(name, extended: false)
49
+ @fields ||= []
50
+ @fields << Field.new(name: name, extended: extended)
51
+ register_field_as_attr(@fields.last)
52
+ end
53
+
54
+ def has_many(name, model, extended: true)
55
+ @fields ||= []
56
+ @fields << Field.new(name: name, extended: extended, model: model, type: :many)
57
+ register_field_as_attr(@fields.last)
58
+ end
59
+
60
+ def has_one(name, model, extended: true)
61
+ @fields ||= []
62
+ @fields << Field.new(name: name, extended: extended, model: model, type: :one)
63
+ register_field_as_attr(@fields.last)
64
+ end
65
+
66
+ def register_field_as_attr(field)
67
+ attr_accessor field.attr_name
68
+ end
69
+
70
+ def from_json(json)
71
+ if json.is_a?(Array)
72
+ json.map { |item| from_json(item) }
73
+ else
74
+ self.new.tap do |instance|
75
+ json.each do |key, value|
76
+ field = fields.find { |f| f.name == key }
77
+ next unless field.present?
78
+ field_value = field.model.present? && value.present? ? field.model.from_json(value) : value
79
+ instance.send(field.attr_name + "=", field_value)
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ def initialize(attrs = {})
87
+ attrs.each do |k, v|
88
+ next unless respond_to?(k.to_s + "=")
89
+ send(k.to_s + "=", v)
90
+ end
91
+ end
92
+
93
+ def to_h
94
+ self.class.all_fields.map do |field|
95
+ value = send(field.attr_name)
96
+ if field.model.present?
97
+ if value.is_a?(Array)
98
+ value = value.map(&:to_h)
99
+ elsif value.present?
100
+ value = value.to_h
101
+ end
102
+ end
103
+ [field.attr_name, value]
104
+ end.to_h
105
+ end
106
+ alias_method :to_hash, :to_h
107
+
108
+ def as_payload
109
+ to_h.compact.to_json
110
+ end
111
+
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,11 @@
1
+ module Youtrack
2
+ module Models
3
+ class FieldStyle < Base
4
+
5
+ field "id"
6
+ field "background"
7
+ field "foreground"
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,26 @@
1
+ module Youtrack
2
+ module Models
3
+ class Issue < Base
4
+
5
+ field "id"
6
+ field "idReadable"
7
+ field "numberInProject"
8
+ field "created"
9
+ field "updated"
10
+ field "resolved"
11
+ has_one "project", Project, extended: false
12
+ field "summary"
13
+ field "description"
14
+
15
+ has_one "reporter", User, extended: true
16
+ has_one "updater", User, extended: true
17
+ field "wikifiedDescription", extended: true
18
+ field "usesMarkdown", extended: true
19
+ has_many "fields", IssueCustomField, extended: true
20
+ field "isDraft", extended: true
21
+ has_many "tags", Tag, extended: true
22
+ # has_many "links", Link, extended: true
23
+ # has_many "comments", Comment, extended: true
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,11 @@
1
+ module Youtrack
2
+ module Models
3
+ class IssueCustomField < Base
4
+
5
+ field "id"
6
+ field "name"
7
+ has_one "value", IssueCustomFieldValue, extended: false
8
+
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ module Youtrack
2
+ module Models
3
+ class IssueCustomFieldValue < Base
4
+
5
+ field "id"
6
+ field "name"
7
+ field "localizedName"
8
+ field "fullName"
9
+ field "login"
10
+ field "avatarUrl"
11
+ field "isResolved"
12
+ field "text"
13
+ field "minutes"
14
+ field "presentation"
15
+ has_one "color", FieldStyle, extended: false
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,21 @@
1
+ module Youtrack
2
+ module Models
3
+ class Project < Base
4
+
5
+ field "id"
6
+ field "name"
7
+ field "shortName"
8
+ field "description"
9
+ field "archived"
10
+
11
+ has_one "createdBy", User, extended: true
12
+ # has_many "fields", Field, extended: true
13
+ field "fromEmail", extended: true
14
+ field "hubResourceId", extended: true
15
+ field "iconUrl", extended: true
16
+ field "timeTrackingEnabled", extended: true
17
+ has_one "leader", User, extended: true
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ module Youtrack
2
+ module Models
3
+ class Tag < Base
4
+
5
+ field "id"
6
+ field "name"
7
+ field "untagOnResolve"
8
+
9
+ has_one "owner", User
10
+
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ module Youtrack
2
+ module Models
3
+ class User < Base
4
+
5
+ field "id"
6
+ field "email"
7
+ field "fullName"
8
+ field "login"
9
+ field "name"
10
+
11
+ field "avatarUrl", extended: true
12
+ field "banned", extended: true
13
+ field "online", extended: true
14
+ field "guest", extended: true
15
+ field "jabberAccountName", extended: true
16
+ field "ringId", extended: true
17
+
18
+ has_many "tags", Tag
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,54 @@
1
+ module Youtrack
2
+ module Resources
3
+ class Base
4
+ attr_reader :client
5
+
6
+ def initialize(client:)
7
+ @client = client
8
+ end
9
+
10
+ def get_resource_with_fields(fields, path, options = {})
11
+ query_params = query_params_for_fields(fields).merge(options.delete(:params) || {})
12
+ response = client.get(path, { params: query_params })
13
+ deserialize_response(response)
14
+ end
15
+
16
+ def post_resource_with_fields(fields, path, data)
17
+ response = client.post(path, prepare_payload(data), { params: query_params_for_fields(fields) })
18
+ deserialize_response(response)
19
+ end
20
+
21
+ def delete_resource(path)
22
+ client.delete(path)
23
+ true
24
+ end
25
+
26
+ def query_params_for_fields(fields)
27
+ return {} unless fields.present?
28
+ { fields: fields.map(&:to_query).join(",") }
29
+ end
30
+
31
+ def deserialize_response(response)
32
+ $stdout.puts response.body if ENV["DEBUG"]
33
+ json = JSON.parse(response.body)
34
+ model.from_json(json)
35
+ end
36
+
37
+ def prepare_payload(data)
38
+ if data.respond_to?(:deep_transform_keys)
39
+ data = data.deep_transform_keys { |k| k.to_s.camelize(:lower) }
40
+ end
41
+ if data.respond_to?(:as_payload)
42
+ data = data.as_payload
43
+ elsif data.respond_to?(:to_json)
44
+ data = data.to_json
45
+ end
46
+ data
47
+ end
48
+
49
+ def self.descendants
50
+ ObjectSpace.each_object(Class).select { |klass| klass < self }
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,44 @@
1
+ module Youtrack
2
+ module Resources
3
+ class Issues < Base
4
+ PATHS = OpenStruct.new(
5
+ issue: '/issues/%{id}',
6
+ issues: '/issues',
7
+ commands: '/commands',
8
+ )
9
+
10
+ def by_id(id)
11
+ get_resource_with_fields(model.all_fields, PATHS.issue % { id: id })
12
+ end
13
+
14
+ def search(query, params = {})
15
+ issues = get_resource_with_fields(model.minimal_fields, PATHS.issues, { params: { query: query }.merge(params) })
16
+ return issues if issues.is_a?(Array)
17
+ [issues]
18
+ end
19
+
20
+ def delete(id)
21
+ delete_resource(PATHS.issue % { id: id })
22
+ end
23
+
24
+ # @param issue either a hash, json string or Issue instance
25
+ def create(issue)
26
+ post_resource_with_fields(model.all_fields, PATHS.issues, issue)
27
+ end
28
+
29
+ # @param issues either a list of ids or a list of Issue instances
30
+ def command(command, issues = [])
31
+ issues = issues.map { |item| { id: item.respond_to?("id") ? item.id : item } }
32
+ post_resource_with_fields([], PATHS.commands, { query: command, issues: issues })
33
+ true
34
+ end
35
+
36
+ private
37
+
38
+ def model
39
+ Models::Issue
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,25 @@
1
+ module Youtrack
2
+ module Resources
3
+ class Projects < Base
4
+ PATHS = OpenStruct.new(
5
+ projects: '/admin/projects',
6
+ project: '/admin/projects/%{id}',
7
+ )
8
+
9
+ def all(params = {})
10
+ get_resource_with_fields(model.minimal_fields, PATHS.projects, params: params)
11
+ end
12
+
13
+ def by_id(id)
14
+ get_resource_with_fields(model.all_fields, PATHS.project % { id: id })
15
+ end
16
+
17
+ private
18
+
19
+ def model
20
+ Models::Project
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,30 @@
1
+ module Youtrack
2
+ module Resources
3
+ class Users < Base
4
+ PATHS = OpenStruct.new(
5
+ current: '/users/me',
6
+ users: '/users',
7
+ user: '/users/%{id}'
8
+ )
9
+
10
+ def current
11
+ get_resource_with_fields(model.all_fields, PATHS.current)
12
+ end
13
+
14
+ def all(params = {})
15
+ get_resource_with_fields(model.minimal_fields, PATHS.users, params: params)
16
+ end
17
+
18
+ def by_id(id)
19
+ get_resource_with_fields(model.all_fields, PATHS.user % { id: id })
20
+ end
21
+
22
+ private
23
+
24
+ def model
25
+ Models::User
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,3 @@
1
+ module Youtrack
2
+ VERSION = "1.0.0"
3
+ end
data/lib/youtrack.rb ADDED
@@ -0,0 +1,7 @@
1
+ require "zeitwerk"
2
+ loader = Zeitwerk::Loader.for_gem
3
+ loader.setup
4
+
5
+ module Youtrack
6
+ # Your code goes here...
7
+ end
@@ -0,0 +1 @@
1
+ require 'youtrack'
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'youtrack/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "youtrack_client"
8
+ gem.version = Youtrack::VERSION
9
+ gem.authors = ["Shane Hofstetter"]
10
+ gem.email = ["shane.hofstetter@gmail.com"]
11
+ gem.description = %q{REST API client for youtrack from jetbrains}
12
+ gem.summary = %q{youtrack REST API client}
13
+ gem.homepage = "https://github.com/shanehofstetter/youtrack-rest-client-ruby"
14
+ gem.metadata["homepage_uri"] = gem.homepage
15
+ gem.metadata["source_code_uri"] = "https://github.com/shanehofstetter/youtrack-rest-client-ruby"
16
+ gem.metadata["changelog_uri"] = "https://github.com/shanehofstetter/youtrack-rest-client-ruby/blob/main/CHANGELOG.md"
17
+ gem.metadata["bug_tracker_uri"] = "https://github.com/shanehofstetter/youtrack-rest-client-ruby/issues"
18
+ gem.license = "MIT"
19
+
20
+ gem.files = `git ls-files -z`.split("\x0").reject do |f|
21
+ f.match(%r{^(test|spec|features)/})
22
+ end
23
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
24
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
25
+ gem.required_ruby_version = Gem::Requirement.new(">= 2.1.0")
26
+ gem.require_paths = ["lib"]
27
+
28
+ gem.add_runtime_dependency "rest-client", '~> 2.0'
29
+ gem.add_runtime_dependency "activesupport", '> 5.0.0'
30
+ gem.add_runtime_dependency "zeitwerk", '~> 2.6'
31
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: youtrack_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Shane Hofstetter
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-01-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rest-client
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">"
32
+ - !ruby/object:Gem::Version
33
+ version: 5.0.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">"
39
+ - !ruby/object:Gem::Version
40
+ version: 5.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: zeitwerk
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.6'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.6'
55
+ description: REST API client for youtrack from jetbrains
56
+ email:
57
+ - shane.hofstetter@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".github/workflows/specs.yml"
63
+ - ".gitignore"
64
+ - ".rspec"
65
+ - CHANGELOG.md
66
+ - Gemfile
67
+ - LICENSE
68
+ - README.md
69
+ - lib/youtrack.rb
70
+ - lib/youtrack/client.rb
71
+ - lib/youtrack/models/base.rb
72
+ - lib/youtrack/models/field_style.rb
73
+ - lib/youtrack/models/issue.rb
74
+ - lib/youtrack/models/issue_custom_field.rb
75
+ - lib/youtrack/models/issue_custom_field_value.rb
76
+ - lib/youtrack/models/project.rb
77
+ - lib/youtrack/models/tag.rb
78
+ - lib/youtrack/models/user.rb
79
+ - lib/youtrack/resources/base.rb
80
+ - lib/youtrack/resources/issues.rb
81
+ - lib/youtrack/resources/projects.rb
82
+ - lib/youtrack/resources/users.rb
83
+ - lib/youtrack/version.rb
84
+ - lib/youtrack_client.rb
85
+ - youtrack_client.gemspec
86
+ homepage: https://github.com/shanehofstetter/youtrack-rest-client-ruby
87
+ licenses:
88
+ - MIT
89
+ metadata:
90
+ homepage_uri: https://github.com/shanehofstetter/youtrack-rest-client-ruby
91
+ source_code_uri: https://github.com/shanehofstetter/youtrack-rest-client-ruby
92
+ changelog_uri: https://github.com/shanehofstetter/youtrack-rest-client-ruby/blob/main/CHANGELOG.md
93
+ bug_tracker_uri: https://github.com/shanehofstetter/youtrack-rest-client-ruby/issues
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: 2.1.0
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubygems_version: 3.1.6
110
+ signing_key:
111
+ specification_version: 4
112
+ summary: youtrack REST API client
113
+ test_files: []