artifactory 2.2.1 → 2.3.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.
@@ -15,5 +15,5 @@
15
15
  #
16
16
 
17
17
  module Artifactory
18
- VERSION = '2.2.1'
18
+ VERSION = '2.3.0'
19
19
  end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ module Artifactory
4
+ describe Resource::BuildComponent, :integration do
5
+ let(:build_component) { described_class.find('wicket') }
6
+
7
+ describe '.all' do
8
+ it 'returns an array of build component objects' do
9
+ results = described_class.all
10
+ expect(results).to be_a(Array)
11
+ expect(results.first).to be_a(described_class)
12
+ end
13
+ end
14
+
15
+ describe '.find' do
16
+ it 'finds a build component by name' do
17
+ expect(build_component).to be_a(described_class)
18
+ expect(build_component.name).to eq('wicket')
19
+ expect(build_component.last_started).to eq(Time.parse('2015-06-19T20:13:20.222Z'))
20
+ end
21
+ end
22
+
23
+ describe '#delete' do
24
+ let(:build_numbers) { %w( 51 52 )}
25
+ let(:delete_all) { false }
26
+
27
+ it 'deletes the specified builds from the component' do
28
+
29
+ expect(build_component.delete(
30
+ build_numbers: build_numbers,
31
+ delete_all: delete_all
32
+ )).to be_truthy
33
+ end
34
+
35
+ context 'no build numbers provided' do
36
+ let(:build_numbers) { nil }
37
+
38
+ it 'deletes no builds' do
39
+
40
+ expect(build_component.delete(
41
+ delete_all: delete_all
42
+ )).to be_falsey
43
+ end
44
+
45
+ context 'the delete_all flag is true' do
46
+ let(:delete_all) { true }
47
+
48
+ it 'deletes the component and all builds' do
49
+ expect(build_component.delete(
50
+ delete_all: delete_all
51
+ )).to be_truthy
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ describe '#rename' do
58
+ it 'renames the build component on the server' do
59
+
60
+ expect(build_component.rename('fricket')).to be_truthy
61
+ end
62
+ end
63
+ end
64
+ end
@@ -3,7 +3,35 @@ require 'spec_helper'
3
3
  module Artifactory
4
4
  describe Resource::Build, :integration do
5
5
  describe '.all' do
6
- it 'returns an array of build objects'
6
+ it 'returns an array of build objects' do
7
+ results = described_class.all('wicket')
8
+ expect(results).to be_a(Array)
9
+ expect(results.first).to be_a(described_class)
10
+ end
11
+ end
12
+
13
+ describe '.find' do
14
+ it 'finds a build by component and number' do
15
+ build = described_class.find('wicket', 51)
16
+
17
+ expect(build).to be_a(described_class)
18
+ expect(build.name).to eq('wicket')
19
+ expect(build.number).to eq('51')
20
+ expect(build.started).to eq(Time.parse('2014-09-30T12:00:19.893+0300'))
21
+ end
22
+ end
23
+
24
+ describe '#save' do
25
+ it 'saves the build data to the server' do
26
+ build = described_class.new(
27
+ name: 'fricket',
28
+ number: '1',
29
+ properties: {
30
+ 'buildInfo.env.JAVA_HOME' => '/usr/jdk/latest'
31
+ })
32
+
33
+ expect(build.save).to be_truthy
34
+ end
7
35
  end
8
36
  end
9
37
  end
@@ -25,9 +25,10 @@ RSpec.configure do |config|
25
25
  config.before(:each) { Artifactory.reset! }
26
26
  config.after(:each) { Artifactory.reset! }
27
27
 
28
- #
29
28
  config.before(:each, :integration) do
30
29
  Artifactory.endpoint = 'http://localhost:8889'
30
+ Artifactory.username = nil
31
+ Artifactory.password = nil
31
32
  stub_request(:any, /#{Artifactory.endpoint}/).to_rack(Artifactory::APIServer)
32
33
  end
33
34
 
@@ -7,6 +7,7 @@ module Artifactory
7
7
  #
8
8
  class APIServer < Sinatra::Base
9
9
  require_relative 'api_server/artifact_endpoints'
10
+ require_relative 'api_server/build_component_endpoints'
10
11
  require_relative 'api_server/build_endpoints'
11
12
  require_relative 'api_server/group_endpoints'
12
13
  require_relative 'api_server/repository_endpoints'
@@ -16,6 +17,7 @@ module Artifactory
16
17
  require_relative 'api_server/user_endpoints'
17
18
 
18
19
  register APIServer::ArtifactEndpoints
20
+ register APIServer::BuildComponentEndpoints
19
21
  register APIServer::BuildEndpoints
20
22
  register APIServer::GroupEndpoints
21
23
  register APIServer::PermissionTargetEndpoints
@@ -0,0 +1,44 @@
1
+ module Artifactory
2
+ module APIServer::BuildComponentEndpoints
3
+ def self.registered(app)
4
+ app.get('/api/build') do
5
+ content_type 'application/vnd.org.jfrog.build.Builds+json'
6
+ JSON.fast_generate(
7
+ 'uri' => server_url.join('/api/build'),
8
+ 'builds' => [
9
+ {
10
+ 'uri' => '/wicket',
11
+ 'lastStarted' => '2015-06-19T20:13:20.222Z',
12
+ },
13
+ {
14
+ 'uri' => '/jackrabbit',
15
+ 'lastStarted' => '2015-06-20T20:13:20.333Z',
16
+ }
17
+ ]
18
+ )
19
+ end
20
+
21
+ app.post('/api/build/rename/:name') do
22
+ content_type 'text/plain'
23
+ body "Build renaming of '#{params['name']}' to '#{params['to']}' was successfully started."
24
+ end
25
+
26
+ app.delete('/api/build/:name') do
27
+ content_type 'text/plain'
28
+
29
+ if params['deleteAll']
30
+ body "All '#{params['name']}' builds have been deleted successfully."
31
+ elsif params['buildNumbers'].nil?
32
+ status 400
33
+ body 'Please provide at least one build number to delete.'
34
+ else
35
+ message = params['buildNumbers'].split(',').map do |n|
36
+ "#{params['name']}##{n}"
37
+ end.join(', ')
38
+
39
+ body "The following builds has been deleted successfully: #{message}."
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,18 +1,227 @@
1
1
  module Artifactory
2
2
  module APIServer::BuildEndpoints
3
3
  def self.registered(app)
4
- app.get('/api/build') do
5
- content_type 'application/vnd.org.jfrog.build.Builds+json'
4
+ app.get('/api/build/wicket') do
5
+ content_type 'application/vnd.org.jfrog.build.BuildsByName+json'
6
6
  JSON.fast_generate(
7
- 'uri' => server_url.join('/api/build'),
8
- 'builds' => [
7
+ 'uri' => server_url.join('/api/build/wicket'),
8
+ 'buildsNumbers' => [
9
9
  {
10
- 'uri' => '/wicket',
11
- 'lastStarted' => '2014-01-01 12:00:00',
10
+ 'uri' => "/51",
11
+ 'started' => '2014-09-30T12:00:19.893+0300',
12
+ }
13
+ ]
14
+ )
15
+ end
16
+
17
+ app.get('/api/build/wicket/51') do
18
+ content_type 'application/vnd.org.jfrog.build.BuildInfo+json'
19
+ JSON.fast_generate(
20
+ 'uri' => server_url.join('/api/build/wicket/51'),
21
+ 'buildInfo' => {
22
+ "properties" => {
23
+ "buildInfo.env.JAVA_HOME" => "/usr/jdk/latest",
24
+ },
25
+ "version" => "1.0.1",
26
+ "name" => "wicket",
27
+ "number" => "51",
28
+ "type" => "MAVEN",
29
+ "buildAgent" => {
30
+ "name" => "Maven",
31
+ "version" => "3.0.5"
32
+ },
33
+ "agent" => {
34
+ "name" => "Jenkins",
35
+ "version" => "1.565.2"
12
36
  },
37
+ "started" => '2014-09-30T12:00:19.893+0300',
38
+ "durationMillis" => 8926,
39
+ "artifactoryPrincipal" => "admin",
40
+ "url" => "http://localhost:8080/job/Maven2-3/9/",
41
+ "vcsRevision" => "83049487ecc61bef3dce798838e7a9457e174a5a",
42
+ "vcsUrl" => "https://github.com/aseftel/project-examples",
43
+ "licenseControl" => {
44
+ "runChecks" => false,
45
+ "includePublishedArtifacts" => false,
46
+ "autoDiscover" => true,
47
+ "scopesList" => "",
48
+ "licenseViolationsRecipientsList" => ""
49
+ },
50
+ "buildRetention" => {
51
+ "count" => -1,
52
+ "deleteBuildArtifacts" => true,
53
+ "buildNumbersNotToBeDiscarded" => []
54
+ },
55
+ "modules" => [
56
+ {
57
+ "properties" => {
58
+ "project.build.sourceEncoding" => "UTF-8"
59
+ },
60
+ "id" => "org.jfrog.test:multi:2.19-SNAPSHOT",
61
+ "artifacts" => [
62
+ {
63
+ "type" => "pom",
64
+ "sha1" => "045b66ebbf8504002b626f592d087612aca36582",
65
+ "md5" => "c25542a353dab1089cd186465dc47a68",
66
+ "name" => "multi-2.19-SNAPSHOT.pom"
67
+ }
68
+ ]
69
+ },
70
+ {
71
+ "properties" => {
72
+ "project.build.sourceEncoding" => "UTF-8"
73
+ },
74
+ "id" => "org.jfrog.test:multi1:2.19-SNAPSHOT",
75
+ "artifacts"=> [
76
+ {
77
+ "type" => "jar",
78
+ "sha1" => "f4c5c9cb3091011ec2a895b3dedd7f10d847361c",
79
+ "md5" => "d1fd850a3582efba41092c624e0b46b8",
80
+ "name" => "multi1-2.19-SNAPSHOT.jar"
81
+ },
82
+ {
83
+ "type" => "pom",
84
+ "sha1" => "2ddbf9824676f548d637726d3bcbb494ba823090",
85
+ "md5" => "a64aa7f305f63a85e63a0155ff0fb404",
86
+ "name" => "multi1-2.19-SNAPSHOT.pom"
87
+ },
88
+ {
89
+ "type" => "jar",
90
+ "sha1" => "6fdd143a44cea3a2636660c5c266c95c27e50abc",
91
+ "md5" => "12a1e438f4bef8c4b740fe848a1704a4",
92
+ "id" => "org.slf4j:slf4j-simple:1.4.3",
93
+ "scopes" => [ "compile" ]
94
+ },
95
+ {
96
+ "type" => "jar",
97
+ "sha1" => "496e91f7df8a0417e00cecdba840cdf0e5f2472c",
98
+ "md5" => "76a412a37c9d18659d2dacccdb1c24ff",
99
+ "id" => "org.jenkins-ci.lib:dry-run-lib:0.1",
100
+ "scopes" => [ "compile" ]
101
+ }
102
+ ]
103
+ },
104
+ {
105
+ "properties" => {
106
+ "daversion" => "2.19-SNAPSHOT",
107
+ "project.build.sourceEncoding"=>"UTF-8"
108
+ },
109
+ "id" => "org.jfrog.test:multi2:2.19-SNAPSHOT",
110
+ "artifacts" => [
111
+ {
112
+ "type" => "txt",
113
+ "name" => "multi2-2.19-SNAPSHOT.txt"
114
+ },
115
+ {
116
+ "type" => "java-source-jar",
117
+ "sha1" => "49108b0c7db5fdb4efe3c29a5a9f54e806aecb62",
118
+ "md5" => "0e2c5473cf2a9b694afb4a2e8da34b53",
119
+ "name" => "multi2-2.19-SNAPSHOT-sources.jar"},
120
+ {
121
+ "type" => "jar",
122
+ "sha1" => "476e89d290ae36dabb38ff22f75f264ae019d542",
123
+ "md5" => "fa9b3df58ac040fffcff9310f261be80",
124
+ "name" => "multi2-2.19-SNAPSHOT.jar"
125
+ },
126
+ {
127
+ "type" => "pom",
128
+ "sha1" => "b719b90364e5ae38cda358072f61f821bdae5d5d",
129
+ "md5" => "8d5060005235d75907baca4490cf60bf",
130
+ "name" => "multi2-2.19-SNAPSHOT.pom"
131
+ }
132
+ ],
133
+ "dependencies"=> [
134
+ {
135
+ "type" => "jar",
136
+ "sha1" => "19d4e90b43059058f6e056f794f0ea4030d60b86",
137
+ "md5" => "dcd95bcb84b09897b2b66d4684c040da",
138
+ "id" => "xpp3:xpp3_min:1.1.4c",
139
+ "scopes" => [ "provided" ]
140
+ },
141
+ {
142
+ "type" => "jar",
143
+ "sha1" => "e2d866af5518e81282838301b49a1bd2452619d3",
144
+ "md5" => "e9e4b59c69305ba3698dd61c5dfc4fc8",
145
+ "id" => "org.jvnet.hudson.plugins:perforce:1.3.7",
146
+ "scopes" => [ "compile" ]
147
+ },
148
+ {
149
+ "type" => "jar",
150
+ "sha1" => "6fdd143a44cea3a2636660c5c266c95c27e50abc",
151
+ "md5" => "12a1e438f4bef8c4b740fe848a1704a4",
152
+ "id" => "org.slf4j:slf4j-simple:1.4.3",
153
+ "scopes" => [ "compile" ]
154
+ },
155
+ {
156
+ "type" => "jar",
157
+ "sha1" => "496e91f7df8a0417e00cecdba840cdf0e5f2472c",
158
+ "md5" => "76a412a37c9d18659d2dacccdb1c24ff",
159
+ "id" => "org.jenkins-ci.lib:dry-run-lib:0.1",
160
+ "scopes" => [ "compile" ]
161
+ }
162
+ ]
163
+ },
164
+ {
165
+ "properties" => {
166
+ "project.build.sourceEncoding" => "UTF-8"
167
+ },
168
+ "id" => "org.jfrog.test:multi3:2.19-SNAPSHOT",
169
+ "artifacts" => [
170
+ {
171
+ "type" => "java-source-jar",
172
+ "sha1" => "3cd104785167ac37ef999431f308ffef10810348",
173
+ "md5" => "c683276f8dda97078ae8eb5e26bb3ee5",
174
+ "name" => "multi3-2.19-SNAPSHOT-sources.jar"
175
+ },
176
+ {
177
+ "type" => "war",
178
+ "sha1" => "34aeebeb805b23922d9d05507404533518cf81e4",
179
+ "md5" => "55af06a2175cfb23cc6dc3931475b57c",
180
+ "name" => "multi3-2.19-SNAPSHOT.war"
181
+ },
182
+ {
183
+ "type" => "jar",
184
+ "sha1" => "496e91f7df8a0417e00cecdba840cdf0e5f2472c",
185
+ "md5" => "76a412a37c9d18659d2dacccdb1c24ff",
186
+ "id" => "org.jenkins-ci.lib:dry-run-lib:0.1",
187
+ "scopes" => [ "compile" ]
188
+ },
189
+ {
190
+ "type" => "jar",
191
+ "sha1" => "7e9978fdb754bce5fcd5161133e7734ecb683036",
192
+ "md5" => "7df83e09e41d742cc5fb20d16b80729c",
193
+ "id" => "hsqldb:hsqldb:1.8.0.10",
194
+ "scopes" => [ "runtime" ]
195
+ }
196
+ ]
197
+ }
198
+ ],
199
+ "governance" => {
200
+ "blackDuckProperties" => {
201
+ "runChecks" => false,
202
+ "includePublishedArtifacts" => false,
203
+ "autoCreateMissingComponentRequests" => false,
204
+ "autoDiscardStaleComponentRequests" => false
205
+ }
206
+ }
207
+ }
208
+ )
209
+ end
210
+
211
+ app.put('/api/build') do
212
+ status 204
213
+ body ''
214
+ end
215
+
216
+ app.post('/api/build/promote/wicket/51') do
217
+ content_type 'application/vnd.org.jfrog.artifactory.build.PromotionResult+json'
218
+
219
+ JSON.fast_generate(
220
+ 'uri' => server_url.join('/api/build/wicket'),
221
+ 'buildsNumbers' => [
13
222
  {
14
- 'uri' => '/jackrabbit',
15
- 'lastStarted' => '2014-02-11 10:00:00',
223
+ 'uri' => "/51",
224
+ 'started' => '2014-09-30T12:00:19.893+0300',
16
225
  }
17
226
  ]
18
227
  )
@@ -0,0 +1,118 @@
1
+ require 'spec_helper'
2
+
3
+ module Artifactory
4
+ describe Resource::BuildComponent do
5
+ let(:client) { double(:client) }
6
+
7
+ before(:each) do
8
+ allow(Artifactory).to receive(:client).and_return(client)
9
+ allow(client).to receive(:get).and_return(response) if defined?(response)
10
+ subject.name = 'wicket'
11
+ end
12
+
13
+ describe '.all' do
14
+ let(:response) do
15
+ {
16
+ 'uri' => "#{Artifactory.endpoint}/api/build",
17
+ 'builds' => [
18
+ {
19
+ 'uri' => "/wicket",
20
+ 'lastStarted' => '2015-06-19T20:13:20.222Z',
21
+ },
22
+ {
23
+ 'uri' => "/jackrabbit",
24
+ 'lastStarted' => '2015-06-20T20:13:20.333Z',
25
+ },
26
+ ]
27
+ }
28
+ end
29
+
30
+ before do
31
+ allow(described_class).to receive(:from_hash).with(hash_including('uri' => '/wicket'), client: client).and_return('wicket')
32
+ allow(described_class).to receive(:from_hash).with(hash_including('uri' => '/jackrabbit'), client: client).and_return('jackrabbit')
33
+ end
34
+
35
+ it 'GETS /api/build' do
36
+ expect(client).to receive(:get).with('/api/build').once
37
+ described_class.all
38
+ end
39
+
40
+ context 'when there are components with builds' do
41
+ it 'returns the components' do
42
+ expect(described_class.all).to eq(%w( wicket jackrabbit ))
43
+ end
44
+ end
45
+
46
+ context 'when the system has no components with builds' do
47
+ it 'returns an empty array' do
48
+ allow(client).to receive(:get).and_raise(Error::HTTPError.new('status' => 404))
49
+ expect(described_class.all).to be_empty
50
+ end
51
+ end
52
+ end
53
+
54
+ describe '.find' do
55
+ before do
56
+ allow(described_class).to receive(:all).and_return([
57
+ described_class.new(name: 'wicket'),
58
+ described_class.new(name: 'jackrabbit')
59
+ ])
60
+ end
61
+
62
+ it 'filters the full build component list by name' do
63
+ expect(described_class.find('wicket')).to_not be_nil
64
+ end
65
+
66
+ context 'when the build component does not exist' do
67
+ it 'returns nil' do
68
+ expect(described_class.find('fricket')).to be_nil
69
+ end
70
+ end
71
+ end
72
+
73
+ describe '.from_hash' do
74
+ let(:time) { Time.now.utc.round }
75
+ let(:hash) do
76
+ {
77
+ 'uri' => '/wicket',
78
+ 'lastStarted' => time.iso8601(3),
79
+ }
80
+ end
81
+
82
+ it 'creates a new instance' do
83
+ instance = described_class.from_hash(hash)
84
+ expect(instance.uri).to eq('/wicket')
85
+ expect(instance.name).to eq('wicket')
86
+ expect(instance.last_started).to eq(time)
87
+ end
88
+ end
89
+
90
+ describe '#builds' do
91
+
92
+ it 'returns a build collection' do
93
+ expect(subject.builds).to be_a(Collection::Build)
94
+ end
95
+ end
96
+
97
+ describe '#delete' do
98
+
99
+ it 'sends DELETE to the client' do
100
+ expect(client).to receive(:delete)
101
+ subject.delete
102
+ end
103
+
104
+ it 'adds the correct parameters to the request' do
105
+ expect(client).to receive(:delete).with('/api/build/wicket?buildNumbers=51,52,55&artifacts=1&deleteAll=1', {})
106
+ subject.delete(build_numbers: %w( 51 52 55 ), artifacts: true, delete_all: true)
107
+ end
108
+ end
109
+
110
+ describe '#rename' do
111
+
112
+ it 'sends POST to the client with the correct param' do
113
+ expect(client).to receive(:post).with('/api/build/rename/wicket?to=fricket', {})
114
+ subject.rename('fricket')
115
+ end
116
+ end
117
+ end
118
+ end