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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +28 -0
  3. data/README.md +14 -4
  4. data/db/migrations/20220622_default_allow_dangerous_contract_modification_to_false_for_new_installations.rb +22 -0
  5. data/db/migrations/20220625_delete_pacticipants_with_no_name.rb +62 -0
  6. data/db/migrations/migration_helper.rb +6 -0
  7. data/docs/CONFIGURATION.md +3 -1
  8. data/lib/pact_broker/api/contracts/pacticipant_create_schema.rb +28 -0
  9. data/lib/pact_broker/api/decorators/embedded_version_decorator.rb +0 -1
  10. data/lib/pact_broker/api/middleware/basic_auth.rb +2 -0
  11. data/lib/pact_broker/api/resources/base_resource.rb +8 -1
  12. data/lib/pact_broker/api/resources/matrix_for_consumer_and_provider.rb +10 -0
  13. data/lib/pact_broker/api/resources/pact.rb +4 -0
  14. data/lib/pact_broker/api/resources/pacticipant.rb +1 -1
  15. data/lib/pact_broker/api/resources/pacticipants.rb +6 -2
  16. data/lib/pact_broker/config/runtime_configuration.rb +1 -1
  17. data/lib/pact_broker/domain/verification.rb +3 -2
  18. data/lib/pact_broker/domain/version.rb +8 -0
  19. data/lib/pact_broker/index/service.rb +3 -1
  20. data/lib/pact_broker/matrix/service.rb +14 -6
  21. data/lib/pact_broker/pacticipants/find_potential_duplicate_pacticipant_names.rb +3 -3
  22. data/lib/pact_broker/pacts/pact_version.rb +1 -0
  23. data/lib/pact_broker/string_refinements.rb +28 -0
  24. data/lib/pact_broker/test/http_test_data_builder.rb +1 -0
  25. data/lib/pact_broker/ui/app.rb +1 -0
  26. data/lib/pact_broker/ui/controllers/index.rb +3 -1
  27. data/lib/pact_broker/ui/helpers/haml_helpers.rb +10 -0
  28. data/lib/pact_broker/ui/views/dashboard/show.haml +3 -4
  29. data/lib/pact_broker/ui/views/index/show-with-tags.haml +4 -5
  30. data/lib/pact_broker/ui/views/index/show.haml +4 -5
  31. data/lib/pact_broker/verifications/pact_version_provider_tag_successful_verification.rb +15 -0
  32. data/lib/pact_broker/version.rb +1 -1
  33. data/lib/pact_broker/webhooks/pact_and_verification_parameters.rb +1 -1
  34. data/pact_broker.gemspec +7 -0
  35. metadata +21 -4
  36. data/lib/db.rb +0 -79
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '08222ce855214163448e53d62e9beea5b6b04c5fc6f9e56308ac27984c21599a'
4
- data.tar.gz: 2e5f39087b8ff5a7b906d179554ba701043619910923465b10611fe198736a53
3
+ metadata.gz: 1747ecbaa97d17fef8acf4946bd24c59ea255d3179776c09c701ccea77f4d006
4
+ data.tar.gz: e748481ebd6df16c369e8ba7660ba371f82a4445b2b89df8a9cf1aa8b23ac657
5
5
  SHA512:
6
- metadata.gz: 4bb5843f3f1fc44f56bfeea79d2315ecb61c278ebdbb089e8cd5405784f39ba4475c0a04bdeaddd179a5bf863fa46139f76692ebaff3c8185abc8c21075544e6
7
- data.tar.gz: 6982da454c1f364143d0d3abd11777c25a8114dbd3dd6ab6c5987dadb2239e804dee6ec124ada34f7d8a1aabe62dabf29047bb12f0a48f306fb29ee7a54ca111
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
- * Install Ruby and Bundler (check the automated tests to find the most recent version of Ruby and Bundler that are supported)
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 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?)
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://github.com/pact-foundation/pact_broker/wiki/Configuration#running-the-broker-behind-a-reverse-proxy
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
@@ -3,6 +3,12 @@ module PactBroker
3
3
 
4
4
  extend self
5
5
 
6
+ def for_upgrades_of_existing_installations
7
+ if from(:integrations).count > 0
8
+ yield
9
+ end
10
+ end
11
+
6
12
  def large_text_type
7
13
  if postgres?
8
14
  :text
@@ -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.82.0 and later, this defaults to `false`.<br/>
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
@@ -8,7 +8,6 @@ module PactBroker
8
8
 
9
9
  property :number
10
10
  if PactBroker.feature_enabled?(:branches)
11
- property :branch
12
11
  property :build_url
13
12
  end
14
13
 
@@ -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
@@ -36,6 +36,10 @@ module PactBroker
36
36
  ["GET", "PUT", "DELETE", "PATCH", "OPTIONS"]
37
37
  end
38
38
 
39
+ def request_body_required?
40
+ request.put? || request.patch?
41
+ end
42
+
39
43
  def put_can_create?
40
44
  true
41
45
  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/pacticipant_schema"
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::PacticipantSchema
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: true,
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 | (verification_id) REFERENCES verifications(id) ON DELETE CASCADE
278
- # triggered_webhooks | triggered_webhooks_verification_id_fkey | (verification_id) REFERENCES verifications(id)
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)
@@ -330,6 +330,14 @@ module PactBroker
330
330
  def tag_names
331
331
  tags.collect(&:name)
332
332
  end
333
+
334
+ def branch
335
+ raise NotImplementedError
336
+ end
337
+
338
+ def branch= branch
339
+ raise NotImplementedError
340
+ end
333
341
  end
334
342
  end
335
343
  end
@@ -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.blank?
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, Metrics/MethodLength
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, Metrics/MethodLength
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 new_name, existing_names
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 new_name, existing_names
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 name
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
  }
@@ -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.blank? && !search.blank?
32
+ if index_items.empty? && !search.blank?
31
33
  error_messages << "No pacticipants found matching: \"#{search}\""
32
34
  end
33
35
 
@@ -0,0 +1,10 @@
1
+ require "haml"
2
+ require "pact_broker/string_refinements"
3
+
4
+ module Haml::Helpers
5
+ using PactBroker::StringRefinements
6
+
7
+ def blank?(thing)
8
+ thing.blank?
9
+ end
10
+ end
@@ -23,10 +23,9 @@
23
23
  = provider_name
24
24
 
25
25
 
26
- - unless errors.blank?
27
- - errors.each do | error |
28
- %div.alert.alert-danger
29
- = error
26
+ - errors.each do | error |
27
+ %div.alert.alert-danger
28
+ = error
30
29
 
31
30
  - if consumer && provider
32
31
  %form
@@ -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? && search.blank?
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
- - unless errors.blank?
11
- - errors.each do | error |
12
- %div.alert.alert-danger
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? && search.blank?
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
- - unless errors.blank?
11
- - errors.each do | error |
12
- %div.alert.alert-danger
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
@@ -1,3 +1,3 @@
1
1
  module PactBroker
2
- VERSION = "2.101.0"
2
+ VERSION = "2.102.2"
3
3
  end
@@ -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&.branch || ""
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.101.0
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-06-13 00:00:00.000000000 Z
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.15
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