pact_broker 2.0.0 → 2.0.1
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 +4 -4
- data/CHANGELOG.md +7 -0
- data/lib/pact_broker/api/decorators/version_decorator.rb +1 -1
- data/lib/pact_broker/api/decorators/webhook_decorator.rb +3 -3
- data/lib/pact_broker/api/decorators/webhooks_decorator.rb +10 -2
- data/lib/pact_broker/api/resources/version.rb +6 -1
- data/lib/pact_broker/app.rb +6 -1
- data/lib/pact_broker/doc/views/webhooks-create.markdown +38 -0
- data/lib/pact_broker/doc/views/webhooks-webhooks.markdown +15 -0
- data/lib/pact_broker/domain/order_versions.rb +15 -1
- data/lib/pact_broker/pacticipants/service.rb +4 -2
- data/lib/pact_broker/pacts/repository.rb +4 -0
- data/lib/pact_broker/tags/repository.rb +4 -0
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/versions/repository.rb +4 -0
- data/lib/pact_broker/versions/service.rb +7 -1
- data/lib/rack/pact_broker/database_transaction.rb +42 -0
- data/lib/rack/pact_broker/invalid_uri_protection.rb +36 -0
- data/pact_broker.gemspec +1 -0
- data/script/publish-new.sh +3 -1
- data/script/recreate-pg-db.sh +1 -0
- data/spec/features/delete_version_spec.rb +23 -0
- data/spec/lib/pact_broker/api/decorators/version_decorator_spec.rb +1 -1
- data/spec/lib/pact_broker/api/decorators/webhook_decorator_spec.rb +3 -3
- data/spec/lib/pact_broker/api/decorators/webhooks_decorator_spec.rb +3 -3
- data/spec/lib/pact_broker/app_spec.rb +35 -1
- data/spec/lib/pact_broker/domain/order_versions_spec.rb +22 -0
- data/spec/lib/pact_broker/pacts/repository_spec.rb +23 -0
- data/spec/lib/pact_broker/tags/repository_spec.rb +22 -1
- data/spec/lib/pact_broker/versions/repository_spec.rb +16 -0
- data/spec/lib/pact_broker/versions/service_spec.rb +35 -0
- data/spec/lib/rack/pact_broker/database_transaction_spec.rb +45 -0
- data/spec/lib/rack/pact_broker/invalid_uri_protection_spec.rb +30 -0
- data/spec/spec_helper.rb +2 -1
- metadata +28 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 880db0a792e03e1d623978995043fd1658e9674e
|
4
|
+
data.tar.gz: 0dca6bd356860e3392292b10bc3c23d18f51cd65
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2eab4b5d78400d982467ccd00f9e1e382a99cc145ee02d6721147a91de925f67f97c4a9cf3d998cef126ab73b1f41a85e308d64f5743aa8eef76b846052adf92
|
7
|
+
data.tar.gz: 9cd39079ca7a9ff6a595aee30933fd74dbc3c899a3fb65daf9522c040fa8a5979ccb3c5f2c295a3f7398c85d7010987812c24b43bd53aafe967690fbfe0dc238
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,13 @@ Do this to generate your change history
|
|
2
2
|
|
3
3
|
$ git log --pretty=format:' * %h - %s (%an, %ad)' vX.Y.Z..HEAD
|
4
4
|
|
5
|
+
#### 2.0.1 (2017-05-17)
|
6
|
+
* 8d105aa - Allow an application version to be deleted via the API. (Beth Skurrie, Fri May 19 10:39:16 2017 +1000)
|
7
|
+
* 025b0f7 - Ensure version numbers that don't conform to the semver2 spec don't cause errors when sorting versions. #103 (Beth Skurrie, Fri May 19 09:58:50 2017 +1000)
|
8
|
+
* ca6d88e - Corrected hal link rels that had missing curies (prepended "pb:") (Beth Skurrie, Thu May 18 10:20:06 2017 +1000)
|
9
|
+
* 1cabd5e - Use Rack::Protection. (Beth Skurrie, Tue May 16 10:13:40 2017 +1000)
|
10
|
+
* 2a3bbd1 - Return 404 instead of 500 when Ruby standard URI lib can't parse the URI. https://github.com/pact-foundation/pact_broker/issues/101 (Beth Skurrie, Tue May 16 09:45:37 2017 +1000)
|
11
|
+
|
5
12
|
#### 2.0.0 (2017-05-16)
|
6
13
|
|
7
14
|
#### 2.0.0.beta.8 (2017-05-15)
|
@@ -24,21 +24,21 @@ module PactBroker
|
|
24
24
|
|
25
25
|
end
|
26
26
|
|
27
|
-
link :'pact-webhooks' do | options |
|
27
|
+
link :'pb:pact-webhooks' do | options |
|
28
28
|
{
|
29
29
|
title: "All webhooks for the pact between #{represented.consumer.name} and #{represented.provider.name}",
|
30
30
|
href: webhooks_for_pact_url(represented.consumer, represented.provider, options[:base_url])
|
31
31
|
}
|
32
32
|
end
|
33
33
|
|
34
|
-
link :'webhooks' do | options |
|
34
|
+
link :'pb:webhooks' do | options |
|
35
35
|
{
|
36
36
|
title: "All webhooks",
|
37
37
|
href: webhooks_url(options[:base_url])
|
38
38
|
}
|
39
39
|
end
|
40
40
|
|
41
|
-
link :execute do | options |
|
41
|
+
link :'pb:execute' do | options |
|
42
42
|
{
|
43
43
|
title: "Test the execution of the webhook by sending a POST request to this URL",
|
44
44
|
href: webhook_execution_url(represented, options[:base_url])
|
@@ -14,7 +14,14 @@ module PactBroker
|
|
14
14
|
}
|
15
15
|
end
|
16
16
|
|
17
|
-
|
17
|
+
link :'pb:create' do | context |
|
18
|
+
{
|
19
|
+
title: "POST to create a webhook",
|
20
|
+
href: context[:resource_url]
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
links :'pb:webhooks' do | context |
|
18
25
|
represented.entries.collect do | webhook |
|
19
26
|
{
|
20
27
|
title: webhook.description,
|
@@ -27,7 +34,8 @@ module PactBroker
|
|
27
34
|
curies do | context |
|
28
35
|
[{
|
29
36
|
name: :pb,
|
30
|
-
href: context[:base_url] + '/doc/webhooks',
|
37
|
+
href: context[:base_url] + '/doc/webhooks-{rel}',
|
38
|
+
templated: true
|
31
39
|
}]
|
32
40
|
end
|
33
41
|
|
@@ -12,7 +12,7 @@ module PactBroker
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def allowed_methods
|
15
|
-
["GET"]
|
15
|
+
["GET", "DELETE"]
|
16
16
|
end
|
17
17
|
|
18
18
|
def resource_exists?
|
@@ -23,6 +23,11 @@ module PactBroker
|
|
23
23
|
Decorators::VersionDecorator.new(version).to_json(user_options: {base_url: base_url})
|
24
24
|
end
|
25
25
|
|
26
|
+
def delete_resource
|
27
|
+
version_service.delete version
|
28
|
+
true
|
29
|
+
end
|
30
|
+
|
26
31
|
private
|
27
32
|
|
28
33
|
def version
|
data/lib/pact_broker/app.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
require 'pact_broker/configuration'
|
2
2
|
require 'pact_broker/db'
|
3
3
|
require 'pact_broker/project_root'
|
4
|
+
require 'rack-protection'
|
4
5
|
require 'rack/hal_browser'
|
5
6
|
require 'rack/pact_broker/add_pact_broker_version_header'
|
6
7
|
require 'rack/pact_broker/convert_file_extension_to_accept_header'
|
8
|
+
require 'rack/pact_broker/database_transaction'
|
9
|
+
require 'rack/pact_broker/invalid_uri_protection'
|
7
10
|
require 'sucker_punch'
|
8
11
|
|
9
12
|
module PactBroker
|
@@ -54,6 +57,8 @@ module PactBroker
|
|
54
57
|
def build_app
|
55
58
|
@app = Rack::Builder.new
|
56
59
|
|
60
|
+
@app.use Rack::Protection, except: [:remote_token, :session_hijacking]
|
61
|
+
@app.use Rack::PactBroker::InvalidUriProtection
|
57
62
|
@app.use Rack::PactBroker::AddPactBrokerVersionHeader
|
58
63
|
@app.use Rack::Static, :urls => ["/stylesheets", "/css", "/fonts", "/js", "/javascripts", "/images"], :root => PactBroker.project_root.join("public")
|
59
64
|
@app.use Rack::PactBroker::ConvertFileExtensionToAcceptHeader
|
@@ -79,7 +84,7 @@ module PactBroker
|
|
79
84
|
end
|
80
85
|
|
81
86
|
apps << PactBroker::UI::App.new
|
82
|
-
apps << PactBroker::API
|
87
|
+
apps << Rack::PactBroker::DatabaseTransaction.new(PactBroker::API, configuration.database_connection)
|
83
88
|
|
84
89
|
@app.map "/" do
|
85
90
|
run Rack::Cascade.new(apps)
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Create a webhook
|
2
|
+
|
3
|
+
Allowed methods: POST
|
4
|
+
|
5
|
+
1. Click the "NON-GET" button for the "pb:create" relation.
|
6
|
+
3. Paste in the webhook JSON (example shown below) in the body section and click "Make Request".
|
7
|
+
|
8
|
+
An example webhook to trigger a Bamboo job.
|
9
|
+
|
10
|
+
{
|
11
|
+
"request": {
|
12
|
+
"method": "POST",
|
13
|
+
"url": "http://master.ci.my.domain:8085/rest/api/latest/queue/SOME-PROJECT?os_authType=basic",
|
14
|
+
"username": "username",
|
15
|
+
"password": "password",
|
16
|
+
"headers": {
|
17
|
+
"Accept": "application/json"
|
18
|
+
}
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
A request body can be specified as well.
|
23
|
+
|
24
|
+
{
|
25
|
+
"request": {
|
26
|
+
"method": "POST",
|
27
|
+
"url": "http://example.org/something",
|
28
|
+
"body": {
|
29
|
+
"some" : "json"
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
**BEWARE** The password can be reverse engineered from the database, so make a separate account for the Pact Broker to use, don't use your personal account!
|
35
|
+
|
36
|
+
### Testing
|
37
|
+
|
38
|
+
To test a webhook, navigate to the webhook in the HAL browser, then make a POST request to the "execute" relation. The response or error will be shown in the window.
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Webhooks
|
2
|
+
|
3
|
+
Allowed methods: GET, DELETE
|
4
|
+
|
5
|
+
### Testing
|
6
|
+
|
7
|
+
To test a webhook, navigate to the webhook in the HAL browser, then make a POST request to the "execute" relation. The response or error will be shown in the window.
|
8
|
+
|
9
|
+
### Deleting
|
10
|
+
|
11
|
+
Send a DELETE request to the webhook URL.
|
12
|
+
|
13
|
+
### Updating
|
14
|
+
|
15
|
+
Currently not implemented. You will need to delete and re-create the webhook.
|
@@ -26,8 +26,22 @@ module PactBroker
|
|
26
26
|
@sortable_number = PactBroker.configuration.version_parser.call version_model.number
|
27
27
|
end
|
28
28
|
|
29
|
+
# Incoming version numbers are rejected if they can't be parsed by the version parser,
|
30
|
+
# however, the change from Versionomy to SemVer for version parsing means that some
|
31
|
+
# existing version numbers cannot be parsed and are returning nil.
|
32
|
+
# The main reason to sort the versions is to that we can get the "latest" pact.
|
33
|
+
# Any existing version with a number that cannot be parsed will almost definitely not
|
34
|
+
# be the "latest", so sort them first.
|
29
35
|
def <=> other
|
30
|
-
|
36
|
+
if sortable_number.nil? && other.sortable_number.nil?
|
37
|
+
0
|
38
|
+
elsif sortable_number.nil?
|
39
|
+
-1
|
40
|
+
elsif other.sortable_number.nil?
|
41
|
+
1
|
42
|
+
else
|
43
|
+
self.sortable_number <=> other.sortable_number
|
44
|
+
end
|
31
45
|
end
|
32
46
|
|
33
47
|
def update_model new_order
|
@@ -75,15 +75,17 @@ module PactBroker
|
|
75
75
|
def self.delete name
|
76
76
|
pacticipant = find_pacticipant_by_name name
|
77
77
|
connection = PactBroker::Domain::Pacticipant.new.db
|
78
|
+
version_ids = PactBroker::Domain::Version.where(pacticipant_id: pacticipant.id).select(:id)
|
78
79
|
select_pacticipant = "select id from pacticipants where name = '#{name}'"
|
79
|
-
|
80
|
-
|
80
|
+
tag_repository.delete_by_version_id version_ids
|
81
|
+
pact_repository.delete_by_version_id version_ids
|
81
82
|
connection.run("delete from pact_publications where provider_id = #{pacticipant.id}")
|
82
83
|
connection.run("delete from verifications where pact_version_id IN (select id from pact_versions where provider_id = #{pacticipant.id})")
|
83
84
|
connection.run("delete from verifications where pact_version_id IN (select id from pact_versions where consumer_id = #{pacticipant.id})")
|
84
85
|
connection.run("delete from pact_versions where provider_id = #{pacticipant.id}")
|
85
86
|
connection.run("delete from pact_versions where consumer_id = #{pacticipant.id}")
|
86
87
|
connection.run("delete from versions where pacticipant_id = #{pacticipant.id}")
|
88
|
+
version_repository.delete_by_id version_ids
|
87
89
|
webhook_service.delete_by_pacticipant pacticipant
|
88
90
|
connection.run("delete from pacticipants where id = #{pacticipant.id}")
|
89
91
|
end
|
@@ -48,6 +48,10 @@ module PactBroker
|
|
48
48
|
PactPublication.where(id: id).delete
|
49
49
|
end
|
50
50
|
|
51
|
+
def delete_by_version_id version_id
|
52
|
+
Sequel::Model.db[:pact_publications].where(consumer_version_id: version_id).delete
|
53
|
+
end
|
54
|
+
|
51
55
|
def find_all_pact_versions_between consumer_name, options
|
52
56
|
provider_name = options.fetch(:and)
|
53
57
|
LatestPactPublicationsByConsumerVersion
|
@@ -22,6 +22,10 @@ module PactBroker
|
|
22
22
|
.where(name_like(Sequel.qualify("pacticipants", "name"), args.fetch(:pacticipant_name)))
|
23
23
|
.single_record
|
24
24
|
end
|
25
|
+
|
26
|
+
def delete_by_version_id version_id
|
27
|
+
Sequel::Model.db[:tags].where(version_id: version_id).delete
|
28
|
+
end
|
25
29
|
end
|
26
30
|
end
|
27
31
|
end
|
data/lib/pact_broker/version.rb
CHANGED
@@ -10,6 +10,12 @@ module PactBroker
|
|
10
10
|
def self.find_by_pacticipant_name_and_number params
|
11
11
|
version_repository.find_by_pacticipant_name_and_number params.fetch(:pacticipant_name), params.fetch(:pacticipant_version_number)
|
12
12
|
end
|
13
|
+
|
14
|
+
def self.delete version
|
15
|
+
tag_repository.delete_by_version_id version.id
|
16
|
+
pact_repository.delete_by_version_id version.id
|
17
|
+
version_repository.delete_by_id version.id
|
18
|
+
end
|
13
19
|
end
|
14
20
|
end
|
15
|
-
end
|
21
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'pact_broker/version'
|
2
|
+
require 'sequel'
|
3
|
+
|
4
|
+
module Rack
|
5
|
+
module PactBroker
|
6
|
+
class DatabaseTransaction
|
7
|
+
|
8
|
+
REQUEST_METHOD = "REQUEST_METHOD".freeze
|
9
|
+
TRANS_METHODS = %{POST PUT PATCH DELETE}.freeze
|
10
|
+
|
11
|
+
def initialize app, database_connection
|
12
|
+
@app = app
|
13
|
+
@database_connection = database_connection
|
14
|
+
end
|
15
|
+
|
16
|
+
def call env
|
17
|
+
if use_transaction? env
|
18
|
+
call_with_transaction env
|
19
|
+
else
|
20
|
+
call_without_transaction env
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def use_transaction? env
|
25
|
+
TRANS_METHODS.include? env[REQUEST_METHOD]
|
26
|
+
end
|
27
|
+
|
28
|
+
def call_without_transaction env
|
29
|
+
@app.call(env)
|
30
|
+
end
|
31
|
+
|
32
|
+
def call_with_transaction env
|
33
|
+
response = nil
|
34
|
+
@database_connection.transaction do
|
35
|
+
response = @app.call(env)
|
36
|
+
raise Sequel::Rollback if response.first == 500
|
37
|
+
end
|
38
|
+
response
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
# This class is for https://github.com/pact-foundation/pact_broker/issues/101
|
4
|
+
# curl -i "http://127.0.0.1:9292/<script>"
|
5
|
+
|
6
|
+
module Rack
|
7
|
+
module PactBroker
|
8
|
+
class InvalidUriProtection
|
9
|
+
|
10
|
+
def initialize app
|
11
|
+
@app = app
|
12
|
+
end
|
13
|
+
|
14
|
+
def call env
|
15
|
+
if valid_uri? env
|
16
|
+
@app.call(env)
|
17
|
+
else
|
18
|
+
[404, {}, []]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def valid_uri? env
|
23
|
+
begin
|
24
|
+
parse(::Rack::Request.new(env).url)
|
25
|
+
true
|
26
|
+
rescue URI::InvalidURIError
|
27
|
+
false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def parse uri
|
32
|
+
URI.parse(uri)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/pact_broker.gemspec
CHANGED
@@ -36,6 +36,7 @@ Gem::Specification.new do |gem|
|
|
36
36
|
gem.add_runtime_dependency 'padrino-core', '~>0.12.4'
|
37
37
|
gem.add_runtime_dependency 'haml', '~>4.0'
|
38
38
|
gem.add_runtime_dependency 'sucker_punch', '~>2.0'
|
39
|
+
gem.add_runtime_dependency 'rack-protection', '~>1.5'
|
39
40
|
|
40
41
|
gem.add_development_dependency 'sqlite3'
|
41
42
|
gem.add_development_dependency 'pry-byebug'
|
data/script/publish-new.sh
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
# set -x
|
2
2
|
BODY=$(ruby -e "require 'json'; j = JSON.parse(File.read('script/foo-bar.json')); j['interactions'][0]['providerState'] = 'it is ' + Time.now.to_s; puts j.to_json")
|
3
|
+
latest_url=$(curl http://localhost:9292/pacts/provider/Bar/consumer/Foo/latest | jq -r ._links.self.href)
|
4
|
+
next_version=$(echo ${latest_url} | ruby -e "require 'semver'; puts SemVer.parse(ARGF.read[/\d+\.\d\.\d+/]).tap{ | v| v.minor = v.minor + 1}.format('%M.%m.%p')")
|
3
5
|
echo ${BODY} >> tmp.json
|
4
6
|
curl -v -XPUT \-H "Content-Type: application/json" \
|
5
7
|
-d@tmp.json \
|
6
|
-
http://127.0.0.1:9292/pacts/provider/Bar/consumer/Foo/version
|
8
|
+
http://127.0.0.1:9292/pacts/provider/Bar/consumer/Foo/version/${next_version}
|
7
9
|
rm tmp.json
|
data/script/recreate-pg-db.sh
CHANGED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec/support/provider_state_builder'
|
2
|
+
|
3
|
+
describe "Delete version" do
|
4
|
+
|
5
|
+
let(:path) { "/pacticipants/Consumer/versions/1.2.3" }
|
6
|
+
let(:last_response_body) { JSON.parse(subject.body, symbolize_names: true) }
|
7
|
+
|
8
|
+
subject { delete path; last_response }
|
9
|
+
|
10
|
+
before do
|
11
|
+
ProviderStateBuilder.new
|
12
|
+
.create_consumer("Another Consumer")
|
13
|
+
.create_consumer("Consumer")
|
14
|
+
.create_consumer_version("1.2.3")
|
15
|
+
.create_consumer_version_tag("prod")
|
16
|
+
.create_consumer_version("1.2.4")
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
it "returns a 200 HAL JSON response" do
|
21
|
+
expect(subject.status).to eq 204
|
22
|
+
end
|
23
|
+
end
|
@@ -35,7 +35,7 @@ module PactBroker
|
|
35
35
|
end
|
36
36
|
|
37
37
|
it "includes a link to the pacticipant" do
|
38
|
-
expect(subject[:_links][:pacticipant]).to eq title: "Pacticipant", name: "Consumer", href: "http://example.org/pacticipants/Consumer"
|
38
|
+
expect(subject[:_links][:'pb:pacticipant']).to eq title: "Pacticipant", name: "Consumer", href: "http://example.org/pacticipants/Consumer"
|
39
39
|
end
|
40
40
|
|
41
41
|
it "includes a list of the tags" do
|
@@ -72,15 +72,15 @@ module PactBroker
|
|
72
72
|
end
|
73
73
|
|
74
74
|
it 'includes a link to its parent collection' do
|
75
|
-
expect(parsed_json[:_links][:'pact-webhooks'][:href]).to_not be_nil
|
75
|
+
expect(parsed_json[:_links][:'pb:pact-webhooks'][:href]).to_not be_nil
|
76
76
|
end
|
77
77
|
|
78
78
|
it 'includes a link to the webhooks resource' do
|
79
|
-
expect(parsed_json[:_links][:webhooks][:href]).to_not be_nil
|
79
|
+
expect(parsed_json[:_links][:'pb:webhooks'][:href]).to_not be_nil
|
80
80
|
end
|
81
81
|
|
82
82
|
it 'includes a link to execute the webhook directly' do
|
83
|
-
expect(parsed_json[:_links][:execute][:href]).to eq 'http://example.org/webhooks/some-uuid/execute'
|
83
|
+
expect(parsed_json[:_links][:'pb:execute'][:href]).to eq 'http://example.org/webhooks/some-uuid/execute'
|
84
84
|
end
|
85
85
|
|
86
86
|
it 'includes timestamps' do
|
@@ -30,12 +30,12 @@ module PactBroker
|
|
30
30
|
end
|
31
31
|
|
32
32
|
it "includes a list of links to the webhooks" do
|
33
|
-
expect(subject[:_links][:webhooks]).to be_instance_of(Array)
|
34
|
-
expect(subject[:_links][:webhooks].first).to eq title: 'description', name: 'request description', href: 'http://example.org/webhooks/some-uuid'
|
33
|
+
expect(subject[:_links][:'pb:webhooks']).to be_instance_of(Array)
|
34
|
+
expect(subject[:_links][:'pb:webhooks'].first).to eq title: 'description', name: 'request description', href: 'http://example.org/webhooks/some-uuid'
|
35
35
|
end
|
36
36
|
|
37
37
|
it "includes curies" do
|
38
|
-
expect(subject[:_links][:curies]).to eq [{:name=>"pb", :href=>"http://example.org/doc/webhooks"}]
|
38
|
+
expect(subject[:_links][:curies]).to eq [{:name=>"pb", :href=>"http://example.org/doc/webhooks-{rel}", templated: true}]
|
39
39
|
end
|
40
40
|
|
41
41
|
end
|
@@ -3,9 +3,22 @@ require 'pact_broker/app'
|
|
3
3
|
module PactBroker
|
4
4
|
describe App do
|
5
5
|
|
6
|
+
class TestApp < PactBroker::App
|
7
|
+
|
8
|
+
def configure_database_connection
|
9
|
+
# do nothing
|
10
|
+
end
|
11
|
+
|
12
|
+
def post_configure
|
13
|
+
# do nothing
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
6
18
|
let(:app) do
|
7
|
-
|
19
|
+
TestApp.new do | configuration |
|
8
20
|
configuration.database_connection = PactBroker::DB.connection
|
21
|
+
configuration.auto_migrate_db = false
|
9
22
|
end
|
10
23
|
end
|
11
24
|
|
@@ -14,5 +27,26 @@ module PactBroker
|
|
14
27
|
expect(last_response.headers['X-Pact-Broker-Version']).to match /\d/
|
15
28
|
end
|
16
29
|
|
30
|
+
describe "transactions", no_db_clean: true do
|
31
|
+
let(:pact_content) { load_fixture('a_consumer-a_provider.json') }
|
32
|
+
let(:path) { "/pacts/provider/A%20Provider/consumer/A%20Consumer/versions/1.2.3" }
|
33
|
+
let(:response_body_json) { JSON.parse(subject.body) }
|
34
|
+
|
35
|
+
before do
|
36
|
+
PactBroker::Database.truncate
|
37
|
+
allow_any_instance_of(PactBroker::Pacts::Repository).to receive(:create).and_raise("an error")
|
38
|
+
end
|
39
|
+
|
40
|
+
after do
|
41
|
+
PactBroker::Database.truncate
|
42
|
+
end
|
43
|
+
|
44
|
+
subject { put path, pact_content, {'CONTENT_TYPE' => 'application/json' }; last_response }
|
45
|
+
|
46
|
+
it "wraps the API with a database transaction" do
|
47
|
+
expect { subject }.to_not change { PactBroker::Domain::Pacticipant.count }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
17
51
|
end
|
18
52
|
end
|
@@ -40,4 +40,26 @@ describe PactBroker::Domain::OrderVersions do
|
|
40
40
|
|
41
41
|
end
|
42
42
|
|
43
|
+
context "when an existing version number in the database that Versionomy could parse cannot be parsed by SemVer" do
|
44
|
+
let!(:consumer) do
|
45
|
+
ProviderStateBuilder.new
|
46
|
+
.create_consumer
|
47
|
+
.create_consumer_version('1')
|
48
|
+
.create_consumer_version('2')
|
49
|
+
.create_consumer_version('3')
|
50
|
+
.create_consumer_version('4')
|
51
|
+
.and_return(:consumer)
|
52
|
+
end
|
53
|
+
|
54
|
+
let(:ordered_versions) { PactBroker::Domain::Version.order(:order).all.collect(&:number) }
|
55
|
+
|
56
|
+
it "sorts the unparseable version as being first and maintains their relative order" do
|
57
|
+
Sequel::Model.db[:versions].where(number: '1').update(number: 'z')
|
58
|
+
Sequel::Model.db[:versions].where(number: '2').update(number: 'a')
|
59
|
+
Sequel::Model.db[:versions].where(number: '4').update(number: 'h')
|
60
|
+
PactBroker::Domain::Version.create(number: '5', pacticipant_id: consumer.id)
|
61
|
+
expect(ordered_versions).to eq(['z', 'a', 'h', '3', '5'])
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
43
65
|
end
|
@@ -191,6 +191,29 @@ module PactBroker
|
|
191
191
|
|
192
192
|
end
|
193
193
|
|
194
|
+
describe "delete_by_version_id" do
|
195
|
+
let!(:version) do
|
196
|
+
ProviderStateBuilder.new
|
197
|
+
.create_consumer
|
198
|
+
.create_provider
|
199
|
+
.create_consumer_version("4.5.6")
|
200
|
+
.create_pact
|
201
|
+
.create_consumer_version("1.2.3")
|
202
|
+
.create_pact
|
203
|
+
.and_return(:consumer_version)
|
204
|
+
end
|
205
|
+
|
206
|
+
subject { Repository.new.delete_by_version_id(version.id) }
|
207
|
+
|
208
|
+
it "deletes the pact publication" do
|
209
|
+
expect{ subject }.to change { PactPublication.count }.by(-1)
|
210
|
+
end
|
211
|
+
|
212
|
+
it "does not delete the content because it may be used by another pact" do
|
213
|
+
expect { subject }.to change { PactVersion.count }.by(0)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
194
217
|
describe "#find_all_pact_versions_between" do
|
195
218
|
|
196
219
|
before do
|
@@ -62,6 +62,27 @@ module PactBroker
|
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
|
+
describe "delete_by_version_id" do
|
66
|
+
let!(:version) do
|
67
|
+
ProviderStateBuilder.new
|
68
|
+
.create_consumer
|
69
|
+
.create_provider
|
70
|
+
.create_consumer_version("4.5.6")
|
71
|
+
.create_consumer_version_tag("prod")
|
72
|
+
.create_consumer_version("1.2.3")
|
73
|
+
.create_consumer_version_tag("prod")
|
74
|
+
.create_consumer_version_tag("foo")
|
75
|
+
.and_return(:consumer_version)
|
76
|
+
end
|
77
|
+
|
78
|
+
subject { Repository.new.delete_by_version_id(version.id) }
|
79
|
+
|
80
|
+
it "deletes the tag" do
|
81
|
+
expect{ subject }.to change { PactBroker::Domain::Tag.count }.by(-2)
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
65
86
|
end
|
66
87
|
end
|
67
|
-
end
|
88
|
+
end
|
@@ -24,6 +24,22 @@ module PactBroker
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
describe "#delete_by_id" do
|
28
|
+
let!(:version) do
|
29
|
+
ProviderStateBuilder.new
|
30
|
+
.create_consumer
|
31
|
+
.create_consumer_version("1.2.3")
|
32
|
+
.create_consumer_version("4.5.6")
|
33
|
+
.and_return(:consumer_version)
|
34
|
+
end
|
35
|
+
|
36
|
+
subject { Repository.new.delete_by_id version.id }
|
37
|
+
|
38
|
+
it "deletes the version" do
|
39
|
+
expect { subject }.to change{ PactBroker::Domain::Version.count }.by(-1)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
27
43
|
describe "#find_by_pacticipant_name_and_number" do
|
28
44
|
|
29
45
|
subject { described_class.new.find_by_pacticipant_name_and_number pacticipant_name, version_number }
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'pact_broker/versions/service'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
|
5
|
+
module Versions
|
6
|
+
describe Service do
|
7
|
+
|
8
|
+
describe ".delete" do
|
9
|
+
let!(:version) do
|
10
|
+
ProviderStateBuilder.new
|
11
|
+
.create_consumer
|
12
|
+
.create_provider
|
13
|
+
.create_consumer_version("1.2.3")
|
14
|
+
.create_consumer_version_tag("prod")
|
15
|
+
.create_pact
|
16
|
+
.and_return(:consumer_version)
|
17
|
+
end
|
18
|
+
|
19
|
+
subject { Service.delete(version) }
|
20
|
+
|
21
|
+
it "deletes the pact publication" do
|
22
|
+
expect{ subject }.to change { PactBroker::Pacts::PactPublication.count }.by(-1)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "deletes the tags" do
|
26
|
+
expect{ subject }.to change { PactBroker::Domain::Tag.count }.by(-1)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "deletes the version" do
|
30
|
+
expect{ subject }.to change { PactBroker::Domain::Version.count }.by(-1)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'tasks/database'
|
2
|
+
require 'rack/pact_broker/database_transaction'
|
3
|
+
|
4
|
+
module Rack
|
5
|
+
module PactBroker
|
6
|
+
describe DatabaseTransaction, no_db_clean: true do
|
7
|
+
|
8
|
+
before do
|
9
|
+
::PactBroker::Database.truncate
|
10
|
+
end
|
11
|
+
|
12
|
+
after do
|
13
|
+
::PactBroker::Database.truncate
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:api) do
|
17
|
+
->(env) { ::PactBroker::Domain::Pacticipant.create(name: 'Foo'); [500, {}, []] }
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:api_with_transaction) do
|
21
|
+
::Rack::PactBroker::DatabaseTransaction.new(api, ::PactBroker::DB.connection)
|
22
|
+
end
|
23
|
+
|
24
|
+
subject { self.send(http_method, "/") }
|
25
|
+
|
26
|
+
context "for get requests" do
|
27
|
+
let(:app) { api_with_transaction }
|
28
|
+
|
29
|
+
let(:http_method) { :get }
|
30
|
+
it "does not use a transaction" do
|
31
|
+
expect { subject }.to change { ::PactBroker::Domain::Pacticipant.count }.by(1)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
[:post, :put, :patch, :delete].each do | http_meth |
|
36
|
+
let(:http_method) { http_meth }
|
37
|
+
context "for #{http_meth} requests" do
|
38
|
+
it "uses a transaction and rollsback if there is a 500 error" do
|
39
|
+
expect { subject }.to change { ::PactBroker::Domain::Pacticipant.count }.by(0)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'rack/pact_broker/invalid_uri_protection'
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
module PactBroker
|
5
|
+
describe InvalidUriProtection do
|
6
|
+
|
7
|
+
let(:app) { InvalidUriProtection.new(->(env){ [200,{},[]] }) }
|
8
|
+
|
9
|
+
subject { get "/badpath"; last_response }
|
10
|
+
|
11
|
+
context "with a URI that the Ruby default URI library cannot parse" do
|
12
|
+
|
13
|
+
before do
|
14
|
+
# Can't use or stub URI.parse because rack test uses it to execute the actual test
|
15
|
+
allow_any_instance_of(InvalidUriProtection).to receive(:parse).and_raise(URI::InvalidURIError)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "returns a 404" do
|
19
|
+
expect(subject.status).to eq 404
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "when the URI can be parsed" do
|
24
|
+
it "passes the request to the underlying app" do
|
25
|
+
expect(subject.status).to eq 200
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -5,6 +5,7 @@ $: << File.expand_path("../../", __FILE__)
|
|
5
5
|
require 'rack/test'
|
6
6
|
require 'db'
|
7
7
|
require 'pact_broker/api'
|
8
|
+
require 'tasks/database'
|
8
9
|
require 'rspec/its'
|
9
10
|
|
10
11
|
Dir.glob("./spec/support/**/*.rb") { |file| require file }
|
@@ -14,7 +15,7 @@ I18n.config.enforce_available_locales = false
|
|
14
15
|
RSpec.configure do | config |
|
15
16
|
config.before :suite do
|
16
17
|
raise "Wrong environment!!! Don't run this script!! ENV['RACK_ENV'] is #{ENV['RACK_ENV']} and RACK_ENV is #{RACK_ENV}" if ENV['RACK_ENV'] != 'test' || RACK_ENV != 'test'
|
17
|
-
PactBroker::DB.connection = DB::PACT_BROKER_DB
|
18
|
+
PactBroker::DB.connection = PactBroker::Database.database = DB::PACT_BROKER_DB
|
18
19
|
end
|
19
20
|
|
20
21
|
config.include Rack::Test::Methods
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pact_broker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bethany Skurrie
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2017-05-
|
13
|
+
date: 2017-05-19 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: httparty
|
@@ -234,6 +234,20 @@ dependencies:
|
|
234
234
|
- - "~>"
|
235
235
|
- !ruby/object:Gem::Version
|
236
236
|
version: '2.0'
|
237
|
+
- !ruby/object:Gem::Dependency
|
238
|
+
name: rack-protection
|
239
|
+
requirement: !ruby/object:Gem::Requirement
|
240
|
+
requirements:
|
241
|
+
- - "~>"
|
242
|
+
- !ruby/object:Gem::Version
|
243
|
+
version: '1.5'
|
244
|
+
type: :runtime
|
245
|
+
prerelease: false
|
246
|
+
version_requirements: !ruby/object:Gem::Requirement
|
247
|
+
requirements:
|
248
|
+
- - "~>"
|
249
|
+
- !ruby/object:Gem::Version
|
250
|
+
version: '1.5'
|
237
251
|
- !ruby/object:Gem::Dependency
|
238
252
|
name: sqlite3
|
239
253
|
requirement: !ruby/object:Gem::Requirement
|
@@ -534,6 +548,8 @@ files:
|
|
534
548
|
- lib/pact_broker/doc/views/self.markdown
|
535
549
|
- lib/pact_broker/doc/views/tag-prod-version.markdown
|
536
550
|
- lib/pact_broker/doc/views/tag-version.markdown
|
551
|
+
- lib/pact_broker/doc/views/webhooks-create.markdown
|
552
|
+
- lib/pact_broker/doc/views/webhooks-webhooks.markdown
|
537
553
|
- lib/pact_broker/doc/views/webhooks.markdown
|
538
554
|
- lib/pact_broker/domain.rb
|
539
555
|
- lib/pact_broker/domain/group.rb
|
@@ -607,6 +623,8 @@ files:
|
|
607
623
|
- lib/rack/hal_browser/redirect.rb
|
608
624
|
- lib/rack/pact_broker/add_pact_broker_version_header.rb
|
609
625
|
- lib/rack/pact_broker/convert_file_extension_to_accept_header.rb
|
626
|
+
- lib/rack/pact_broker/database_transaction.rb
|
627
|
+
- lib/rack/pact_broker/invalid_uri_protection.rb
|
610
628
|
- pact_broker.gemspec
|
611
629
|
- pact_broker_client-pact_broker.json
|
612
630
|
- public/Network Graph_files/d3.v3.js
|
@@ -643,6 +661,7 @@ files:
|
|
643
661
|
- script/update-hal-browser
|
644
662
|
- spec/features/create_webhook_spec.rb
|
645
663
|
- spec/features/delete_pact_spec.rb
|
664
|
+
- spec/features/delete_version_spec.rb
|
646
665
|
- spec/features/get_diff_spec.rb
|
647
666
|
- spec/features/get_pact_spec.rb
|
648
667
|
- spec/features/get_pact_versions_spec.rb
|
@@ -744,11 +763,14 @@ files:
|
|
744
763
|
- spec/lib/pact_broker/verifications/summary_for_consumer_version_spec.rb
|
745
764
|
- spec/lib/pact_broker/versions/parse_semantic_version_spec.rb
|
746
765
|
- spec/lib/pact_broker/versions/repository_spec.rb
|
766
|
+
- spec/lib/pact_broker/versions/service_spec.rb
|
747
767
|
- spec/lib/pact_broker/webhooks/job_spec.rb
|
748
768
|
- spec/lib/pact_broker/webhooks/repository_spec.rb
|
749
769
|
- spec/lib/pact_broker/webhooks/service_spec.rb
|
750
770
|
- spec/lib/rack/hal_browser/redirect_spec.rb
|
751
771
|
- spec/lib/rack/pact_broker/add_pact_broker_version_header_spec.rb
|
772
|
+
- spec/lib/rack/pact_broker/database_transaction_spec.rb
|
773
|
+
- spec/lib/rack/pact_broker/invalid_uri_protection_spec.rb
|
752
774
|
- spec/migrations/23_pact_versions_spec.rb
|
753
775
|
- spec/migrations/24_populate_pact_contents_spec.rb
|
754
776
|
- spec/migrations/34_latest_tagged_pacts_spec.rb
|
@@ -830,6 +852,7 @@ summary: See description
|
|
830
852
|
test_files:
|
831
853
|
- spec/features/create_webhook_spec.rb
|
832
854
|
- spec/features/delete_pact_spec.rb
|
855
|
+
- spec/features/delete_version_spec.rb
|
833
856
|
- spec/features/get_diff_spec.rb
|
834
857
|
- spec/features/get_pact_spec.rb
|
835
858
|
- spec/features/get_pact_versions_spec.rb
|
@@ -931,11 +954,14 @@ test_files:
|
|
931
954
|
- spec/lib/pact_broker/verifications/summary_for_consumer_version_spec.rb
|
932
955
|
- spec/lib/pact_broker/versions/parse_semantic_version_spec.rb
|
933
956
|
- spec/lib/pact_broker/versions/repository_spec.rb
|
957
|
+
- spec/lib/pact_broker/versions/service_spec.rb
|
934
958
|
- spec/lib/pact_broker/webhooks/job_spec.rb
|
935
959
|
- spec/lib/pact_broker/webhooks/repository_spec.rb
|
936
960
|
- spec/lib/pact_broker/webhooks/service_spec.rb
|
937
961
|
- spec/lib/rack/hal_browser/redirect_spec.rb
|
938
962
|
- spec/lib/rack/pact_broker/add_pact_broker_version_header_spec.rb
|
963
|
+
- spec/lib/rack/pact_broker/database_transaction_spec.rb
|
964
|
+
- spec/lib/rack/pact_broker/invalid_uri_protection_spec.rb
|
939
965
|
- spec/migrations/23_pact_versions_spec.rb
|
940
966
|
- spec/migrations/24_populate_pact_contents_spec.rb
|
941
967
|
- spec/migrations/34_latest_tagged_pacts_spec.rb
|