dpl-releases 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 44e70cc91d21e963c4aeb3f8e1db0bea45fae7b8
4
+ data.tar.gz: 933d5352e2199ee2cc1659d830aee46e5e85f651
5
+ SHA512:
6
+ metadata.gz: e967a9c342b0fab62d6ac5d1587885ec2d6c5b45fbc7204f18582c5d607076e1a52ecec595d15efc71f811189559a47b57aa5d579782980d3f69a3d856c4f0d4
7
+ data.tar.gz: 1fe1bb7d81f066a76baceb071b1b2f52c81c1cee051ae26304314d7df6e10405fd4da53fbaddf6e9862842a5be830f55fabd7312526993d080d72d47b74adc81
@@ -0,0 +1,3 @@
1
+ require './gemspec_helper'
2
+
3
+ gemspec_for 'releases', [['octokit', '~> 4.6.2'], ['mime-types', '~> 2.0']]
@@ -0,0 +1,134 @@
1
+ require 'octokit'
2
+ require 'mime-types'
3
+
4
+ module DPL
5
+ class Provider
6
+ class Releases < Provider
7
+ require 'pathname'
8
+
9
+ def travis_tag
10
+ # Check if $TRAVIS_TAG is unset or set but empty
11
+ if context.env.fetch('TRAVIS_TAG','') == ''
12
+ nil
13
+ else
14
+ context.env['TRAVIS_TAG']
15
+ end
16
+ end
17
+
18
+ def get_tag
19
+ if travis_tag.nil?
20
+ @tag ||= `git describe --tags --exact-match 2>/dev/null`.chomp
21
+ else
22
+ @tag ||= travis_tag
23
+ end
24
+ end
25
+
26
+ def api
27
+ if options[:user] and options[:password]
28
+ @api ||= Octokit::Client.new(:login => options[:user], :password => options[:password])
29
+ else
30
+ @api ||= Octokit::Client.new(:access_token => option(:api_key))
31
+ end
32
+ end
33
+
34
+ def slug
35
+ options.fetch(:repo) { context.env['TRAVIS_REPO_SLUG'] }
36
+ end
37
+
38
+ def releases
39
+ @releases ||= api.releases(slug)
40
+ end
41
+
42
+ def user
43
+ @user ||= api.user
44
+ end
45
+
46
+ def files
47
+ if options[:file_glob]
48
+ Array(options[:file]).map do |glob|
49
+ Dir.glob(glob)
50
+ end.flatten
51
+ else
52
+ Array(options[:file])
53
+ end
54
+ end
55
+
56
+ def needs_key?
57
+ false
58
+ end
59
+
60
+ def check_app
61
+ log "Deploying to repo: #{slug}"
62
+
63
+ context.shell 'git fetch --tags' if travis_tag.nil?
64
+ log "Current tag is: #{get_tag}"
65
+ end
66
+
67
+ def setup_auth
68
+ user.login
69
+ end
70
+
71
+ def check_auth
72
+ setup_auth
73
+
74
+ unless api.scopes.include? 'public_repo' or api.scopes.include? 'repo'
75
+ raise Error, "Dpl does not have permission to upload assets. Make sure your token contains the repo or public_repo scope."
76
+ end
77
+
78
+ log "Logged in as #{user.name}"
79
+ end
80
+
81
+ def push_app
82
+ tag_matched = false
83
+ release_url = nil
84
+
85
+ if options[:release_number]
86
+ tag_matched = true
87
+ release_url = "https://api.github.com/repos/" + slug + "/releases/" + options[:release_number]
88
+ else
89
+ releases.each do |release|
90
+ if release.tag_name == get_tag
91
+ release_url = release.rels[:self].href
92
+ tag_matched = true
93
+ end
94
+ end
95
+ end
96
+
97
+ #If for some reason GitHub hasn't already created a release for the tag, create one
98
+ if tag_matched == false
99
+ release_url = api.create_release(slug, get_tag, options.merge({:draft => true})).rels[:self].href
100
+ end
101
+
102
+ files.each do |file|
103
+ existing_url = nil
104
+ filename = Pathname.new(file).basename.to_s
105
+ api.release(release_url).rels[:assets].get.data.each do |existing_file|
106
+ if existing_file.name == filename
107
+ existing_url = existing_file.url
108
+ end
109
+ end
110
+ if !existing_url
111
+ upload_file(file, filename, release_url)
112
+ elsif existing_url && options[:overwrite]
113
+ log "#{filename} already exists, overwriting."
114
+ api.delete_release_asset(existing_url)
115
+ upload_file(file, filename, release_url)
116
+ else
117
+ log "#{filename} already exists, skipping."
118
+ end
119
+ end
120
+
121
+ api.update_release(release_url, {:draft => false}.merge(options))
122
+ end
123
+
124
+ def upload_file(file, filename, release_url)
125
+ content_type = MIME::Types.type_for(file).first.to_s
126
+ if content_type.empty?
127
+ # Specify the default content type, as it is required by GitHub
128
+ content_type = "application/octet-stream"
129
+ end
130
+ api.upload_asset(release_url, file, {:name => filename, :content_type => content_type})
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,303 @@
1
+ require 'spec_helper'
2
+ require 'dpl/provider/releases'
3
+ require 'octokit'
4
+
5
+ describe DPL::Provider::Releases do
6
+ subject :provider do
7
+ described_class.new(DummyContext.new, :api_key => '0123445789qwertyuiop0123445789qwertyuiop', :file => 'blah.txt')
8
+ end
9
+
10
+ describe "#travis_tag" do
11
+ example "When $TRAVIS_TAG is nil" do
12
+ provider.context.env['TRAVIS_TAG'] = nil
13
+
14
+ expect(provider.travis_tag).to eq(nil)
15
+ end
16
+
17
+ example "When $TRAVIS_TAG if set but empty" do
18
+ provider.context.env['TRAVIS_TAG'] = nil
19
+
20
+ expect(provider.travis_tag).to eq(nil)
21
+ end
22
+
23
+ example "When $TRAVIS_TAG if set" do
24
+ provider.context.env['TRAVIS_TAG'] = "foo"
25
+
26
+ expect(provider.travis_tag).to eq("foo")
27
+ end
28
+ end
29
+
30
+ describe "#api" do
31
+ example "With API key" do
32
+ api = double(:api)
33
+ expect(::Octokit::Client).to receive(:new).with(:access_token => '0123445789qwertyuiop0123445789qwertyuiop').and_return(api)
34
+ expect(provider.api).to eq(api)
35
+ end
36
+
37
+ example "With username and password" do
38
+ api = double(:api)
39
+ provider.options.update(:user => 'foo')
40
+ provider.options.update(:password => 'bar')
41
+
42
+ expect(::Octokit::Client).to receive(:new).with(:login => 'foo', :password => 'bar').and_return(api)
43
+ expect(provider.api).to eq(api)
44
+ end
45
+ end
46
+
47
+ describe "#releases" do
48
+ example "With ENV Slug" do
49
+ allow(provider).to receive(:slug).and_return("foo/bar")
50
+
51
+ expect(provider.api).to receive(:releases).with("foo/bar")
52
+ provider.releases
53
+ end
54
+
55
+ example "With repo option" do
56
+ provider.options.update(:repo => 'bar/foo')
57
+
58
+ expect(provider.api).to receive(:releases).with('bar/foo')
59
+ provider.releases
60
+ end
61
+ end
62
+
63
+ describe "#files" do
64
+ example "without file globbing and a single file" do
65
+ expect(provider.files).to eq(['blah.txt'])
66
+ end
67
+
68
+ example "without file globbing and multiple files" do
69
+ provider.options.update(:file => ['foo.txt', 'bar.txt'])
70
+ expect(provider.files).to eq(['foo.txt', 'bar.txt'])
71
+ end
72
+
73
+ example "with file globbing and a single glob" do
74
+ provider.options.update(:file_glob => true)
75
+ provider.options.update(:file => 'bl*.txt')
76
+ expect(::Dir).to receive(:glob).with('bl*.txt').and_return(['blah.txt'])
77
+ expect(provider.files).to eq(['blah.txt'])
78
+ end
79
+
80
+ example "with file globbing and multiple globs" do
81
+ provider.options.update(:file_glob => true)
82
+ provider.options.update(:file => ['f*.txt', 'b*.txt'])
83
+ expect(::Dir).to receive(:glob).with('f*.txt').and_return(['foo.txt'])
84
+ expect(::Dir).to receive(:glob).with('b*.txt').and_return(['bar.txt'])
85
+ expect(provider.files).to eq(['foo.txt', 'bar.txt'])
86
+ end
87
+ end
88
+
89
+ describe "#needs_key?" do
90
+ example do
91
+ expect(provider.needs_key?).to eq(false)
92
+ end
93
+ end
94
+
95
+ describe "#check_app" do
96
+ example "Without $TRAVIS_TAG" do
97
+ allow(provider).to receive(:travis_tag).and_return(nil)
98
+ allow(provider).to receive(:slug).and_return("foo/bar")
99
+ allow(provider).to receive(:get_tag).and_return("foo")
100
+
101
+ expect(provider.context).to receive(:shell).with("git fetch --tags")
102
+ expect(provider).to receive(:log).with("Deploying to repo: foo/bar")
103
+ expect(provider).to receive(:log).with("Current tag is: foo")
104
+
105
+ provider.check_app
106
+ end
107
+
108
+ example "With $TRAVIS_TAG" do
109
+ allow(provider).to receive(:travis_tag).and_return("bar")
110
+ allow(provider).to receive(:slug).and_return("foo/bar")
111
+
112
+ expect(provider.context).not_to receive(:shell).with("git fetch --tags")
113
+ expect(provider).to receive(:log).with("Deploying to repo: foo/bar")
114
+ expect(provider).to receive(:log).with("Current tag is: bar")
115
+
116
+ provider.check_app
117
+ end
118
+ end
119
+
120
+ describe "#get_tag" do
121
+ example "Without $TRAVIS_TAG" do
122
+ allow(provider).to receive(:travis_tag).and_return(nil)
123
+ allow(provider).to receive(:`).and_return("bar")
124
+
125
+ expect(provider.get_tag).to eq("bar")
126
+ end
127
+
128
+ example "With $TRAVIS_TAG" do
129
+ allow(provider).to receive(:travis_tag).and_return("foo")
130
+
131
+ expect(provider.get_tag).to eq("foo")
132
+ end
133
+ end
134
+
135
+ describe "#check_auth" do
136
+ example "With proper permissions" do
137
+ allow_message_expectations_on_nil
138
+ allow(provider).to receive(:user)
139
+ allow(provider).to receive(:setup_auth)
140
+ expect(provider.api).to receive(:scopes).and_return(["public_repo"])
141
+ expect(provider.user).to receive(:name).and_return("foo")
142
+ expect(provider).to receive(:log).with("Logged in as foo")
143
+ provider.check_auth
144
+ end
145
+
146
+ example "With improper permissions" do
147
+ allow_message_expectations_on_nil
148
+ allow(provider).to receive(:user)
149
+ allow(provider).to receive(:setup_auth)
150
+ expect(provider.api).to receive(:scopes).exactly(2).times.and_return([])
151
+ expect { provider.check_auth }.to raise_error(DPL::Error)
152
+ end
153
+ end
154
+
155
+ describe "#push_app" do
156
+ example "When Release Exists but has no Files" do
157
+ allow_message_expectations_on_nil
158
+
159
+ provider.options.update(:file => ["test/foo.bar", "bar.txt"])
160
+
161
+ allow(provider).to receive(:releases).and_return([""])
162
+ allow(provider).to receive(:get_tag).and_return("v0.0.0")
163
+
164
+ provider.releases.map do |release|
165
+ allow(release).to receive(:tag_name).and_return("v0.0.0")
166
+ allow(release).to receive(:rels).and_return({:self => nil})
167
+ allow(release.rels[:self]).to receive(:href)
168
+ end
169
+
170
+ allow(provider.api).to receive(:release)
171
+ allow(provider.api.release).to receive(:rels).and_return({:assets => nil})
172
+ allow(provider.api.release.rels[:assets]).to receive(:get).and_return({:data => [""]})
173
+ allow(provider.api.release.rels[:assets].get).to receive(:data).and_return([])
174
+
175
+ expect(provider.api).to receive(:upload_asset).with(anything, "test/foo.bar", {:name=>"foo.bar", :content_type=>"application/octet-stream"})
176
+ expect(provider.api).to receive(:upload_asset).with(anything, "bar.txt", {:name=>"bar.txt", :content_type=>"text/plain"})
177
+ expect(provider.api).to receive(:update_release).with(anything, hash_including(:draft => false))
178
+
179
+ provider.push_app
180
+ end
181
+
182
+ example "When Release Exists and has Files" do
183
+ allow_message_expectations_on_nil
184
+
185
+ provider.options.update(:file => ["test/foo.bar", "bar.txt"])
186
+
187
+ allow(provider).to receive(:releases).and_return([""])
188
+ allow(provider).to receive(:get_tag).and_return("v0.0.0")
189
+
190
+ provider.releases.map do |release|
191
+ allow(release).to receive(:tag_name).and_return("v0.0.0")
192
+ allow(release).to receive(:rels).and_return({:self => nil})
193
+ allow(release.rels[:self]).to receive(:href)
194
+ end
195
+
196
+ allow(provider.api).to receive(:release)
197
+ allow(provider.api.release).to receive(:rels).and_return({:assets => nil})
198
+ allow(provider.api.release.rels[:assets]).to receive(:get).and_return({:data => [""]})
199
+ allow(provider.api.release.rels[:assets].get).to receive(:data).and_return([double(:name => "foo.bar", :url => 'foo-bar-url'), double(:name => "foo.foo", :url => 'foo-foo-url')])
200
+
201
+ expect(provider.api).to receive(:upload_asset).with(anything, "bar.txt", {:name=>"bar.txt", :content_type=>"text/plain"})
202
+ expect(provider).to receive(:log).with("foo.bar already exists, skipping.")
203
+ expect(provider.api).to receive(:update_release).with(anything, hash_including(:draft => false))
204
+
205
+ provider.push_app
206
+ end
207
+
208
+ example "When Release Exists and has Files but overwrite flag is true" do
209
+ allow_message_expectations_on_nil
210
+
211
+ provider.options.update(:file => ["exists.txt"])
212
+ provider.options.update(:overwrite => true)
213
+
214
+ allow(provider).to receive(:releases).and_return([""])
215
+ allow(provider).to receive(:get_tag).and_return("v0.0.0")
216
+
217
+ provider.releases.map do |release|
218
+ allow(release).to receive(:tag_name).and_return("v0.0.0")
219
+ allow(release).to receive(:rels).and_return({:self => nil})
220
+ allow(release.rels[:self]).to receive(:href)
221
+ end
222
+
223
+ allow(provider.api).to receive(:release)
224
+ allow(provider.api.release).to receive(:rels).and_return({:assets => nil})
225
+ allow(provider.api.release.rels[:assets]).to receive(:get).and_return({:data => [""]})
226
+ allow(provider.api.release.rels[:assets].get).to receive(:data).and_return([double(:name => "exists.txt", :url => "release-url")])
227
+
228
+ expect(provider.api).to receive(:delete_release_asset).with("release-url").and_return(true)
229
+ expect(provider.api).to receive(:upload_asset).with(anything, "exists.txt", {:name=>"exists.txt", :content_type=>"text/plain"})
230
+ expect(provider.api).to receive(:update_release).with(anything, hash_including(:draft => false))
231
+
232
+ provider.push_app
233
+ end
234
+
235
+ example "When Release Doesn't Exist" do
236
+ allow_message_expectations_on_nil
237
+
238
+ provider.options.update(:file => ["test/foo.bar", "bar.txt"])
239
+
240
+ allow(provider).to receive(:releases).and_return([""])
241
+
242
+ provider.releases.map do |release|
243
+ allow(release).to receive(:tag_name).and_return("foo")
244
+ allow(release).to receive(:rels).and_return({:self => nil})
245
+ allow(release.rels[:self]).to receive(:href)
246
+ end
247
+
248
+ allow(provider.api).to receive(:create_release)
249
+ allow(provider.api.create_release).to receive(:rels).and_return({:self => nil})
250
+ allow(provider.api.create_release.rels[:slef]).to receive(:href)
251
+
252
+ allow(provider.api).to receive(:release)
253
+ allow(provider.api.release).to receive(:rels).and_return({:assets => nil})
254
+ allow(provider.api.release.rels[:assets]).to receive(:get).and_return({:data => nil})
255
+ allow(provider.api.release.rels[:assets].get).to receive(:data).and_return([])
256
+
257
+ expect(provider.api).to receive(:upload_asset).with(anything, "test/foo.bar", {:name=>"foo.bar", :content_type=>"application/octet-stream"})
258
+ expect(provider.api).to receive(:upload_asset).with(anything, "bar.txt", {:name=>"bar.txt", :content_type=>"text/plain"})
259
+ expect(provider.api).to receive(:update_release).with(anything, hash_including(:draft => false))
260
+
261
+ provider.push_app
262
+ end
263
+
264
+ example "With Release Number" do
265
+ allow_message_expectations_on_nil
266
+
267
+ provider.options.update(:file => ["bar.txt"])
268
+ provider.options.update(:release_number => "1234")
269
+
270
+ allow(provider).to receive(:slug).and_return("foo/bar")
271
+
272
+ allow(provider.api).to receive(:release)
273
+ allow(provider.api.release).to receive(:rels).and_return({:assets => nil})
274
+ allow(provider.api.release.rels[:assets]).to receive(:get).and_return({:data => nil})
275
+ allow(provider.api.release.rels[:assets].get).to receive(:data).and_return([])
276
+
277
+ expect(provider.api).to receive(:upload_asset).with("https://api.github.com/repos/foo/bar/releases/1234", "bar.txt", {:name=>"bar.txt", :content_type=>"text/plain"})
278
+ expect(provider.api).to receive(:update_release).with(anything, hash_including(:draft => false))
279
+
280
+ provider.push_app
281
+ end
282
+
283
+ example "When draft is true" do
284
+ allow_message_expectations_on_nil
285
+
286
+ provider.options.update(:file => ["bar.txt"])
287
+ provider.options.update(:release_number => "1234")
288
+ provider.options.update(:draft => true)
289
+
290
+ allow(provider).to receive(:slug).and_return("foo/bar")
291
+
292
+ allow(provider.api).to receive(:release)
293
+ allow(provider.api.release).to receive(:rels).and_return({:assets => nil})
294
+ allow(provider.api.release.rels[:assets]).to receive(:get).and_return({:data => nil})
295
+ allow(provider.api.release.rels[:assets].get).to receive(:data).and_return([])
296
+
297
+ expect(provider.api).to receive(:upload_asset).with("https://api.github.com/repos/foo/bar/releases/1234", "bar.txt", {:name=>"bar.txt", :content_type=>"text/plain"})
298
+ expect(provider.api).to receive(:update_release).with(anything, hash_including(:draft => true))
299
+
300
+ provider.push_app
301
+ end
302
+ end
303
+ end
metadata ADDED
@@ -0,0 +1,187 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dpl-releases
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.9.0
5
+ platform: ruby
6
+ authors:
7
+ - Konstantin Haase
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-03-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: dpl
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.9.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 1.9.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: octokit
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 4.6.2
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 4.6.2
41
+ - !ruby/object:Gem::Dependency
42
+ name: mime-types
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec-its
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
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
+ - !ruby/object:Gem::Dependency
98
+ name: json_pure
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: tins
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: coveralls
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: highline
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ description: deploy tool abstraction for clients
154
+ email: konstantin.mailinglists@googlemail.com
155
+ executables: []
156
+ extensions: []
157
+ extra_rdoc_files: []
158
+ files:
159
+ - dpl-releases.gemspec
160
+ - lib/dpl/provider/releases.rb
161
+ - spec/provider/releases_spec.rb
162
+ homepage: https://github.com/travis-ci/dpl
163
+ licenses:
164
+ - MIT
165
+ metadata: {}
166
+ post_install_message:
167
+ rdoc_options: []
168
+ require_paths:
169
+ - lib
170
+ required_ruby_version: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - ">="
173
+ - !ruby/object:Gem::Version
174
+ version: '2.2'
175
+ required_rubygems_version: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: '0'
180
+ requirements: []
181
+ rubyforge_project:
182
+ rubygems_version: 2.6.13
183
+ signing_key:
184
+ specification_version: 4
185
+ summary: deploy tool
186
+ test_files:
187
+ - spec/provider/releases_spec.rb