pact_broker 2.101.0 → 2.102.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +28 -0
- data/README.md +14 -4
- data/db/migrations/20220622_default_allow_dangerous_contract_modification_to_false_for_new_installations.rb +22 -0
- data/db/migrations/20220625_delete_pacticipants_with_no_name.rb +62 -0
- data/db/migrations/migration_helper.rb +6 -0
- data/docs/CONFIGURATION.md +3 -1
- data/lib/pact_broker/api/contracts/pacticipant_create_schema.rb +28 -0
- data/lib/pact_broker/api/decorators/embedded_version_decorator.rb +0 -1
- data/lib/pact_broker/api/middleware/basic_auth.rb +2 -0
- data/lib/pact_broker/api/resources/base_resource.rb +8 -1
- data/lib/pact_broker/api/resources/matrix_for_consumer_and_provider.rb +10 -0
- data/lib/pact_broker/api/resources/pact.rb +4 -0
- data/lib/pact_broker/api/resources/pacticipant.rb +1 -1
- data/lib/pact_broker/api/resources/pacticipants.rb +6 -2
- data/lib/pact_broker/config/runtime_configuration.rb +1 -1
- data/lib/pact_broker/domain/verification.rb +3 -2
- data/lib/pact_broker/domain/version.rb +8 -0
- data/lib/pact_broker/index/service.rb +3 -1
- data/lib/pact_broker/matrix/service.rb +14 -6
- data/lib/pact_broker/pacticipants/find_potential_duplicate_pacticipant_names.rb +3 -3
- data/lib/pact_broker/pacts/pact_version.rb +1 -0
- data/lib/pact_broker/string_refinements.rb +28 -0
- data/lib/pact_broker/test/http_test_data_builder.rb +1 -0
- data/lib/pact_broker/ui/app.rb +1 -0
- data/lib/pact_broker/ui/controllers/index.rb +3 -1
- data/lib/pact_broker/ui/helpers/haml_helpers.rb +10 -0
- data/lib/pact_broker/ui/views/dashboard/show.haml +3 -4
- data/lib/pact_broker/ui/views/index/show-with-tags.haml +4 -5
- data/lib/pact_broker/ui/views/index/show.haml +4 -5
- data/lib/pact_broker/verifications/pact_version_provider_tag_successful_verification.rb +15 -0
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/webhooks/pact_and_verification_parameters.rb +1 -1
- data/pact_broker.gemspec +7 -0
- metadata +21 -4
- data/lib/db.rb +0 -79
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1747ecbaa97d17fef8acf4946bd24c59ea255d3179776c09c701ccea77f4d006
|
4
|
+
data.tar.gz: e748481ebd6df16c369e8ba7660ba371f82a4445b2b89df8a9cf1aa8b23ac657
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a10ebe04db5984d671e58f99f8857363d3a2bf806d7429d9b39fa6d8a2a202af423166c429acacb3f8fedc9773b078964b02d67a2d9687e71e0303466b04d106
|
7
|
+
data.tar.gz: a50a13c96cd171b4f1583f7c17d7d5c95a557fab21aa210c1235e6505bd6eb5eceae8b0cf5d9c3fa02284d3b845093e30c8a2ec18628868dde5256b663cca34a
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,31 @@
|
|
1
|
+
<a name="v2.102.2"></a>
|
2
|
+
### v2.102.2 (2022-07-14)
|
3
|
+
|
4
|
+
#### Bug Fixes
|
5
|
+
|
6
|
+
* add blank? refinement for TrueClass and FalseClass ([05bb3bed](/../../commit/05bb3bed))
|
7
|
+
|
8
|
+
<a name="v2.102.1"></a>
|
9
|
+
### v2.102.1 (2022-07-08)
|
10
|
+
|
11
|
+
#### Bug Fixes
|
12
|
+
|
13
|
+
* ensure blank? method is defined where used ([b81b5e9b](/../../commit/b81b5e9b))
|
14
|
+
|
15
|
+
<a name="v2.102.0"></a>
|
16
|
+
### v2.102.0 (2022-07-07)
|
17
|
+
|
18
|
+
#### Features
|
19
|
+
|
20
|
+
* default allow_dangerous_contract_modification to false for new installations ([85a89951](/../../commit/85a89951))
|
21
|
+
|
22
|
+
#### Bug Fixes
|
23
|
+
|
24
|
+
* add missing provider version branch parameter to webhook requests ([262dae44](/../../commit/262dae44))
|
25
|
+
* clean up pacticipants with no names ([0aff250d](/../../commit/0aff250d))
|
26
|
+
* update string refinements with blank? and present? ([8373f88f](/../../commit/8373f88f))
|
27
|
+
* update validation for creating pacticipants to return a 400 when name is missing ([fcb02aa6](/../../commit/fcb02aa6))
|
28
|
+
|
1
29
|
<a name="v2.101.0"></a>
|
2
30
|
### v2.101.0 (2022-06-07)
|
3
31
|
|
data/README.md
CHANGED
@@ -114,7 +114,17 @@ Use the HAL browser to view documentation as you browse.
|
|
114
114
|
|
115
115
|
### To have a play around on your local machine
|
116
116
|
|
117
|
-
|
117
|
+
#### Using Docker Compose
|
118
|
+
|
119
|
+
Download a copy of the [example Docker Compose file](https://github.com/pact-foundation/pact-broker-docker/blob/master/docker-compose.yml) from the Pact Broker Docker repository and run:
|
120
|
+
|
121
|
+
`docker compose up`
|
122
|
+
|
123
|
+
Then open a browser at [http://localhost:9292](http://localhost:9292).
|
124
|
+
|
125
|
+
#### Using Ruby
|
126
|
+
|
127
|
+
* Install Ruby 2.7 and Bundler (check the automated tests to find the most recent version of Ruby and Bundler that are supported)
|
118
128
|
* Windows users: get a Rails/Ruby installer from [RailsInstaller](http://railsinstaller.org/) and run it
|
119
129
|
* unix users just use your package manager
|
120
130
|
* Run `git clone git@github.com:pact-foundation/pact_broker.git && cd pact_broker/example`
|
@@ -144,8 +154,8 @@ You can use the [Pact Broker Docker image][docker] or [Terraform on AWS][terrafo
|
|
144
154
|
* 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
155
|
* 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
156
|
* 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
|
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.
|
157
|
+
* Install ruby 2.7 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?)
|
158
|
+
* 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 if you are not using a containerized solution.
|
149
159
|
* Modify the config.ru and Gemfile as desired (eg. choose database driver gem, set your database credentials. Use the "pg" gem for Postgres)
|
150
160
|
* example Sequel configuration for postgres `{ adapter: "postgres", database: "pact_broker", username: 'pact_broker', password: 'pact_broker', :encoding => 'utf8' }`
|
151
161
|
* Please ensure you use `encoding: 'utf8'` in your Sequel options to avoid encoding issues.
|
@@ -169,7 +179,7 @@ The Pact Broker follows the [semantic versioning](https://semver.org/) scheme.
|
|
169
179
|
[terraform]: https://github.com/nadnerb/terraform-pact-broker
|
170
180
|
[pactflow]: https://pactflow.io/?utm_source=github&utm_campaign=pact_broker_usage
|
171
181
|
[wiki]: https://github.com/pact-foundation/pact_broker/wiki
|
172
|
-
[reverse-proxy-docs]: https://
|
182
|
+
[reverse-proxy-docs]: https://docs.pact.io/pact_broker/configuration/features#running-the-broker-behind-a-reverse-proxy
|
173
183
|
[stackoverflow]: http://stackoverflow.com/questions/tagged/pact-broker
|
174
184
|
[twitter]: https://twitter.com/pact_up
|
175
185
|
[slack]: https://slack.pact.io/
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative "migration_helper"
|
2
|
+
include PactBroker::MigrationHelper
|
3
|
+
|
4
|
+
Sequel.migration do
|
5
|
+
up do
|
6
|
+
# Need to do this again because didn't actually set default of allow_dangerous_contract_modification to true
|
7
|
+
# when the first migration was run in db/migrations/20210810_set_allow_contract_modification.rb
|
8
|
+
for_upgrades_of_existing_installations do
|
9
|
+
from(:config).insert_ignore.insert(
|
10
|
+
name: "allow_dangerous_contract_modification",
|
11
|
+
type: "boolean",
|
12
|
+
value: "1",
|
13
|
+
created_at: Sequel.datetime_class.now,
|
14
|
+
updated_at: Sequel.datetime_class.now
|
15
|
+
)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
down do
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# There was a bug that caused a duplicate pacticipant to be created
|
2
|
+
# with a null name when updating the pacticipant in a certain way.
|
3
|
+
# It was fixed in be24a8ad650f0ed49993283b22ba1d1a744fb3e8.
|
4
|
+
# This migration deletes any pacticipants with null names that are not referenced by any other rows,
|
5
|
+
# or assigns a name if the pacticipant is referenced so that it can be deleted through the API
|
6
|
+
# (I can't think of a reason why a pacticipant with a null name should be referenced, but better to be safe than sorry).
|
7
|
+
# The "find tables that reference pacticipants" logic is done dynamically because Pactflow has extra tables not in the OSS.
|
8
|
+
|
9
|
+
# Query each table that references the pacticipants table to determine
|
10
|
+
# if there are any rows in it that reference the pacticipant with the specified ID.
|
11
|
+
# @return [Boolean]
|
12
|
+
def pacticipant_is_unreferenced(pacticipant_id, table_foreign_keys)
|
13
|
+
table_foreign_keys.any? do | (table_name, foreign_keys) |
|
14
|
+
criteria = foreign_keys.flat_map do | fk |
|
15
|
+
fk[:columns].collect do | column_name |
|
16
|
+
{ column_name => pacticipant_id }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# SELECT 'one' FROM xxx where consumer_id = x or provider_id = x LIMIT 1
|
21
|
+
!from(table_name).where(Sequel.|(*criteria)).empty?
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Return a structure describing the tables and columns that reference the pacticipants table.
|
26
|
+
# @return [Array] eg. [ [:integrations, [ { columns: [:consumer_id] }, { columns: [:provider_id] } ] ] ]
|
27
|
+
def get_table_foreign_keys
|
28
|
+
table_foreign_keys = tables.sort.collect do | table_name |
|
29
|
+
key_list = foreign_key_list(table_name).select{ |fk| fk[:table] == :pacticipants }
|
30
|
+
if key_list.any?
|
31
|
+
[ table_name, key_list]
|
32
|
+
end
|
33
|
+
end.compact
|
34
|
+
|
35
|
+
# move the integrations table check first because that's the most likely candidate to have a referencing row
|
36
|
+
table_foreign_keys.select{ |(table_name, _)| table_name == :integrations } | table_foreign_keys
|
37
|
+
end
|
38
|
+
|
39
|
+
# Deletes the pacticipant if it is unreferenced, or populates the name so it can
|
40
|
+
# be deleted through the API.
|
41
|
+
def delete_pacticipant_or_populate_name(row, table_foreign_keys)
|
42
|
+
if pacticipant_is_unreferenced(row[:id], table_foreign_keys)
|
43
|
+
from(:pacticipants).where(id: row[:id]).delete
|
44
|
+
else
|
45
|
+
from(:pacticipants).where(id: row[:id]).update(name: "Delete me #{row[:id]}")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
Sequel.migration do
|
50
|
+
up do
|
51
|
+
|
52
|
+
table_foreign_keys = get_table_foreign_keys
|
53
|
+
|
54
|
+
from(:pacticipants).where(name: nil).all.each do | row |
|
55
|
+
delete_pacticipant_or_populate_name(row, table_foreign_keys)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
down do
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
data/docs/CONFIGURATION.md
CHANGED
@@ -648,10 +648,12 @@ Whether or not to allow the pact content for an existing consumer version to be
|
|
648
648
|
as allowing modification makes the results of can-i-deploy unreliable. When this is set to false as recommended, each commit must publish pacts
|
649
649
|
with a unique version number.
|
650
650
|
|
651
|
+
If modification of an existing contract is attempted when the value is set to `false`, an HTTP 409 status will be returned.
|
652
|
+
|
651
653
|
**Supported versions:** From v2.82.0<br/>
|
652
654
|
**Environment variable name:** `PACT_BROKER_ALLOW_DANGEROUS_CONTRACT_MODIFICATION`<br/>
|
653
655
|
**YAML configuration key name:** `allow_dangerous_contract_modification`<br/>
|
654
|
-
**Default:** For new installations of v2.
|
656
|
+
**Default:** For new installations of v2.102 and later, this defaults to `false` (the recommended value). Previous installations will have the default value of `true` (not recommended).<br/>
|
655
657
|
**Allowed values:** `true`, `false`<br/>
|
656
658
|
**More information:** https://docs.pact.io/versioning<br/>
|
657
659
|
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require "pact_broker/api/contracts/pacticipant_schema"
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Api
|
5
|
+
module Contracts
|
6
|
+
class PacticipantCreateSchema
|
7
|
+
extend DryValidationWorkarounds
|
8
|
+
extend PactBroker::Messages
|
9
|
+
using PactBroker::HashRefinements
|
10
|
+
|
11
|
+
SCHEMA = Dry::Validation.Schema do
|
12
|
+
configure do
|
13
|
+
predicates(DryValidationPredicates)
|
14
|
+
config.messages_file = File.expand_path("../../../locale/en.yml", __FILE__)
|
15
|
+
end
|
16
|
+
required(:name).filled(:str?, :single_line?)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.call(params_with_string_keys)
|
20
|
+
params = params_with_string_keys&.symbolize_keys
|
21
|
+
update_errors = PacticipantSchema::SCHEMA.call(params).messages(full: true)
|
22
|
+
create_errors = SCHEMA.call(params).messages(full: true)
|
23
|
+
select_first_message(flatten_indexed_messages(update_errors.merge(create_errors)))
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -1,11 +1,13 @@
|
|
1
1
|
require "rack"
|
2
2
|
require "pact_broker/hash_refinements"
|
3
|
+
require "pact_broker/string_refinements"
|
3
4
|
|
4
5
|
module PactBroker
|
5
6
|
module Api
|
6
7
|
module Middleware
|
7
8
|
class BasicAuth
|
8
9
|
using PactBroker::HashRefinements
|
10
|
+
using PactBroker::StringRefinements
|
9
11
|
|
10
12
|
def initialize(app, write_credentials, read_credentials, policy)
|
11
13
|
@app = app
|
@@ -306,20 +306,27 @@ module PactBroker
|
|
306
306
|
invalid_json? || validation_errors_for_schema?(schema_to_use, params_to_validate)
|
307
307
|
end
|
308
308
|
|
309
|
+
# Ensure we have valid JSON if a JSON body is required OR if a body has been provided
|
309
310
|
def content_type_is_json_but_invalid_json_provided?
|
310
|
-
content_type_json? && any_request_body? && invalid_json?
|
311
|
+
content_type_json? && ((request_body_required? || any_request_body?) && invalid_json?)
|
311
312
|
end
|
312
313
|
|
313
314
|
def content_type_json?
|
314
315
|
request.content_type&.include?("json")
|
315
316
|
end
|
316
317
|
|
318
|
+
def request_body_required?
|
319
|
+
false
|
320
|
+
end
|
321
|
+
|
322
|
+
# TODO rename to put_to_create_supported, otherwise it sounds like it's a policy issue
|
317
323
|
# Not a Webmachine method. This is used by security policy code to identify whether
|
318
324
|
# a PUT to a non existing resource can create a new object.
|
319
325
|
def put_can_create?
|
320
326
|
false
|
321
327
|
end
|
322
328
|
|
329
|
+
# TODO rename to patch_to_create_supported, otherwise it sounds like it's a policy issue
|
323
330
|
# Not a Webmachine method. This is used by security policy code to identify whether
|
324
331
|
# a PATCH to a non existing resource can create a new object.
|
325
332
|
def patch_can_create?
|
@@ -23,6 +23,16 @@ module PactBroker
|
|
23
23
|
consumer && provider
|
24
24
|
end
|
25
25
|
|
26
|
+
def malformed_request?
|
27
|
+
error_messages = matrix_service.validate_options(options)
|
28
|
+
if error_messages.any?
|
29
|
+
set_json_validation_error_messages error_messages
|
30
|
+
true
|
31
|
+
else
|
32
|
+
false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
26
36
|
def to_json
|
27
37
|
decorator_class(:matrix_decorator).new(results).to_json(decorator_options)
|
28
38
|
end
|
@@ -34,7 +34,7 @@ module PactBroker
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def malformed_request?
|
37
|
-
super || ((request.patch? || request.really_put?) && validation_errors_for_schema?)
|
37
|
+
super || ((request.patch? || request.really_put?) && any_request_body? && validation_errors_for_schema?)
|
38
38
|
end
|
39
39
|
|
40
40
|
# PUT or PATCH with content-type application/json
|
@@ -2,7 +2,7 @@ require "pact_broker/api/resources/base_resource"
|
|
2
2
|
require "pact_broker/api/decorators/pacticipant_decorator"
|
3
3
|
require "pact_broker/domain/pacticipant"
|
4
4
|
require "pact_broker/hash_refinements"
|
5
|
-
require "pact_broker/api/contracts/
|
5
|
+
require "pact_broker/api/contracts/pacticipant_create_schema"
|
6
6
|
|
7
7
|
module PactBroker
|
8
8
|
module Api
|
@@ -26,6 +26,10 @@ module PactBroker
|
|
26
26
|
super || (request.post? && validation_errors_for_schema?)
|
27
27
|
end
|
28
28
|
|
29
|
+
def request_body_required?
|
30
|
+
request.post?
|
31
|
+
end
|
32
|
+
|
29
33
|
def post_is_create?
|
30
34
|
true
|
31
35
|
end
|
@@ -62,7 +66,7 @@ module PactBroker
|
|
62
66
|
private
|
63
67
|
|
64
68
|
def schema
|
65
|
-
PactBroker::Api::Contracts::
|
69
|
+
PactBroker::Api::Contracts::PacticipantCreateSchema
|
66
70
|
end
|
67
71
|
|
68
72
|
def pacticipants
|
@@ -85,7 +85,7 @@ module PactBroker
|
|
85
85
|
use_first_tag_as_branch_time_limit: 10,
|
86
86
|
auto_detect_main_branch: true,
|
87
87
|
main_branch_candidates: ["develop", "main", "master"],
|
88
|
-
allow_dangerous_contract_modification:
|
88
|
+
allow_dangerous_contract_modification: false,
|
89
89
|
semver_formats: ["%M.%m.%p%s%d", "%M.%m", "%M"],
|
90
90
|
seed_example_data: true,
|
91
91
|
features: []
|
@@ -274,5 +274,6 @@ end
|
|
274
274
|
# verifications_pact_version_id_fkey | (pact_version_id) REFERENCES pact_versions(id)
|
275
275
|
# verifications_provider_id_fkey | (provider_id) REFERENCES pacticipants(id)
|
276
276
|
# Referenced By:
|
277
|
-
# latest_verification_id_for_pact_version_and_provider_version | latest_v_id_for_pv_and_pv_verification_id_fk
|
278
|
-
#
|
277
|
+
# latest_verification_id_for_pact_version_and_provider_version | latest_v_id_for_pv_and_pv_verification_id_fk | (verification_id) REFERENCES verifications(id) ON DELETE CASCADE
|
278
|
+
# pact_version_provider_tag_successful_verifications | pact_version_provider_tag_successful_verifications_v_id_fk | (verification_id) REFERENCES verifications(id) ON DELETE SET NULL
|
279
|
+
# triggered_webhooks | triggered_webhooks_verification_id_fkey | (verification_id) REFERENCES verifications(id)
|
@@ -4,6 +4,7 @@ require "pact_broker/domain/index_item"
|
|
4
4
|
require "pact_broker/repositories/helpers"
|
5
5
|
require "pact_broker/index/page"
|
6
6
|
require "pact_broker/verifications/latest_verification_for_consumer_version_tag"
|
7
|
+
require "pact_broker/string_refinements"
|
7
8
|
|
8
9
|
module PactBroker
|
9
10
|
module Index
|
@@ -11,6 +12,7 @@ module PactBroker
|
|
11
12
|
extend PactBroker::Repositories
|
12
13
|
extend PactBroker::Services
|
13
14
|
extend PactBroker::Logging
|
15
|
+
using PactBroker::StringRefinements
|
14
16
|
|
15
17
|
DEFAULT_PAGE_SIZE = 30
|
16
18
|
DEFAULT_PAGE_NUMBER = 1
|
@@ -182,7 +184,7 @@ module PactBroker
|
|
182
184
|
))
|
183
185
|
|
184
186
|
# Return early if there is no pacticipant matches the input name
|
185
|
-
return base.paginate(options[:page_number] || DEFAULT_PAGE_NUMBER, options[:page_size] || DEFAULT_PAGE_SIZE) if pacticipant_ids.
|
187
|
+
return base.paginate(options[:page_number] || DEFAULT_PAGE_NUMBER, options[:page_size] || DEFAULT_PAGE_SIZE) if pacticipant_ids.empty?
|
186
188
|
end
|
187
189
|
|
188
190
|
ids_query = if options[:view]
|
@@ -52,7 +52,7 @@ module PactBroker
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
-
# rubocop: disable Metrics/CyclomaticComplexity
|
55
|
+
# rubocop: disable Metrics/CyclomaticComplexity
|
56
56
|
def validate_selectors selectors, options = {}
|
57
57
|
error_messages = []
|
58
58
|
|
@@ -73,6 +73,18 @@ module PactBroker
|
|
73
73
|
end
|
74
74
|
end
|
75
75
|
|
76
|
+
if selectors.size == 0
|
77
|
+
error_messages << "Please provide 1 or more version selectors."
|
78
|
+
end
|
79
|
+
|
80
|
+
error_messages + validate_options(options)
|
81
|
+
end
|
82
|
+
# rubocop: enable Metrics/CyclomaticComplexity
|
83
|
+
|
84
|
+
# rubocop: disable Metrics/CyclomaticComplexity
|
85
|
+
def validate_options(options = {})
|
86
|
+
error_messages = []
|
87
|
+
|
76
88
|
options.fetch(:ignore_selectors, []).each do | s |
|
77
89
|
if s[:pacticipant_name].nil?
|
78
90
|
error_messages << "Please specify the pacticipant name to ignore"
|
@@ -83,10 +95,6 @@ module PactBroker
|
|
83
95
|
end
|
84
96
|
end
|
85
97
|
|
86
|
-
if selectors.size == 0
|
87
|
-
error_messages << "Please provide 1 or more version selectors."
|
88
|
-
end
|
89
|
-
|
90
98
|
destination_identifiers = [options[:tag], options[:environment_name], options[:main_branch]&.to_s].compact
|
91
99
|
|
92
100
|
if destination_identifiers.size > 1
|
@@ -107,7 +115,7 @@ module PactBroker
|
|
107
115
|
|
108
116
|
error_messages
|
109
117
|
end
|
110
|
-
# rubocop: enable Metrics/CyclomaticComplexity
|
118
|
+
# rubocop: enable Metrics/CyclomaticComplexity
|
111
119
|
end
|
112
120
|
end
|
113
121
|
end
|
@@ -5,12 +5,12 @@ module PactBroker
|
|
5
5
|
class FindPotentialDuplicatePacticipantNames
|
6
6
|
attr_reader :new_name, :existing_names
|
7
7
|
|
8
|
-
def initialize
|
8
|
+
def initialize(new_name, existing_names)
|
9
9
|
@new_name = new_name
|
10
10
|
@existing_names = existing_names
|
11
11
|
end
|
12
12
|
|
13
|
-
def self.call
|
13
|
+
def self.call(new_name, existing_names)
|
14
14
|
new(new_name, existing_names).call
|
15
15
|
end
|
16
16
|
|
@@ -22,7 +22,7 @@ module PactBroker
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
def clean
|
25
|
+
def clean(name)
|
26
26
|
self.class.split(name).collect{|w| w.chomp("s") } - ["api", "provider", "service"]
|
27
27
|
end
|
28
28
|
|
@@ -179,4 +179,5 @@ end
|
|
179
179
|
# latest_pact_publication_ids_for_consumer_versions | latest_pact_publication_ids_for_consumer_v_pact_version_id_fkey | (pact_version_id) REFERENCES pact_versions(id) ON DELETE CASCADE
|
180
180
|
# latest_verification_id_for_pact_version_and_provider_version | latest_v_id_for_pv_and_pv_pact_version_id_fk | (pact_version_id) REFERENCES pact_versions(id) ON DELETE CASCADE
|
181
181
|
# pact_publications | pact_publications_pact_version_id_fkey | (pact_version_id) REFERENCES pact_versions(id)
|
182
|
+
# pact_version_provider_tag_successful_verifications | pact_version_provider_tag_successful_verifications_pv_id_fk | (pact_version_id) REFERENCES pact_versions(id) ON DELETE CASCADE
|
182
183
|
# verifications | verifications_pact_version_id_fkey | (pact_version_id) REFERENCES pact_versions(id)
|
@@ -1,9 +1,33 @@
|
|
1
1
|
module PactBroker
|
2
2
|
module StringRefinements
|
3
|
+
refine TrueClass do
|
4
|
+
def blank?
|
5
|
+
false
|
6
|
+
end
|
7
|
+
|
8
|
+
def present?
|
9
|
+
true
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
refine FalseClass do
|
14
|
+
def blank?
|
15
|
+
false
|
16
|
+
end
|
17
|
+
|
18
|
+
def present?
|
19
|
+
true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
3
23
|
refine NilClass do
|
4
24
|
def blank?
|
5
25
|
true
|
6
26
|
end
|
27
|
+
|
28
|
+
def present?
|
29
|
+
false
|
30
|
+
end
|
7
31
|
end
|
8
32
|
|
9
33
|
refine Numeric do
|
@@ -13,6 +37,10 @@ module PactBroker
|
|
13
37
|
end
|
14
38
|
|
15
39
|
refine String do
|
40
|
+
def present?
|
41
|
+
!blank?
|
42
|
+
end
|
43
|
+
|
16
44
|
def not_blank?
|
17
45
|
!blank?
|
18
46
|
end
|
@@ -286,6 +286,7 @@ module PactBroker
|
|
286
286
|
"githubVerificationStatus" => "${pactbroker.githubVerificationStatus}",
|
287
287
|
"providerVersionNumber" => "${pactbroker.providerVersionNumber}",
|
288
288
|
"providerVersionTags" => "${pactbroker.providerVersionTags}",
|
289
|
+
"providerVersionBranch" => "${pactbroker.providerVersionBranch}",
|
289
290
|
"canIMerge" => "${pactbroker.providerMainBranchGithubVerificationStatus}"
|
290
291
|
}
|
291
292
|
}
|
data/lib/pact_broker/ui/app.rb
CHANGED
@@ -5,6 +5,7 @@ require "pact_broker/ui/controllers/matrix"
|
|
5
5
|
require "pact_broker/ui/controllers/can_i_deploy"
|
6
6
|
require "pact_broker/ui/controllers/error_test"
|
7
7
|
require "pact_broker/ui/controllers/dashboard"
|
8
|
+
require "pact_broker/ui/helpers/haml_helpers"
|
8
9
|
require "pact_broker/doc/controllers/app"
|
9
10
|
|
10
11
|
module PactBroker
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require "pact_broker/ui/controllers/base_controller"
|
2
2
|
require "pact_broker/ui/view_models/index_items"
|
3
|
+
require "pact_broker/string_refinements"
|
3
4
|
require "haml"
|
4
5
|
|
5
6
|
module PactBroker
|
@@ -7,6 +8,7 @@ module PactBroker
|
|
7
8
|
module Controllers
|
8
9
|
class Index < Base
|
9
10
|
include PactBroker::Services
|
11
|
+
using PactBroker::StringRefinements
|
10
12
|
|
11
13
|
get "/" do
|
12
14
|
set_headers
|
@@ -27,7 +29,7 @@ module PactBroker
|
|
27
29
|
|
28
30
|
index_items = index_service.find_index_items(options)
|
29
31
|
|
30
|
-
if index_items.
|
32
|
+
if index_items.empty? && !search.blank?
|
31
33
|
error_messages << "No pacticipants found matching: \"#{search}\""
|
32
34
|
end
|
33
35
|
|
@@ -2,15 +2,14 @@
|
|
2
2
|
!= render :haml, :'index/_css_and_js', :layout => false
|
3
3
|
.container
|
4
4
|
!= render :haml, :'index/_navbar', :layout => false, locals: {tag_toggle: false, base_url: base_url}
|
5
|
-
- if index_items.empty? &&
|
5
|
+
- if index_items.empty? && blank?(search)
|
6
6
|
!= render :haml, :'index/_getting-started', :layout => false
|
7
7
|
%h1.page-header
|
8
8
|
Pacts
|
9
9
|
|
10
|
-
-
|
11
|
-
-
|
12
|
-
|
13
|
-
= error
|
10
|
+
- errors.each do | error |
|
11
|
+
%div.alert.alert-danger
|
12
|
+
= error
|
14
13
|
|
15
14
|
%form{action: "#{base_url}"}
|
16
15
|
.field
|
@@ -2,15 +2,14 @@
|
|
2
2
|
!= render :haml, :'index/_css_and_js', :layout => false
|
3
3
|
.container
|
4
4
|
!= render :haml, :'index/_navbar', :layout => false, locals: {tag_toggle: true, base_url: base_url}
|
5
|
-
- if index_items.empty? &&
|
5
|
+
- if index_items.empty? && blank?(search)
|
6
6
|
!= render :haml, :'index/_getting-started', :layout => false
|
7
7
|
%h1.page-header
|
8
8
|
Pacts
|
9
9
|
|
10
|
-
-
|
11
|
-
-
|
12
|
-
|
13
|
-
= error
|
10
|
+
- errors.each do | error |
|
11
|
+
%div.alert.alert-danger
|
12
|
+
= error
|
14
13
|
|
15
14
|
%form{action: "#{base_url}"}
|
16
15
|
.search-field
|
@@ -9,3 +9,18 @@ module PactBroker
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
12
|
+
|
13
|
+
# Table: pact_version_provider_tag_successful_verifications
|
14
|
+
# Columns:
|
15
|
+
# id | integer | PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY
|
16
|
+
# pact_version_id | integer | NOT NULL
|
17
|
+
# provider_version_tag_name | text | NOT NULL
|
18
|
+
# wip | boolean | NOT NULL
|
19
|
+
# verification_id | integer |
|
20
|
+
# execution_date | timestamp without time zone | NOT NULL
|
21
|
+
# Indexes:
|
22
|
+
# pact_version_provider_tag_successful_verifications_pkey | PRIMARY KEY btree (id)
|
23
|
+
# pact_version_provider_tag_verifications_pv_pvtn_wip_unique | UNIQUE btree (pact_version_id, provider_version_tag_name, wip)
|
24
|
+
# Foreign key constraints:
|
25
|
+
# pact_version_provider_tag_successful_verifications_pv_id_fk | (pact_version_id) REFERENCES pact_versions(id) ON DELETE CASCADE
|
26
|
+
# pact_version_provider_tag_successful_verifications_v_id_fk | (verification_id) REFERENCES verifications(id) ON DELETE SET NULL
|
data/lib/pact_broker/version.rb
CHANGED
@@ -173,7 +173,7 @@ module PactBroker
|
|
173
173
|
if webhook_context.key?(:provider_version_branch)
|
174
174
|
webhook_context[:provider_version_branch] || ""
|
175
175
|
else
|
176
|
-
verification&.provider_version&.
|
176
|
+
verification&.provider_version&.branch_names&.last || ""
|
177
177
|
end
|
178
178
|
end
|
179
179
|
|
data/pact_broker.gemspec
CHANGED
@@ -55,6 +55,13 @@ Gem::Specification.new do |gem|
|
|
55
55
|
gem.add_runtime_dependency "roar", "~> 1.1"
|
56
56
|
gem.add_runtime_dependency "reform", "~> 2.3.3"
|
57
57
|
gem.add_runtime_dependency "dry-validation", "~> 0.10.5"
|
58
|
+
# if dry-container is not locked, get this error:
|
59
|
+
# An error occurred while loading spec_helper.
|
60
|
+
# Failure/Error: require "reform/form/dry"
|
61
|
+
# NoMethodError:
|
62
|
+
# undefined method `call' for nil:NilClass
|
63
|
+
# # /Users/beth.skurrie/.gem/ruby/2.7.5/gems/dry-container-0.10.0/lib/dry/container/mixin.rb:151:in `register'
|
64
|
+
gem.add_runtime_dependency "dry-container", "0.8.0"
|
58
65
|
# /usr/local/bundle/gems/dry-validation-0.10.7/lib/dry/validation/schema/class_interface.rb:7:in `<module:Validation>' [dry-configurable] default value as positional argument to settings is deprecated and will be removed in the next major version
|
59
66
|
# Provide a `default:` keyword argument instead
|
60
67
|
gem.add_runtime_dependency "dry-configurable", "0.12.1"
|
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.
|
4
|
+
version: 2.102.2
|
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: 2022-
|
13
|
+
date: 2022-07-14 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: httparty
|
@@ -82,6 +82,20 @@ dependencies:
|
|
82
82
|
- - "~>"
|
83
83
|
- !ruby/object:Gem::Version
|
84
84
|
version: 0.10.5
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: dry-container
|
87
|
+
requirement: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - '='
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: 0.8.0
|
92
|
+
type: :runtime
|
93
|
+
prerelease: false
|
94
|
+
version_requirements: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - '='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: 0.8.0
|
85
99
|
- !ruby/object:Gem::Dependency
|
86
100
|
name: dry-configurable
|
87
101
|
requirement: !ruby/object:Gem::Requirement
|
@@ -584,11 +598,12 @@ files:
|
|
584
598
|
- db/migrations/20211120_create_pact_version_provider_tag_successful_verifications.rb
|
585
599
|
- db/migrations/20211121_migrate_pact_version_provider_tag_successful_verifications_data.rb
|
586
600
|
- db/migrations/20220303_increase_consumer_version_selector_hashes_column_size.rb
|
601
|
+
- db/migrations/20220622_default_allow_dangerous_contract_modification_to_false_for_new_installations.rb
|
602
|
+
- db/migrations/20220625_delete_pacticipants_with_no_name.rb
|
587
603
|
- db/migrations/migration_helper.rb
|
588
604
|
- docs/CONFIGURATION.md
|
589
605
|
- docs/api/PACTICIPANTS.md
|
590
606
|
- docs/api/WEBHOOKS.md
|
591
|
-
- lib/db.rb
|
592
607
|
- lib/pact/doc/README.md
|
593
608
|
- lib/pact/doc/doc_file.rb
|
594
609
|
- lib/pact/doc/generate.rb
|
@@ -609,6 +624,7 @@ files:
|
|
609
624
|
- lib/pact_broker/api/contracts/dry_validation_predicates.rb
|
610
625
|
- lib/pact_broker/api/contracts/dry_validation_workarounds.rb
|
611
626
|
- lib/pact_broker/api/contracts/environment_schema.rb
|
627
|
+
- lib/pact_broker/api/contracts/pacticipant_create_schema.rb
|
612
628
|
- lib/pact_broker/api/contracts/pacticipant_name_contract.rb
|
613
629
|
- lib/pact_broker/api/contracts/pacticipant_name_validation.rb
|
614
630
|
- lib/pact_broker/api/contracts/pacticipant_schema.rb
|
@@ -1000,6 +1016,7 @@ files:
|
|
1000
1016
|
- lib/pact_broker/ui/controllers/index.rb
|
1001
1017
|
- lib/pact_broker/ui/controllers/matrix.rb
|
1002
1018
|
- lib/pact_broker/ui/controllers/pacts.rb
|
1019
|
+
- lib/pact_broker/ui/helpers/haml_helpers.rb
|
1003
1020
|
- lib/pact_broker/ui/helpers/matrix_helper.rb
|
1004
1021
|
- lib/pact_broker/ui/helpers/url_helper.rb
|
1005
1022
|
- lib/pact_broker/ui/view_models/clusters.rb
|
@@ -1223,7 +1240,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
1223
1240
|
- !ruby/object:Gem::Version
|
1224
1241
|
version: '0'
|
1225
1242
|
requirements: []
|
1226
|
-
rubygems_version: 3.3.
|
1243
|
+
rubygems_version: 3.3.18
|
1227
1244
|
signing_key:
|
1228
1245
|
specification_version: 4
|
1229
1246
|
summary: See description
|
data/lib/db.rb
DELETED
@@ -1,79 +0,0 @@
|
|
1
|
-
require "sequel"
|
2
|
-
require "sequel/connection_pool/threaded"
|
3
|
-
require "yaml"
|
4
|
-
require "pact_broker/logging"
|
5
|
-
require "erb"
|
6
|
-
require "pact_broker/project_root"
|
7
|
-
require "fileutils"
|
8
|
-
|
9
|
-
module DB
|
10
|
-
include PactBroker::Logging
|
11
|
-
##
|
12
|
-
# Sequel by default does not test connections in its connection pool before
|
13
|
-
# handing them to a client. To enable connection testing you need to load the
|
14
|
-
# "connection_validator" extension like below. The connection validator
|
15
|
-
# extension is configurable, by default it only checks connections once per
|
16
|
-
# hour:
|
17
|
-
#
|
18
|
-
# http://sequel.rubyforge.org/rdoc-plugins/files/lib/sequel/extensions/connection_validator_rb.html
|
19
|
-
#
|
20
|
-
# Because most of our applications so far are accessed infrequently, there is
|
21
|
-
# very little overhead in checking each connection when it is requested. This
|
22
|
-
# takes care of stale connections.
|
23
|
-
#
|
24
|
-
# A gotcha here is that it is not enough to enable the "connection_validator"
|
25
|
-
# extension, we also need to specify that we want to use the threaded connection
|
26
|
-
# pool, as noted in the documentation for the extension.
|
27
|
-
#
|
28
|
-
def self.connect db_credentials
|
29
|
-
# Keep this conifiguration in sync with lib/pact_broker/app.rb#configure_database_connection
|
30
|
-
Sequel.datetime_class = DateTime
|
31
|
-
if ENV["DEBUG"] == "true" && ENV["PACT_BROKER_SQL_LOG_LEVEL"] && ENV["PACT_BROKER_SQL_LOG_LEVEL"] != "none"
|
32
|
-
logger = Logger.new($stdout)
|
33
|
-
end
|
34
|
-
if db_credentials.fetch("adapter") == "sqlite"
|
35
|
-
FileUtils.mkdir_p(File.dirname(db_credentials.fetch("database")))
|
36
|
-
end
|
37
|
-
con = Sequel.connect(db_credentials.merge(:logger => logger, :pool_class => Sequel::ThreadedConnectionPool, :encoding => "utf8"))
|
38
|
-
con.extension(:connection_validator)
|
39
|
-
con.extension(:pagination)
|
40
|
-
con.extension(:statement_timeout)
|
41
|
-
con.extension(:any_not_empty)
|
42
|
-
#con.extension(:caller_logging)
|
43
|
-
con.timezone = :utc
|
44
|
-
con.run("SET sql_mode='STRICT_TRANS_TABLES';") if db_credentials[:adapter].to_s =~ /mysql/
|
45
|
-
con
|
46
|
-
end
|
47
|
-
|
48
|
-
def self.connection_for_env env
|
49
|
-
config = configuration_for_env(env)
|
50
|
-
logger.info "Connecting to #{env} #{config['adapter']} database #{config['database']}."
|
51
|
-
connect config
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.configuration_for_env env
|
55
|
-
database_yml = PactBroker.project_root.join("config","database.yml")
|
56
|
-
config = YAML.load(ERB.new(File.read(database_yml)).result)
|
57
|
-
config.fetch(env).fetch(ENV.fetch("DATABASE_ADAPTER","default"))
|
58
|
-
end
|
59
|
-
|
60
|
-
def self.sqlite?
|
61
|
-
!!(PACT_BROKER_DB.adapter_scheme.to_s =~ /sqlite/)
|
62
|
-
end
|
63
|
-
|
64
|
-
def self.mysql?
|
65
|
-
!!(PACT_BROKER_DB.adapter_scheme.to_s =~ /mysql/)
|
66
|
-
end
|
67
|
-
|
68
|
-
def self.postgres?
|
69
|
-
!!(PACT_BROKER_DB.adapter_scheme.to_s =~ /postgres/)
|
70
|
-
end
|
71
|
-
|
72
|
-
PACT_BROKER_DB ||= connection_for_env ENV.fetch("RACK_ENV")
|
73
|
-
|
74
|
-
def self.health_check
|
75
|
-
PACT_BROKER_DB.synchronize do |c|
|
76
|
-
PACT_BROKER_DB.valid_connection? c
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|