mingle-api 0.0.1

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
+ SHA1:
3
+ metadata.gz: 94199aaae96d4214cecaf879930b8cea304b36f9
4
+ data.tar.gz: a0d01b5477bc18c396343320352e3beee40b466a
5
+ SHA512:
6
+ metadata.gz: b9200be2eb9fca66d9e947dbd7f59b521cc911e1ca4845d9d621603fad06b3da9f77f30bdef5d76c445896f9666903de6accb2e6d7cc6e9f7fb6c83adaef0872
7
+ data.tar.gz: 63440ec88b25d78fa9af6e7386a106616933bd61cb1da12cef41262d2bb5285a83d309174d198722f091b123ff0c9917b0b9be51ba3a8902338d9ed8f4b04f85
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rbenv-vars ADDED
@@ -0,0 +1,4 @@
1
+ MINGLE_SITE=xiao-test100
2
+ MINGLE_USERNAME=admin
3
+ MINGLE_PASSWORD=pass12!
4
+ MINGLE_SECRET_KEY=c1Ur61d/bhmgcH2cqWKyovlNgYHmpuZPu3ZSKzCjCXc=
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.1.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mingle-api.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Xiao Li
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,93 @@
1
+ # Mingle::Api
2
+
3
+ [Built with :yellow_heart: and :coffee: in San Francisco](http://getmingle.io)
4
+
5
+ [Mingle](http://getmingle.io) is a software development team collaborative tool, developed by ThoughtWorks Studios.
6
+ The Mingle API gem provides simple interface for you to build application talks to Mingle.
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'mingle-api'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install mingle-api
23
+
24
+ ## Usage
25
+
26
+ ### Initialize with HMac Auth for SaaS Mingle site
27
+
28
+ mingle = Mingle.new('site-name', hmac: [username, secret_key])
29
+
30
+ ### Initialize with Basic Auth for SaaS Mingle site
31
+
32
+ mingle = Mingle.new('site-name', basic_auth: [username, password])
33
+
34
+ ### Initialize with HMac for onsite Mingle site
35
+
36
+ mingle = Mingle.new('https://your-mingle-site-url', hmac: [username, secret_key])
37
+
38
+ ### Get all projects
39
+
40
+ projects = mingle.projects
41
+
42
+ ### Get project by identifier
43
+
44
+ project = mingle.projects('your_first_project')
45
+
46
+ ### Create project
47
+
48
+ mingle.create_project("Project Name")
49
+ # => OpenStruct.new(identifier, url)
50
+
51
+ Create with project description and from template
52
+
53
+ mingle.create_project("Project Name", description: "description", template: 'kanban')
54
+
55
+ ### Get first page cards in project
56
+
57
+ mingle.cards('project_identifier')
58
+
59
+ ### Get card by card number and project identifier
60
+
61
+ Let's say you have a project named Mingle and its identifier is mingle,
62
+ and card number 123 has a text property named Status and user property named Owner
63
+
64
+ mingle.card('mingle', 123)
65
+
66
+ You will get an OpenStruct object with attributes: name, description, type, status, owner
67
+ As Owner is a user property, the value of the owner will be the user login if it exists
68
+
69
+ ### Create card
70
+
71
+ mingle.create_card('project_identifier', name: 'card name', type: 'Story',
72
+ attachments: [['/path/to/file', "image/png"]],
73
+ properties: {status: 'New', priority: 'high'})
74
+ # => OpenStruct.new(number, url)
75
+
76
+ ## API design
77
+
78
+ 1. flat: one level API, you can find all APIs definition in class Mingle.
79
+ 2. data: all APIs return data object only, they are:
80
+ 1. Primitive type in Ruby
81
+ 2. OpenStruct object, with primitive type values (rule #1 flat)
82
+
83
+ ## Setup development environment
84
+
85
+ See .rbenv-vars file for environment variables need for test.
86
+
87
+ ## Contributing
88
+
89
+ 1. Fork it ( https://github.com/[my-github-username]/mingle-api/fork )
90
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
91
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
92
+ 4. Push to the branch (`git push origin my-new-feature`)
93
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.libs << "test"
7
+ t.test_files = FileList['test/*test.rb']
8
+ t.verbose = true
9
+ end
10
+
11
+
data/TODO ADDED
@@ -0,0 +1,20 @@
1
+ * Error handling
2
+ ** auth failure
3
+ ** Mingle's 5xx error
4
+ ** 4xx errors
5
+ ** Parse error message if Mingle responds
6
+ ** 3xx errors?
7
+ * Card type api
8
+ * property definition api
9
+ * Card APIs
10
+ ** get all card attributes
11
+ ** update card
12
+ ** delete card
13
+ ** attachments
14
+ ** transitions
15
+ * Project APIs
16
+ ** get all project attributes
17
+ * MQL execution
18
+ * Favorite APIs
19
+ * User APIs
20
+ * option to turn off OpenSSL::SSL::VERIFY_NONE
@@ -0,0 +1,5 @@
1
+ module Mingle
2
+ module Api
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
data/lib/mingle/api.rb ADDED
@@ -0,0 +1,7 @@
1
+ require "mingle/api/version"
2
+
3
+ module Mingle
4
+ module Api
5
+ # Your code goes here...
6
+ end
7
+ end
@@ -0,0 +1,61 @@
1
+ require 'net/http'
2
+ require 'net/https'
3
+ require 'net/http/post/multipart'
4
+ require 'api-auth'
5
+
6
+ class Mingle
7
+ class Http
8
+ class Error < StandardError
9
+ def initialize(request_class, url, response)
10
+ super("error[#{request_class.name}][#{url}][#{response.code}]: #{response.body}")
11
+ end
12
+ end
13
+
14
+ def initialize(credentials)
15
+ @credentials = credentials
16
+ end
17
+
18
+ def get(url)
19
+ process(Net::HTTP::Get, url)
20
+ end
21
+
22
+ def post(url, params)
23
+ process(Net::HTTP::Post::Multipart, url, params)
24
+ end
25
+
26
+ def process(request_class, url, form_data={}, headers=nil)
27
+ uri = URI(url)
28
+ http = Net::HTTP.new(uri.host, uri.port)
29
+
30
+ if uri.scheme == 'https'
31
+ http.use_ssl = true
32
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
33
+ end
34
+
35
+ request = request_class.new(uri.request_uri, form_data)
36
+
37
+ if headers
38
+ headers.each do |key, value|
39
+ request[key] = value
40
+ end
41
+ end
42
+
43
+ if @credentials[:hmac]
44
+ ApiAuth.sign!(request, *@credentials[:hmac])
45
+ elsif @credentials[:basic_auth]
46
+ request.basic_auth *@credentials[:basic_auth]
47
+ end
48
+
49
+ response = http.request(request)
50
+ raise Error.new(request_class, url, response) if response.code.to_i >= 300
51
+
52
+ to_canonical_response(response)
53
+ end
54
+
55
+ def to_canonical_response(response)
56
+ headers = {}
57
+ response.each_header {|key, value| headers[key] = value }
58
+ [response.code.to_i, response.body, headers]
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,33 @@
1
+ class Mingle
2
+ class Macro
3
+ def text(node, css)
4
+ if ret = node.at_css(css)
5
+ ret.text
6
+ end
7
+ end
8
+
9
+ def apply(node, attr)
10
+ case attr
11
+ when String
12
+ [attr, text(node, attr)]
13
+ when Symbol
14
+ apply(node, attr.to_s)
15
+ when Array
16
+ attr.map do |a|
17
+ apply(node, a)
18
+ end.flatten
19
+ when Hash
20
+ attr.map do |key, value|
21
+ case value
22
+ when Symbol
23
+ [value, text(node, key)]
24
+ when Proc
25
+ node.css(key).map do |child|
26
+ self.instance_exec(child, &value)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
data/lib/mingle.rb ADDED
@@ -0,0 +1,129 @@
1
+ require 'ostruct'
2
+ require 'nokogiri'
3
+
4
+ require 'mingle/http'
5
+ require 'mingle/macro'
6
+
7
+ class Mingle
8
+
9
+ attr_reader :site
10
+
11
+ PROJECT = [:name, :identifier, :description]
12
+ CARD = [:name, :description,
13
+ {
14
+ "card_type name" => :type,
15
+ 'properties property' => lambda do |node|
16
+ name = text(node, 'name')
17
+ value = case node[:type_description]
18
+ when /team list/
19
+ text(node, 'value login')
20
+ else
21
+ text(node, 'value')
22
+ end
23
+ [name.downcase, value]
24
+ end
25
+ }
26
+ ]
27
+
28
+ def initialize(site, credentials)
29
+ @site, @http = site, Http.new(credentials)
30
+ end
31
+
32
+ def projects
33
+ list(fetch(:projects), PROJECT)
34
+ end
35
+
36
+ def project(identifier)
37
+ ostruct(fetch(:projects, identifier), PROJECT)
38
+ end
39
+
40
+ def create_project(name, options={})
41
+ identifier = name.downcase.gsub(/[^a-z0-9_]/, '_')
42
+ @http.post(v2(:projects), {
43
+ "project[name]" => name,
44
+ "project[identifier]" => identifier,
45
+ "project[description]" => options[:description],
46
+ "project[template]" => false,
47
+ "template_name" => options[:template] ? "yml_#{options[:template]}_template" : nil
48
+ })
49
+ OpenStruct.new(:identifier => identifier, :url => url('projects', identifier))
50
+ end
51
+
52
+ def cards(project_identifier)
53
+ list(fetch(:projects, project_identifier, :cards), CARD)
54
+ end
55
+
56
+ def card(project_identifier, number)
57
+ ostruct(fetch(:projects, project_identifier, :cards, number), CARD)
58
+ end
59
+
60
+ def create_card(project_identifier, attrs)
61
+ params = [
62
+ ["card[name]", attrs[:name]],
63
+ ["card[card_type_name]", attrs[:type]],
64
+ ["card[description]", attrs[:description]]
65
+ ]
66
+ Array(attrs[:attachments]).each_with_index do |attachment, i|
67
+ path, content_type = attachment
68
+ params << ["attachments[#{i}]", UploadIO.new(File.new(path), content_type, File.basename(path))]
69
+ end
70
+ Array(attrs[:properties]).each_with_index do |prop, i|
71
+ name, value = prop
72
+ params << ["card[properties][][name]", name]
73
+ params << ["card[properties][][value]", value]
74
+ end
75
+ resp = @http.post(v2(:projects, project_identifier, :cards), params)
76
+ number = resp[2]["location"].split("/").last.split('.').first
77
+ OpenStruct.new(:number => number, :url => url('projects', project_identifier, 'cards', number))
78
+ end
79
+
80
+ def site_api_url
81
+ gen_site_url(api_host)
82
+ end
83
+
84
+ def site_url
85
+ gen_site_url(host)
86
+ end
87
+
88
+ private
89
+ def url(*parts)
90
+ File.join(site_url, *parts)
91
+ end
92
+
93
+ def api_host
94
+ 'mingle-api.thoughtworks.com' || ENV['MINGLE_API_HOST']
95
+ end
96
+
97
+ def host
98
+ 'mingle.thoughtworks.com' || ENV['MINGLE_HOST']
99
+ end
100
+
101
+ def fetch(*resources)
102
+ dom(@http.get(v2(*resources))[1]).root
103
+ end
104
+
105
+ def list(dom, attrs)
106
+ dom.children.map do |child|
107
+ ostruct(child, attrs)
108
+ end
109
+ end
110
+
111
+ def ostruct(node, attrs)
112
+ macro = Macro.new
113
+ OpenStruct.new(Hash[*macro.apply(node, attrs)])
114
+ end
115
+
116
+ def dom(xml)
117
+ Nokogiri::XML(xml) do |config|
118
+ config.options = Nokogiri::XML::ParseOptions::NOBLANKS | Nokogiri::XML::ParseOptions::STRICT | Nokogiri::XML::ParseOptions::NONET
119
+ end
120
+ end
121
+
122
+ def v2(*parts)
123
+ [File.join(site_api_url, 'api/v2', *parts.map(&:to_s)), 'xml'].join('.')
124
+ end
125
+
126
+ def gen_site_url(h)
127
+ site =~ /^http/i ? site : "https://#{site}.#{h}"
128
+ end
129
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mingle/api/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "mingle-api"
8
+ spec.version = Mingle::Api::VERSION
9
+ spec.authors = ["Xiao Li"]
10
+ spec.email = ["swing1979@gmail.com"]
11
+ spec.summary = %q{[The Mingle API gem provides simple interface for you to build ruby application talks to Mingle.}
12
+ spec.description = %q{[Mingle](http://getmingle.io) is a software development team collaborative tool, developed by ThoughtWorks Studios. The Mingle API gem provides simple interface for you to build ruby application talks to Mingle.}
13
+ spec.homepage = "https://github.com/ThoughtWorksStudios/mingle-api"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency('api-auth')
22
+ spec.add_dependency('multipart-post')
23
+ spec.add_dependency('nokogiri')
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.7"
26
+ spec.add_development_dependency "rake", "~> 10.0"
27
+ spec.add_development_dependency "minitest"
28
+ end
@@ -0,0 +1,63 @@
1
+ require 'test_helper'
2
+
3
+ class MingleTest < Minitest::Test
4
+ def test_projects
5
+ mingle = create_basic_auth_mingle
6
+ first_proj = mingle.projects.find{|proj| proj.identifier == 'your_first_project'}
7
+ assert first_proj
8
+ assert_equal 'Your First Project', first_proj.name
9
+ end
10
+
11
+ def test_find_project_by_identifier
12
+ mingle = create_basic_auth_mingle
13
+ first_proj = mingle.project('your_first_project')
14
+ assert first_proj
15
+ assert_equal 'Your First Project', first_proj.name
16
+ end
17
+
18
+ def test_create_project
19
+ t = Time.now
20
+ mingle = create_basic_auth_mingle
21
+ project = mingle.create_project("Hello #{t.to_i}", description: "proj created at #{t}", template: 'kanban')
22
+ assert_equal "hello_#{t.to_i}", project.identifier
23
+ assert_equal "https://xiao-test100.mingle.thoughtworks.com/projects/hello_#{t.to_i}", project.url
24
+
25
+ proj = mingle.project(project.identifier)
26
+ assert_equal "proj created at #{t}", proj.description
27
+ end
28
+
29
+ def test_cards
30
+ mingle = create_hmac_auth_mingle
31
+ cards = mingle.cards('your_first_project')
32
+ assert cards.size > 0
33
+ end
34
+
35
+ def test_find_card_by_number
36
+ mingle = create_hmac_auth_mingle
37
+ card1 = mingle.card('your_first_project', 1)
38
+ assert_equal 'Welcome to Mingle', card1.name
39
+ assert_equal 'Story', card1.type
40
+ assert_equal 'New', card1.status
41
+ assert_equal 'xli_test100', card1.owner
42
+
43
+ card2 = mingle.card('your_first_project', 2)
44
+ assert_equal 'card name', card2.name
45
+ assert_equal 'Story', card2.type
46
+ assert_equal 'New', card2.status
47
+ assert_equal nil, card2.owner
48
+ end
49
+
50
+ def test_create_card
51
+ mingle = create_hmac_auth_mingle
52
+ card = mingle.create_card('your_first_project', name: 'card name', type: 'Story', description: 'card desc', properties: {status: 'new', priority: 'must'}, attachments: [[__FILE__, 'plain/text']])
53
+ assert card.number
54
+ assert_equal "https://xiao-test100.mingle.thoughtworks.com/projects/your_first_project/cards/#{card.number}", card.url
55
+
56
+ card = mingle.card('your_first_project', card.number)
57
+ assert_equal 'card desc', card.description
58
+ assert_equal 'card name', card.name
59
+ assert_equal 'Story', card.type
60
+ assert_equal 'New', card.status
61
+ assert_equal 'Must', card.priority
62
+ end
63
+ end
@@ -0,0 +1,11 @@
1
+
2
+ require 'mingle'
3
+ require "minitest/autorun"
4
+
5
+ def create_basic_auth_mingle
6
+ Mingle.new(ENV['MINGLE_SITE'], basic_auth: [ENV['MINGLE_USERNAME'], ENV['MINGLE_PASSWORD']])
7
+ end
8
+
9
+ def create_hmac_auth_mingle
10
+ Mingle.new(ENV['MINGLE_SITE'], hmac: [ENV['MINGLE_USERNAME'], ENV['MINGLE_SECRET_KEY']])
11
+ end
metadata ADDED
@@ -0,0 +1,149 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mingle-api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Xiao Li
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: api-auth
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: multipart-post
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: nokogiri
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.7'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.7'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: minitest
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: "[Mingle](http://getmingle.io) is a software development team collaborative
98
+ tool, developed by ThoughtWorks Studios. The Mingle API gem provides simple interface
99
+ for you to build ruby application talks to Mingle."
100
+ email:
101
+ - swing1979@gmail.com
102
+ executables: []
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - ".gitignore"
107
+ - ".rbenv-vars"
108
+ - ".ruby-version"
109
+ - Gemfile
110
+ - LICENSE.txt
111
+ - README.md
112
+ - Rakefile
113
+ - TODO
114
+ - lib/mingle.rb
115
+ - lib/mingle/api.rb
116
+ - lib/mingle/api/version.rb
117
+ - lib/mingle/http.rb
118
+ - lib/mingle/macro.rb
119
+ - mingle-api.gemspec
120
+ - test/mingle_test.rb
121
+ - test/test_helper.rb
122
+ homepage: https://github.com/ThoughtWorksStudios/mingle-api
123
+ licenses:
124
+ - MIT
125
+ metadata: {}
126
+ post_install_message:
127
+ rdoc_options: []
128
+ require_paths:
129
+ - lib
130
+ required_ruby_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ required_rubygems_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ requirements: []
141
+ rubyforge_project:
142
+ rubygems_version: 2.2.0
143
+ signing_key:
144
+ specification_version: 4
145
+ summary: "[The Mingle API gem provides simple interface for you to build ruby application
146
+ talks to Mingle."
147
+ test_files:
148
+ - test/mingle_test.rb
149
+ - test/test_helper.rb