pact_broker 2.93.4 → 2.95.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +40 -0
- data/README.md +7 -8
- data/db/migrations/20220303_increase_consumer_version_selector_hashes_column_size.rb +14 -0
- data/lib/db.rb +1 -0
- data/lib/pact_broker/api/authorization/resource_access_policy.rb +1 -5
- data/lib/pact_broker/api/decorators/format_date_time.rb +1 -1
- data/lib/pact_broker/api/decorators/pacticipant_decorator.rb +8 -0
- data/lib/pact_broker/api/pact_broker_urls.rb +4 -0
- data/lib/pact_broker/api/paths.rb +5 -2
- data/lib/pact_broker/api/resources/badge.rb +2 -25
- data/lib/pact_broker/api/resources/badge_methods.rb +57 -0
- data/lib/pact_broker/api/resources/base_resource.rb +273 -1
- data/lib/pact_broker/api/resources/can_i_deploy_pacticipant_version_by_branch_to_environment.rb +67 -0
- data/lib/pact_broker/api/resources/can_i_deploy_pacticipant_version_by_branch_to_environment_badge.rb +29 -0
- data/lib/pact_broker/api/resources/can_i_deploy_pacticipant_version_by_tag_to_tag.rb +48 -0
- data/lib/pact_broker/api/resources/can_i_deploy_pacticipant_version_by_tag_to_tag_badge.rb +25 -0
- data/lib/pact_broker/api/resources/default_base_resource.rb +0 -280
- data/lib/pact_broker/api.rb +7 -3
- data/lib/pact_broker/configuration.rb +1 -5
- data/lib/pact_broker/date_helper.rb +0 -4
- data/lib/pact_broker/domain/pact.rb +1 -1
- data/lib/pact_broker/domain/version.rb +7 -0
- data/lib/pact_broker/index/service.rb +1 -1
- data/lib/pact_broker/locale/en.yml +3 -0
- data/lib/pact_broker/matrix/quick_row.rb +11 -9
- data/lib/pact_broker/matrix/repository.rb +13 -12
- data/lib/pact_broker/matrix/unresolved_selector.rb +1 -0
- data/lib/pact_broker/pacticipants/find_potential_duplicate_pacticipant_names.rb +1 -4
- data/lib/pact_broker/pacts/pact_publication.rb +12 -6
- data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +29 -5
- data/lib/pact_broker/pacts/repository.rb +1 -0
- data/lib/pact_broker/pacts/verifiable_pact.rb +5 -1
- data/lib/pact_broker/repositories/helpers.rb +4 -0
- data/lib/pact_broker/string_refinements.rb +9 -0
- data/lib/pact_broker/ui/controllers/base_controller.rb +8 -0
- data/lib/pact_broker/ui/controllers/can_i_deploy.rb +1 -1
- data/lib/pact_broker/ui/views/dashboard/show.haml +30 -12
- data/lib/pact_broker/ui/views/matrix/show.haml +8 -8
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/versions/branch.rb +4 -0
- data/lib/pact_broker/versions/branch_service.rb +10 -0
- data/lib/pact_broker/versions/repository.rb +8 -0
- data/lib/pact_broker/versions/service.rb +4 -0
- data/lib/webmachine/describe_routes.rb +24 -2
- data/vendor/hal-browser/js/hal/views/embedded_resource.js +1 -1
- metadata +9 -6
- data/lib/pact_broker/api/resources/can_i_deploy_badge.rb +0 -85
- data/lib/pact_broker/api/resources/can_i_deploy_pacticipant_version.rb +0 -45
- data/public/bootstrap.zip +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f65cf2bd6eb2b3f0f7fd727e61fc73005817200f8e72bbab574493e4ea9b9ba3
|
4
|
+
data.tar.gz: aac1fb501fc5624227e63d424c8982f266fa0a9a2d80b1184844193347ba6724
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8272759e5880069606e56bea3893055df49543b76b237d7511ce8fa21c0414f1a0e593e98ed1f9e67c4b9048b4da1c2d3ef938b0dfea182406cda696111c2bc4
|
7
|
+
data.tar.gz: 426a032f0016c8952934fbf630420be42accf192baeaff3bd2651aefa75170d055d8a4ed125640a7b3cad124cf5a461d7c930e5d289f4a6e5bd666366661940a
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,43 @@
|
|
1
|
+
<a name="v2.95.1"></a>
|
2
|
+
### v2.95.1 (2022-03-18)
|
3
|
+
|
4
|
+
#### Bug Fixes
|
5
|
+
|
6
|
+
* **can-i-deploy**
|
7
|
+
* allow new provider to be introduced to existing consumer without can-i-deploy having circular dependency issues ([e43974ca](/../../commit/e43974ca))
|
8
|
+
|
9
|
+
<a name="v2.95.0"></a>
|
10
|
+
### v2.95.0 (2022-03-16)
|
11
|
+
|
12
|
+
#### Features
|
13
|
+
|
14
|
+
* add relation for can-i-deploy branch to environment badge ([6ece8e93](/../../commit/6ece8e93))
|
15
|
+
* add badge url for 'can I deploy latest version of branch to envionment' endpoint ([086b8c10](/../../commit/086b8c10))
|
16
|
+
|
17
|
+
#### Bug Fixes
|
18
|
+
|
19
|
+
* **pacts for verification**
|
20
|
+
* do not de-duplicate pacts with the same content but different consumers ([ae3bb541](/../../commit/ae3bb541))
|
21
|
+
|
22
|
+
<a name="v2.94.0"></a>
|
23
|
+
### v2.94.0 (2022-02-22)
|
24
|
+
|
25
|
+
#### Features
|
26
|
+
|
27
|
+
* add can-i-deploy endpoint for checking if the latest version for a branch can be deployed to a particular environment ([34b145e8](/../../commit/34b145e8))
|
28
|
+
* truncate tags, branches and versions in UI when they are super long (#513) ([94bbf915](/../../commit/94bbf915))
|
29
|
+
|
30
|
+
* **integration dashboard**
|
31
|
+
* add copy buttons next to the branch, tag and environment labels ([5b86ac88](/../../commit/5b86ac88))
|
32
|
+
|
33
|
+
#### Bug Fixes
|
34
|
+
|
35
|
+
* Improve Matrix request performance (#537) ([123f8629](/../../commit/123f8629))
|
36
|
+
* Eagerly load pact publication fields (#536) ([c3f6993b](/../../commit/c3f6993b))
|
37
|
+
|
38
|
+
* **hal-browser**
|
39
|
+
* properties accordion should be collapsed by default (#544) ([19466121](/../../commit/19466121))
|
40
|
+
|
1
41
|
<a name="v2.93.4"></a>
|
2
42
|
### v2.93.4 (2022-02-21)
|
3
43
|
|
data/README.md
CHANGED
@@ -140,15 +140,14 @@ You can use the [Pact Broker Docker image][docker] or [Terraform on AWS][terrafo
|
|
140
140
|
#### Rolling your own
|
141
141
|
|
142
142
|
* Are you sure you don't just want to use the [Pact Broker Docker image][docker]? No Docker at your company yet? Ah well, keep reading.
|
143
|
-
* Create a PostgreSQL
|
144
|
-
|
145
|
-
*
|
146
|
-
*
|
143
|
+
* Create a PostgreSQL database.
|
144
|
+
* To ensure you're on a supported version of the database that you choose, check the [travis.yml][travisyml] file to see which versions we're currently running our tests against.
|
145
|
+
* MySQL was supported for the native Ruby application until around 2021, but the official `pactfoundation/pact-broker` Docker image does not support it. New features will not be optimised for MySQL, and some new features may not even be supported on it (eg. the database clean feature).
|
146
|
+
* You'll find a sample database creation script in the [example/config.ru](https://github.com/pact-foundation/pact_broker/blob/master/example/config.ru).
|
147
|
+
* Install ruby 2.7 or later and the latest version of bundler (if you've come this far, I'm assuming you know how to do both of these. Did I mention there was a [Docker][docker] image?)
|
147
148
|
* Copy the [pact\_broker](https://github.com/DiUS/pact_broker-docker/tree/master/pact_broker) directory from the Pact Broker Docker project. This will have the recommended settings for database connections, logging, basic auth etc. Note that the Docker image uses Phusion Passenger as the web application server in front of the Pact Broker Ruby application, which is the recommended set up.
|
148
|
-
* Modify the config.ru and Gemfile as desired (eg. choose database driver gem, set your database credentials. Use the "pg" gem
|
149
|
-
|
150
|
-
* example Sequel configuration for mysql `{adapter: "mysql2", database: "pact_broker", username: 'pact_broker', password: 'pact_broker', :encoding => 'utf8'}`
|
151
|
-
`
|
149
|
+
* Modify the config.ru and Gemfile as desired (eg. choose database driver gem, set your database credentials. Use the "pg" gem for Postgres)
|
150
|
+
* example Sequel configuration for postgres `{ adapter: "postgres", database: "pact_broker", username: 'pact_broker', password: 'pact_broker', :encoding => 'utf8' }`
|
152
151
|
* Please ensure you use `encoding: 'utf8'` in your Sequel options to avoid encoding issues.
|
153
152
|
* For production usage, use a web application server like [Phusion Passenger](https://www.phusionpassenger.com) or [Nginx](http://nginx.org/) to serve the Pact Broker application. You'll need to read up on the documentation for these yourself as it is beyond the scope of this documentation. See the [wiki][reverse-proxy-docs] for instructions on using a reverse proxy with SSL.
|
154
153
|
* Ensure the environment variable `RACK_ENV` is set to `production`.
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative "migration_helper"
|
2
|
+
include PactBroker::MigrationHelper
|
3
|
+
|
4
|
+
Sequel.migration do
|
5
|
+
up do
|
6
|
+
if mysql?
|
7
|
+
run("ALTER TABLE verifications CHANGE consumer_version_selector_hashes consumer_version_selector_hashes mediumtext")
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
down do
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
data/lib/db.rb
CHANGED
@@ -38,11 +38,7 @@ module PactBroker
|
|
38
38
|
]
|
39
39
|
|
40
40
|
if enable_public_badge_access
|
41
|
-
rules.concat([
|
42
|
-
[PUBLIC, READ_METHODS, PACT_BADGE_PATH],
|
43
|
-
[PUBLIC, READ_METHODS, MATRIX_BADGE_PATH],
|
44
|
-
[PUBLIC, READ_METHODS, CAN_I_DEPLOY_BADGE_PATH]
|
45
|
-
])
|
41
|
+
rules.concat(BADGE_PATHS.collect { | badge_path | [PUBLIC, READ_METHODS, badge_path] })
|
46
42
|
end
|
47
43
|
|
48
44
|
if allow_public_access_to_heartbeat
|
@@ -8,7 +8,7 @@ module PactBroker
|
|
8
8
|
|
9
9
|
def self.call(date_time)
|
10
10
|
if date_time.is_a?(String)
|
11
|
-
|
11
|
+
Sequel.string_to_datetime(date_time).to_time.utc.to_datetime.xmlschema
|
12
12
|
elsif date_time
|
13
13
|
date_time.to_time.utc.to_datetime.xmlschema if date_time
|
14
14
|
end
|
@@ -90,6 +90,14 @@ module PactBroker
|
|
90
90
|
}
|
91
91
|
end
|
92
92
|
|
93
|
+
link :'pb:can-i-deploy-branch-to-environment-badge' do | options |
|
94
|
+
{
|
95
|
+
title: "Can I Deploy #{represented.name} from branch to environment badge",
|
96
|
+
href: templated_can_i_deploy_branch_to_environment_badge_url(represented.name, options[:base_url]),
|
97
|
+
templated: true
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
93
101
|
curies do | options |
|
94
102
|
[{
|
95
103
|
name: :pb,
|
@@ -255,6 +255,10 @@ module PactBroker
|
|
255
255
|
templated_can_i_deploy_url(pacticipant_name, base_url) + "/badge"
|
256
256
|
end
|
257
257
|
|
258
|
+
def templated_can_i_deploy_branch_to_environment_badge_url pacticipant_name, base_url = ""
|
259
|
+
pacticipant_url_from_params({ pacticipant_name: pacticipant_name }, base_url) + "/branches/{branch}/latest-version/can-i-deploy/to-environment/{environment}/badge"
|
260
|
+
end
|
261
|
+
|
258
262
|
def label_url label, base_url
|
259
263
|
"#{labels_url(label.pacticipant, base_url)}/#{url_encode(label.name)}"
|
260
264
|
end
|
@@ -3,9 +3,12 @@ module PactBroker
|
|
3
3
|
module Paths
|
4
4
|
PACT_BADGE_PATH = %r{^/pacts/provider/[^/]+/consumer/.*/badge(?:\.[A-Za-z]+)?$}.freeze
|
5
5
|
MATRIX_BADGE_PATH = %r{^/matrix/provider/[^/]+/latest/[^/]+/consumer/[^/]+/latest/[^/]+/badge(?:\.[A-Za-z]+)?$}.freeze
|
6
|
-
|
6
|
+
CAN_I_DEPLOY_TAG_BADGE_PATH = %r{^/pacticipants/[^/]+/latest-version/[^/]+/can-i-deploy/to/[^/]+/badge(?:\.[A-Za-z]+)?$}.freeze
|
7
|
+
CAN_I_DEPLOY_BRANCH_ENV_BADGE_PATH = %r{^/pacticipants/[^/]+/branches/[^/]+/latest-version/can-i-deploy/to-environment/[^/]+/badge(?:\.[A-Za-z]+)?$}.freeze
|
7
8
|
VERIFICATION_RESULTS = %r{^/pacts/provider/[^/]+/consumer/[^/]+/pact-version/[^/]+/verification-results/[^/]+}
|
8
9
|
|
10
|
+
BADGE_PATHS = [PACT_BADGE_PATH, MATRIX_BADGE_PATH, CAN_I_DEPLOY_TAG_BADGE_PATH, CAN_I_DEPLOY_BRANCH_ENV_BADGE_PATH]
|
11
|
+
|
9
12
|
extend self
|
10
13
|
|
11
14
|
def is_verification_results_path?(path)
|
@@ -14,7 +17,7 @@ module PactBroker
|
|
14
17
|
|
15
18
|
def is_badge_path?(path)
|
16
19
|
# Optimise by checking include? first - regexp slow
|
17
|
-
path.include?("/badge") &&
|
20
|
+
path.include?("/badge") && BADGE_PATHS.any?{ | regex | path =~ regex }
|
18
21
|
end
|
19
22
|
end
|
20
23
|
end
|
@@ -1,37 +1,22 @@
|
|
1
1
|
require "pact_broker/api/resources/base_resource"
|
2
2
|
require "pact_broker/verifications/pseudo_branch_status"
|
3
3
|
require "pact_broker/configuration"
|
4
|
+
require "pact_broker/api/resources/badge_methods"
|
4
5
|
|
5
6
|
module PactBroker
|
6
7
|
module Api
|
7
8
|
module Resources
|
8
9
|
class Badge < BaseResource
|
9
|
-
|
10
|
-
def allowed_methods
|
11
|
-
["GET", "OPTIONS"]
|
12
|
-
end
|
13
|
-
|
14
|
-
def content_types_provided
|
15
|
-
[["image/svg+xml", :to_svg]]
|
16
|
-
end
|
10
|
+
include BadgeMethods
|
17
11
|
|
18
12
|
def resource_exists?
|
19
13
|
!badge_service.can_provide_badge_using_redirect?
|
20
14
|
end
|
21
15
|
|
22
|
-
# Only called if resource_exists? returns false
|
23
|
-
def previously_existed?
|
24
|
-
true
|
25
|
-
end
|
26
|
-
|
27
16
|
def is_authorized?(authorization_header)
|
28
17
|
super || PactBroker.configuration.enable_public_badge_access
|
29
18
|
end
|
30
19
|
|
31
|
-
def forbidden?
|
32
|
-
false
|
33
|
-
end
|
34
|
-
|
35
20
|
def to_svg
|
36
21
|
response.headers["Cache-Control"] = "no-cache"
|
37
22
|
comment + badge_service.pact_verification_badge(pact, label, initials, pseudo_branch_verification_status, tags)
|
@@ -42,10 +27,6 @@ module PactBroker
|
|
42
27
|
badge_service.pact_verification_badge_url(pact, label, initials, pseudo_branch_verification_status, tags)
|
43
28
|
end
|
44
29
|
|
45
|
-
def policy_name
|
46
|
-
:'badges::badge'
|
47
|
-
end
|
48
|
-
|
49
30
|
private
|
50
31
|
|
51
32
|
def pact
|
@@ -61,10 +42,6 @@ module PactBroker
|
|
61
42
|
@pseudo_branch_verification_status ||= PactBroker::Verifications::PseudoBranchStatus.new(pact, latest_verification).to_sym
|
62
43
|
end
|
63
44
|
|
64
|
-
def label
|
65
|
-
request.query["label"]
|
66
|
-
end
|
67
|
-
|
68
45
|
def initials
|
69
46
|
request.query["initials"] == "true"
|
70
47
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module PactBroker
|
2
|
+
module Api
|
3
|
+
module Resources
|
4
|
+
module BadgeMethods
|
5
|
+
def allowed_methods
|
6
|
+
["GET", "OPTIONS"]
|
7
|
+
end
|
8
|
+
|
9
|
+
def content_types_provided
|
10
|
+
[["image/svg+xml", :to_svg]]
|
11
|
+
end
|
12
|
+
|
13
|
+
def resource_exists?
|
14
|
+
false
|
15
|
+
end
|
16
|
+
|
17
|
+
# Only called if resource_exists? returns false
|
18
|
+
def previously_existed?
|
19
|
+
true
|
20
|
+
end
|
21
|
+
|
22
|
+
def forbidden?
|
23
|
+
false
|
24
|
+
end
|
25
|
+
|
26
|
+
def is_authorized?(authorization_header)
|
27
|
+
super || PactBroker.configuration.enable_public_badge_access
|
28
|
+
end
|
29
|
+
|
30
|
+
def policy_name
|
31
|
+
:'badges::badge'
|
32
|
+
end
|
33
|
+
|
34
|
+
def moved_temporarily?
|
35
|
+
response.headers["Cache-Control"] = "no-cache"
|
36
|
+
begin
|
37
|
+
badge_url
|
38
|
+
rescue StandardError => e
|
39
|
+
# Want to render a badge, even if there's an error
|
40
|
+
badge_service.error_badge_url("error", ErrorResponseBodyGenerator.display_message(e, "reference: #{PactBroker::Errors.generate_error_reference}"))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def badge_url
|
45
|
+
raise NotImplementedError
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def label
|
51
|
+
lab = request.query["label"]
|
52
|
+
lab && !lab.empty? ? lab : nil
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -1,9 +1,281 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require "pact_broker/configuration"
|
3
|
+
require "webmachine"
|
4
|
+
require "pact_broker/services"
|
5
|
+
require "pact_broker/api/decorators"
|
6
|
+
require "pact_broker/logging"
|
7
|
+
require "pact_broker/api/pact_broker_urls"
|
8
|
+
require "pact_broker/json"
|
9
|
+
require "pact_broker/pacts/pact_params"
|
10
|
+
require "pact_broker/api/resources/authentication"
|
11
|
+
require "pact_broker/api/resources/authorization"
|
12
|
+
require "pact_broker/errors"
|
2
13
|
|
3
14
|
module PactBroker
|
4
15
|
module Api
|
5
16
|
module Resources
|
6
|
-
|
17
|
+
class InvalidJsonError < PactBroker::Error ; end
|
18
|
+
|
19
|
+
class BaseResource < Webmachine::Resource
|
20
|
+
include PactBroker::Services
|
21
|
+
include PactBroker::Api::PactBrokerUrls
|
22
|
+
include PactBroker::Api::Resources::Authentication
|
23
|
+
include PactBroker::Api::Resources::Authorization
|
24
|
+
|
25
|
+
include PactBroker::Logging
|
26
|
+
|
27
|
+
attr_accessor :user
|
28
|
+
|
29
|
+
def initialize
|
30
|
+
PactBroker.configuration.before_resource.call(self)
|
31
|
+
application_context.before_resource&.call(self)
|
32
|
+
end
|
33
|
+
|
34
|
+
def options
|
35
|
+
{ "Access-Control-Allow-Methods" => allowed_methods.join(", ")}
|
36
|
+
end
|
37
|
+
|
38
|
+
def known_methods
|
39
|
+
super + ["PATCH"]
|
40
|
+
end
|
41
|
+
|
42
|
+
def finish_request
|
43
|
+
application_context.after_resource&.call(self)
|
44
|
+
PactBroker.configuration.after_resource.call(self)
|
45
|
+
end
|
46
|
+
|
47
|
+
def is_authorized?(authorization_header)
|
48
|
+
authenticated?(self, authorization_header)
|
49
|
+
end
|
50
|
+
|
51
|
+
def forbidden?
|
52
|
+
if application_context.resource_authorizer
|
53
|
+
!application_context.resource_authorizer.call(self)
|
54
|
+
elsif PactBroker.configuration.authorize
|
55
|
+
!PactBroker.configuration.authorize.call(self, {})
|
56
|
+
else
|
57
|
+
false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# The path_info segments aren't URL decoded
|
62
|
+
def identifier_from_path
|
63
|
+
@identifier_from_path ||= request.path_info.each_with_object({}) do | (key, value), hash|
|
64
|
+
if value.is_a?(String)
|
65
|
+
hash[key] = URI.decode(value)
|
66
|
+
elsif value.is_a?(Symbol) || value.is_a?(Numeric)
|
67
|
+
hash[key] = value
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
alias_method :path_info, :identifier_from_path
|
73
|
+
|
74
|
+
def base_url
|
75
|
+
# Have to use something for the base URL here - we can't use an empty string as we can in the UI.
|
76
|
+
# Can't work out if cache poisoning is a vulnerability for APIs or not.
|
77
|
+
# Using the request base URI as a fallback if the base_url is not configured may be a vulnerability,
|
78
|
+
# but the documentation recommends that the
|
79
|
+
# base_url should be set in the configuration to mitigate this.
|
80
|
+
request.env["pactbroker.base_url"] || request.base_uri.to_s.chomp("/")
|
81
|
+
end
|
82
|
+
|
83
|
+
# See comments for base_url in lib/pact_broker/doc/controllers/app.rb
|
84
|
+
def ui_base_url
|
85
|
+
request.env["pactbroker.base_url"] || ""
|
86
|
+
end
|
87
|
+
|
88
|
+
def charsets_provided
|
89
|
+
[["utf-8", :encode]]
|
90
|
+
end
|
91
|
+
|
92
|
+
# We only use utf-8 so leave encoding as it is
|
93
|
+
def encode(body)
|
94
|
+
body
|
95
|
+
end
|
96
|
+
|
97
|
+
def resource_url
|
98
|
+
request.uri.to_s.gsub(/\?.*/, "").chomp("/")
|
99
|
+
end
|
100
|
+
|
101
|
+
def decorator_context options = {}
|
102
|
+
application_context.decorator_context_creator.call(self, options)
|
103
|
+
end
|
104
|
+
|
105
|
+
def decorator_options options = {}
|
106
|
+
{ user_options: decorator_context(options) }
|
107
|
+
end
|
108
|
+
|
109
|
+
def handle_exception(error)
|
110
|
+
error_reference = PactBroker::Errors.generate_error_reference
|
111
|
+
application_context.error_logger.call(error, error_reference, request.env)
|
112
|
+
if PactBroker::Errors.reportable_error?(error)
|
113
|
+
PactBroker::Errors.report(error, error_reference, request.env)
|
114
|
+
end
|
115
|
+
response.body = application_context.error_response_body_generator.call(error, error_reference, request.env)
|
116
|
+
end
|
117
|
+
|
118
|
+
# rubocop: disable Metrics/CyclomaticComplexity
|
119
|
+
def params(options = {})
|
120
|
+
return options[:default] if options.key?(:default) && request_body.empty?
|
121
|
+
|
122
|
+
symbolize_names = !options.key?(:symbolize_names) || options[:symbolize_names]
|
123
|
+
if symbolize_names
|
124
|
+
@params_with_symbol_keys ||= JSON.parse(request_body, { symbolize_names: true }.merge(PACT_PARSING_OPTIONS)) #Not load! Otherwise it will try to load Ruby classes.
|
125
|
+
else
|
126
|
+
@params_with_string_keys ||= JSON.parse(request_body, { symbolize_names: false }.merge(PACT_PARSING_OPTIONS)) #Not load! Otherwise it will try to load Ruby classes.
|
127
|
+
end
|
128
|
+
rescue JSON::JSONError => e
|
129
|
+
raise InvalidJsonError.new("Error parsing JSON - #{e.message}")
|
130
|
+
end
|
131
|
+
# rubocop: enable Metrics/CyclomaticComplexity
|
132
|
+
|
133
|
+
def params_with_string_keys
|
134
|
+
params(symbolize_names: false)
|
135
|
+
end
|
136
|
+
|
137
|
+
def pact_params
|
138
|
+
@pact_params ||= PactBroker::Pacts::PactParams.from_request request, identifier_from_path
|
139
|
+
end
|
140
|
+
|
141
|
+
def set_json_error_message message
|
142
|
+
response.headers["Content-Type"] = "application/hal+json;charset=utf-8"
|
143
|
+
response.body = { error: message }.to_json
|
144
|
+
end
|
145
|
+
|
146
|
+
def set_json_validation_error_messages errors
|
147
|
+
response.headers["Content-Type"] = "application/hal+json;charset=utf-8"
|
148
|
+
response.body = { errors: errors }.to_json
|
149
|
+
end
|
150
|
+
|
151
|
+
def request_body
|
152
|
+
@request_body ||= request.body.to_s
|
153
|
+
end
|
154
|
+
|
155
|
+
def consumer_name
|
156
|
+
identifier_from_path[:consumer_name]
|
157
|
+
end
|
158
|
+
|
159
|
+
def consumer_version_number
|
160
|
+
identifier_from_path[:consumer_version_number]
|
161
|
+
end
|
162
|
+
|
163
|
+
def pacticipant_version_number
|
164
|
+
identifier_from_path[:pacticipant_version_number]
|
165
|
+
end
|
166
|
+
|
167
|
+
def consumer_specified?
|
168
|
+
identifier_from_path.key?(:consumer_name)
|
169
|
+
end
|
170
|
+
|
171
|
+
def provider_specified?
|
172
|
+
identifier_from_path.key?(:provider_name)
|
173
|
+
end
|
174
|
+
|
175
|
+
def provider_name
|
176
|
+
identifier_from_path[:provider_name]
|
177
|
+
end
|
178
|
+
|
179
|
+
def pacticipant_name
|
180
|
+
identifier_from_path[:pacticipant_name]
|
181
|
+
end
|
182
|
+
|
183
|
+
def pacticipant_specified?
|
184
|
+
identifier_from_path.key?(:pacticipant_name)
|
185
|
+
end
|
186
|
+
|
187
|
+
def invalid_json?
|
188
|
+
begin
|
189
|
+
params
|
190
|
+
false
|
191
|
+
rescue StandardError => e
|
192
|
+
logger.info "Error parsing JSON #{e} - #{request_body}"
|
193
|
+
set_json_error_message "Error parsing JSON - #{e.message}"
|
194
|
+
response.headers["Content-Type"] = "application/hal+json;charset=utf-8"
|
195
|
+
true
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def validation_errors? model
|
200
|
+
if (errors = model.validate).any?
|
201
|
+
set_json_validation_error_messages errors
|
202
|
+
true
|
203
|
+
else
|
204
|
+
false
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def contract_validation_errors? contract, params
|
209
|
+
if (invalid = !contract.validate(params))
|
210
|
+
set_json_validation_error_messages contract.errors.messages
|
211
|
+
end
|
212
|
+
invalid
|
213
|
+
end
|
214
|
+
|
215
|
+
def find_pacticipant name, role
|
216
|
+
pacticipant_service.find_pacticipant_by_name(name).tap do | pacticipant |
|
217
|
+
set_json_error_message("No #{role} with name '#{name}' found") if pacticipant.nil?
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def consumer
|
222
|
+
@consumer ||= identifier_from_path[:consumer_name] && find_pacticipant(identifier_from_path[:consumer_name], "consumer")
|
223
|
+
end
|
224
|
+
|
225
|
+
def provider
|
226
|
+
@provider ||= identifier_from_path[:provider_name] && find_pacticipant(identifier_from_path[:provider_name], "provider")
|
227
|
+
end
|
228
|
+
|
229
|
+
def pacticipant
|
230
|
+
@pacticipant ||= identifier_from_path[:pacticipant_name] && find_pacticipant(identifier_from_path[:pacticipant_name], "pacticipant")
|
231
|
+
end
|
232
|
+
|
233
|
+
def pact
|
234
|
+
@pact ||= pact_service.find_pact(pact_params)
|
235
|
+
end
|
236
|
+
|
237
|
+
# Not necessarily an existing integration
|
238
|
+
def integration
|
239
|
+
if consumer_specified? && provider_specified?
|
240
|
+
OpenStruct.new(consumer: consumer, provider: provider)
|
241
|
+
else
|
242
|
+
nil
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
def database_connector
|
247
|
+
request.env["pactbroker.database_connector"]
|
248
|
+
end
|
249
|
+
|
250
|
+
def application_context
|
251
|
+
request.path_info[:application_context]
|
252
|
+
end
|
253
|
+
|
254
|
+
def decorator_class(name)
|
255
|
+
application_context.decorator_configuration.class_for(name)
|
256
|
+
end
|
257
|
+
|
258
|
+
def api_contract_class(name)
|
259
|
+
application_context.api_contract_configuration.class_for(name)
|
260
|
+
end
|
261
|
+
|
262
|
+
def schema
|
263
|
+
nil
|
264
|
+
end
|
265
|
+
|
266
|
+
def validation_errors_for_schema?(schema_to_use = schema, params_to_validate = params)
|
267
|
+
if (errors = schema_to_use.call(params_to_validate)).any?
|
268
|
+
set_json_validation_error_messages(errors)
|
269
|
+
true
|
270
|
+
else
|
271
|
+
false
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
def malformed_request_for_json_with_schema?(schema_to_use = schema, params_to_validate = params)
|
276
|
+
invalid_json? || validation_errors_for_schema?(schema_to_use, params_to_validate)
|
277
|
+
end
|
278
|
+
end
|
7
279
|
end
|
8
280
|
end
|
9
281
|
end
|
data/lib/pact_broker/api/resources/can_i_deploy_pacticipant_version_by_branch_to_environment.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require "pact_broker/api/resources/matrix"
|
2
|
+
require "pact_broker/matrix/can_i_deploy_query_schema"
|
3
|
+
require "pact_broker/matrix/parse_can_i_deploy_query"
|
4
|
+
require "pact_broker/api/decorators/matrix_decorator"
|
5
|
+
require "pact_broker/api/decorators/matrix_text_decorator"
|
6
|
+
|
7
|
+
module PactBroker
|
8
|
+
module Api
|
9
|
+
module Resources
|
10
|
+
class CanIDeployPacticipantVersionByBranchToEnvironment < BaseResource
|
11
|
+
def allowed_methods
|
12
|
+
["GET", "OPTIONS"]
|
13
|
+
end
|
14
|
+
|
15
|
+
def content_types_provided
|
16
|
+
[
|
17
|
+
["application/hal+json", :to_json],
|
18
|
+
["text/plain", :to_text]
|
19
|
+
]
|
20
|
+
end
|
21
|
+
|
22
|
+
def resource_exists?
|
23
|
+
!!(version && environment)
|
24
|
+
end
|
25
|
+
|
26
|
+
def policy_name
|
27
|
+
:'versions::version'
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def selectors
|
33
|
+
@selectors ||= [
|
34
|
+
PactBroker::Matrix::UnresolvedSelector.new(
|
35
|
+
pacticipant_name: pacticipant_name,
|
36
|
+
latest: true,
|
37
|
+
branch: identifier_from_path[:branch_name]
|
38
|
+
)
|
39
|
+
]
|
40
|
+
end
|
41
|
+
|
42
|
+
def options
|
43
|
+
@options ||= {
|
44
|
+
latestby: "cvp",
|
45
|
+
environment_name: identifier_from_path[:environment_name]
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_json
|
50
|
+
decorator_class(:matrix_decorator).new(results).to_json(decorator_options)
|
51
|
+
end
|
52
|
+
|
53
|
+
def results
|
54
|
+
@results ||= matrix_service.can_i_deploy(selectors, options)
|
55
|
+
end
|
56
|
+
|
57
|
+
def version
|
58
|
+
@version ||= version_service.find_latest_by_pacticipant_name_and_branch_name(identifier_from_path[:pacticipant_name], identifier_from_path[:branch_name])
|
59
|
+
end
|
60
|
+
|
61
|
+
def environment
|
62
|
+
@environment ||= environment_service.find_by_name(identifier_from_path[:environment_name])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|