pact_broker 2.86.0 → 2.87.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/release_gem.yml +1 -1
  3. data/CHANGELOG.md +35 -0
  4. data/db/migrations/20210929_increase_event_context_column_size.rb +14 -0
  5. data/docker-compose-test.yml +2 -0
  6. data/lib/pact/doc/interaction_view_model.rb +2 -2
  7. data/lib/pact/doc/markdown/consumer_contract_renderer.rb +1 -1
  8. data/lib/pact_broker/api/contracts/configuration.rb +33 -0
  9. data/lib/pact_broker/api/contracts/publish_contracts_schema.rb +35 -16
  10. data/lib/pact_broker/api/decorators/matrix_decorator.rb +3 -1
  11. data/lib/pact_broker/api/decorators/verification_decorator.rb +5 -3
  12. data/lib/pact_broker/api/pact_broker_urls.rb +26 -6
  13. data/lib/pact_broker/api/resources/default_base_resource.rb +4 -0
  14. data/lib/pact_broker/api/resources/environment.rb +1 -1
  15. data/lib/pact_broker/api/resources/environments.rb +1 -1
  16. data/lib/pact_broker/api/resources/index.rb +7 -1
  17. data/lib/pact_broker/api/resources/publish_contracts.rb +1 -1
  18. data/lib/pact_broker/api/resources/verification.rb +5 -2
  19. data/lib/pact_broker/api/resources/webhook_execution_methods.rb +23 -17
  20. data/lib/pact_broker/api.rb +1 -0
  21. data/lib/pact_broker/application_context.rb +5 -0
  22. data/lib/pact_broker/db/delete_overwritten_data.rb +41 -23
  23. data/lib/pact_broker/deployments/deployed_version.rb +1 -0
  24. data/lib/pact_broker/deployments/deployed_version_service.rb +1 -0
  25. data/lib/pact_broker/deployments/environment_service.rb +4 -1
  26. data/lib/pact_broker/deployments/released_version_service.rb +1 -0
  27. data/lib/pact_broker/doc/controllers/app.rb +1 -0
  28. data/lib/pact_broker/doc/views/can-i-deploy.markdown +2 -1
  29. data/lib/pact_broker/doc/views/index/publish-contracts.markdown +38 -9
  30. data/lib/pact_broker/domain/index_item.rb +9 -0
  31. data/lib/pact_broker/domain/verification.rb +3 -0
  32. data/lib/pact_broker/index/service.rb +2 -2
  33. data/lib/pact_broker/locale/en.yml +3 -1
  34. data/lib/pact_broker/matrix/parse_can_i_deploy_query.rb +5 -3
  35. data/lib/pact_broker/pacticipants/repository.rb +1 -1
  36. data/lib/pact_broker/pacts/metadata.rb +7 -1
  37. data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +3 -2
  38. data/lib/pact_broker/pacts/service.rb +5 -5
  39. data/lib/pact_broker/string_refinements.rb +1 -1
  40. data/lib/pact_broker/test/http_test_data_builder.rb +2 -0
  41. data/lib/pact_broker/ui/helpers/url_helper.rb +12 -0
  42. data/lib/pact_broker/ui/view_models/index_item.rb +15 -1
  43. data/lib/pact_broker/ui/view_models/index_item_branch_head.rb +39 -0
  44. data/lib/pact_broker/ui/view_models/index_item_provider_branch_head.rb +39 -0
  45. data/lib/pact_broker/ui/views/dashboard/show.haml +14 -7
  46. data/lib/pact_broker/verifications/service.rb +3 -3
  47. data/lib/pact_broker/version.rb +1 -1
  48. data/lib/pact_broker/versions/branch_head.rb +0 -2
  49. data/lib/pact_broker/versions/branch_version.rb +1 -0
  50. data/lib/pact_broker/versions/repository.rb +0 -1
  51. data/lib/pact_broker/webhooks/pact_and_verification_parameters.rb +17 -3
  52. data/lib/pact_broker/webhooks/trigger_service.rb +1 -1
  53. data/lib/pact_broker/webhooks/webhook.rb +5 -0
  54. data/public/stylesheets/index.css +5 -0
  55. data/script/data/auto-create-things-for-tags.rb +1 -0
  56. data/script/data/contract-published-requiring-verification.rb +0 -1
  57. data/spec/fixtures/invalid-publish-contract-body.json +38 -0
  58. data/spec/integration/webhooks/contract_publication_spec.rb +68 -0
  59. data/spec/integration/webhooks/contract_requiring_verification_published_spec.rb +67 -0
  60. data/spec/integration/webhooks/pact_publication_spec.rb +1 -1
  61. data/spec/lib/pact/doc/markdown/consumer_contract_renderer_spec.rb +2 -2
  62. data/spec/lib/pact_broker/api/contracts/publish_contracts_schema_spec.rb +13 -0
  63. data/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb +1 -1
  64. data/spec/lib/pact_broker/api/decorators/verification_decorator_spec.rb +7 -6
  65. data/spec/lib/pact_broker/api/decorators/verification_summary_decorator_spec.rb +1 -1
  66. data/spec/lib/pact_broker/api/pact_broker_urls_spec.rb +18 -0
  67. data/spec/lib/pact_broker/api/resources/triggered_webhook_logs_spec.rb +6 -5
  68. data/spec/lib/pact_broker/matrix/parse_can_i_deploy_query_spec.rb +13 -0
  69. data/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb +4 -5
  70. data/spec/lib/pact_broker/ui/view_models/index_item_spec.rb +1 -1
  71. data/spec/lib/pact_broker/verifications/service_spec.rb +6 -6
  72. data/spec/lib/pact_broker/webhooks/render_spec.rb +3 -2
  73. data/tasks/db.rake +4 -1
  74. metadata +13 -3
@@ -2,11 +2,14 @@ require "pact_broker/deployments/environment"
2
2
  require "securerandom"
3
3
  require "pact_broker/pacticipants/generate_display_name"
4
4
  require "pact_broker/string_refinements"
5
+ require "pact_broker/repositories/scopes"
5
6
 
6
7
  module PactBroker
7
8
  module Deployments
8
9
  module EnvironmentService
9
10
  using PactBroker::StringRefinements
11
+ extend PactBroker::Repositories::Scopes
12
+
10
13
  extend self
11
14
 
12
15
  def self.included(base)
@@ -34,7 +37,7 @@ module PactBroker
34
37
  end
35
38
 
36
39
  def find_all
37
- PactBroker::Deployments::Environment.order(Sequel.function(:lower, :display_name)).all
40
+ scope_for(PactBroker::Deployments::Environment).order(Sequel.function(:lower, :display_name)).all
38
41
  end
39
42
 
40
43
  def find(uuid)
@@ -52,6 +52,7 @@ module PactBroker
52
52
  .where(pacticipant_id: pacticipant.id)
53
53
  .eager(:version)
54
54
  .eager(:environment)
55
+ .order(:created_at, :id)
55
56
  .all
56
57
  end
57
58
  end
@@ -17,6 +17,7 @@ module PactBroker
17
17
  "webhooks-webhooks" => "webhooks",
18
18
  "webhook" => "webhooks",
19
19
  "can-i-deploy-pacticipant-version-to-tag" => "can-i-deploy",
20
+ "can-i-deploy-pacticipant-version-to-environment" => "can-i-deploy",
20
21
  "pacticipant" => "pacticipants"
21
22
  }.freeze
22
23
 
@@ -10,7 +10,8 @@ A simplified resource that accepts the same parameters as the basic usage of the
10
10
  * _version_: The version of the pacticipant (application) you want to deploy (required).
11
11
  * _environment_: The name of the environment into which the pacticipant (application) is to be deployed.
12
12
  * _to_: The tag used to identify the environment into which you wish to deploy the application (eg. `test` or `prod`). Deprecated - use the `environment=ENVIRONMENT` parameter in preference to the `to=TAG` parameter as deployments and environments are now explictly supported.
13
- * _ignore[]_: The name of the pacticipant to ignore when determining if it is safe to deploy (optional). May be used multiple times.
13
+ * _ignore[]_: The name of the pacticipant to ignore when determining if it is safe to deploy (optional). May be used multiple times. eg `ignore[]=foo&ignore[]=bar`
14
+ * _ignore[][pacticipant]_ and _ignore[][version]_: When ignoring a specific pacticipant version, the name and version of the application to ignore may be specified using "nested" param names syntax. eg. `ignore[][pacticipant]=foo&ignore[][version]=2ac5a946&ignore[][pacticipant]=bar`
14
15
 
15
16
 
16
17
  If you have an environment that you identify with the name `prod`, and each time you deployed an application to the prod environment you recorded the deployment of relevant application version in the Pact Broker using `record-deployment`, then calling `/can-i-deploy?pacticipant=Foo&version=734137278d&environment=prod` will check that version 734137278d of Foo has a successful verification result with each of the integrated application versions that are currently in prod. That is, it is safe to deploy.
@@ -4,11 +4,16 @@ Allowed methods: `POST`
4
4
 
5
5
  Path: `/contracts/publish`
6
6
 
7
+ Index relation: `pb:publish-contracts`
8
+
9
+ Supported from: `v2.86.0`
10
+
7
11
  This is the preferred endpoint with which to publish contracts (previously, contracts were published using multiple calls to different endpoints to create the tag and contract resources). To detect whether this endpoint exists in a particular version of the Pact Broker, make a request to the index resource, and locate the `pb:publish-contracts` relation. Do a `POST` to the href specified for that relation.
8
12
 
9
- The previous tag and pact endpoints are still supported, however, future features that build on this endpoint may not be able to be backported into those endpoints (eg. publishing pacts with a branch).
13
+ The previous tag and pact endpoints are still supported, however, future features that build on this endpoint may not be able to be backported into those endpoints.
10
14
 
11
15
  ## Parameters
16
+
12
17
  * `pacticipantName`: the name of the application. Required.
13
18
  * `pacticipantVersionNumber`: the version number of the application. Required. It is recommended that this should be or include the git SHA. See [http://docs.pact.io/versioning](http://docs.pact.io/versioning).
14
19
  * `branch`: The git branch name. Optional but strongly recommended.
@@ -20,7 +25,31 @@ The previous tag and pact endpoints are still supported, however, future feature
20
25
  * `specification`: currently, only contracts of type "pact" are supported, but this will be extended in the future. Required.
21
26
  * `contentType`: currently, only contracts with a content type of "application/json" are supported. Required.
22
27
  * `content`: the content of the contract. Must be Base64 encoded. Required.
23
- * `onConflict`: Specifies the action to take when a contract for this consumer version already exists with different content. Allowed values are `overwrite`|`merge`. Optional. Defaults to `overwrite`. When `merge` is specified, the interactions are merged into any pre-existing pact. This is required when the tests that generate pact files are split over multiple nodes.
28
+
29
+ ## Responses
30
+
31
+ ### Success
32
+
33
+ * `notices`
34
+ * `level`: one of `debug`, `info`, `warning`,`prompt`,`success`
35
+ * `text`: the text of the notice. This is designed to be displayed in the output of a CLI.
36
+
37
+ The `_links` section will contain links to all the resources created by the publication. The relations are:
38
+
39
+ * `pb:contracts` (array)
40
+ * `pb:pacticipant-version-tags` (array)
41
+ * `pb:pacticipant-version`
42
+ * `pb:pacticipant`
43
+
44
+ ### Errors
45
+
46
+ Any validation errors will be returned in the standard Pact Broker format:
47
+
48
+ {
49
+ "errors": {
50
+ "<fieldName>": ["message 1", "message 2"]
51
+ }
52
+ }
24
53
 
25
54
  ## Example
26
55
 
@@ -37,30 +66,29 @@ The previous tag and pact endpoints are still supported, however, future feature
37
66
  "providerName": "Bar",
38
67
  "specification": "pact",
39
68
  "contentType": "application/json",
40
- "content": "<base64 encoded JSON pact>",
41
- "onConflict": "overwrite"
69
+ "content": "<base64 encoded JSON pact>"
42
70
  }
43
71
  ]
44
72
  }
45
73
 
46
74
  {
47
75
  {
48
- "logs": [
76
+ "notices": [
49
77
  {
50
78
  "level": "debug",
51
- "message": "Created Foo version dc5eb529230038a4673b8c971395bd2922d8b240 with branch main and tags main"
79
+ "text": "Created Foo version dc5eb529230038a4673b8c971395bd2922d8b240 with branch main and tags main"
52
80
  },
53
81
  {
54
82
  "level": "info",
55
- "message": "Pact published for Foo version dc5eb529230038a4673b8c971395bd2922d8b240 and provider Bar."
83
+ "text": "Pact published for Foo version dc5eb529230038a4673b8c971395bd2922d8b240 and provider Bar."
56
84
  },
57
85
  {
58
86
  "level": "debug",
59
- "message": " Events detected: contract_published, contract_content_changed (first time any pact published for this consumer with consumer version tagged main)"
87
+ "text": " Events detected: contract_published, contract_content_changed (first time any pact published for this consumer with consumer version tagged main)"
60
88
  },
61
89
  {
62
90
  "level": "debug",
63
- "message": " Webhook \"foo webhook\" triggered for event contract_content_changed.\n See logs at http://example.org/triggered-webhooks/1234/logs\""
91
+ "text": " Webhook \"foo webhook\" triggered for event contract_content_changed.\n See logs at http://example.org/triggered-webhooks/1234/logs\""
64
92
  }
65
93
  ],
66
94
  "_embedded": {
@@ -118,3 +146,4 @@ The previous tag and pact endpoints are still supported, however, future feature
118
146
  }
119
147
  }
120
148
  }
149
+
@@ -74,6 +74,10 @@ module PactBroker
74
74
  consumer_version.branch_heads.collect(&:branch_name)
75
75
  end
76
76
 
77
+ def consumer_version_branch_heads
78
+ consumer_version.branch_heads
79
+ end
80
+
77
81
  def consumer_version_environment_names
78
82
  (consumer_version.current_deployed_versions.collect(&:environment).collect(&:name) + consumer_version.current_supported_released_versions.collect(&:environment).collect(&:name)).uniq
79
83
  end
@@ -90,6 +94,11 @@ module PactBroker
90
94
  @latest_verification ? @latest_verification.provider_version_number : nil
91
95
  end
92
96
 
97
+ def provider_version_branch_heads
98
+ provider_version&.branch_heads || []
99
+ end
100
+
101
+
93
102
  def provider_version_branches
94
103
  provider_version&.branch_heads&.collect(&:branch_name) || []
95
104
  end
@@ -258,6 +258,9 @@ end
258
258
  # wip | boolean | NOT NULL DEFAULT false
259
259
  # consumer_version_selector_hashes | text |
260
260
  # tag_names | text |
261
+ # pact_pending | boolean |
262
+ # verified_by_implementation | text |
263
+ # verified_by_version | text |
261
264
  # Indexes:
262
265
  # verifications_pkey | PRIMARY KEY btree (id)
263
266
  # verifications_pact_version_id_number_index | UNIQUE btree (pact_version_id, number)
@@ -138,8 +138,8 @@ module PactBroker
138
138
  pact_publications = head_pact_publications(consumer_name: consumer_name, provider_name: provider_name, tags: true, page_number: page_number, page_size: page_size)
139
139
  .eager(:consumer)
140
140
  .eager(:provider)
141
- .eager(pact_version: { latest_verification: { provider_version: [{ current_deployed_versions: :environment }, { current_supported_released_versions: :environment }, :branch_heads, { tags: :head_tag }]} })
142
- .eager(consumer_version: [{ current_deployed_versions: :environment }, { current_supported_released_versions: :environment }, :branch_heads, { tags: :head_tag }])
141
+ .eager(pact_version: { latest_verification: { provider_version: [{ current_deployed_versions: :environment }, { current_supported_released_versions: :environment }, { branch_heads: :branch_version }, { tags: :head_tag }]} })
142
+ .eager(consumer_version: [{ current_deployed_versions: :environment }, { current_supported_released_versions: :environment }, { branch_heads: :branch_version }, { tags: :head_tag }])
143
143
  .eager(:head_pact_publications_for_tags)
144
144
 
145
145
  pact_publications.all.collect do | pact_publication |
@@ -34,16 +34,18 @@ en:
34
34
  consumerVersionTags: The list of tag names for the most recent consumer version associated with the pact content, separated by ", "
35
35
  consumerVersionBranch: The repository branch associated with the consumer version
36
36
  providerVersionTags: The list of tag names for the provider version associated with the verification result, separated by ", ".
37
+ providerVersionDescriptions: The descriptions of the provider version(s) for which the contract_requiring_verification_published webhook has been triggered.
37
38
  providerVersionBranch: The repository branch associated with the provider version
38
39
  consumerLabels: The list of labels for the consumer associated with the pact content, separated by ", ".
39
40
  providerLabels: The list of labels for the provider associated with the pact content, separated by ", ".
40
- pactUrl: The "permalink" URL to the newly published pact (the URL specifying the consumer version URL, rather than the "/latest" format.
41
+ pactUrl: The "permalink" URL to the newly published pact content (using the pact version SHA).
41
42
  verificationResultUrl: The URL to the relevant verification result.
42
43
  githubVerificationStatus: The verification status using the correct keywords for posting to the Github commit status API. See https://developer.github.com/v3/repos/statuses
43
44
  bitbucketVerificationStatus: The verification status using the correct keywords for posting to the Bitbucket commit status API. See https://developer.atlassian.com/server/bitbucket/how-tos/updating-build-status-for-commits/
44
45
  azureDevOpsVerificationStatus: The verification status using the correct keywords for posting to the Azure DevOps GitStatusState API. See https://docs.microsoft.com/en-us/rest/api/azure/devops/git/statuses/create?view=azure-devops-rest-6.0
45
46
  gitlabVerificationStatus: The verification status using the correct keywords for posting to the Gitlab Commits API. See https://docs.gitlab.com/ee/api/commits.html#post-the-build-status-to-a-commit
46
47
  eventName: The name of the event that triggered the webhook
48
+ buildUrl: The URL of the build that published the resources that have triggered the webhook (currently only supported for contracts published using the 'all in one' endpoint).
47
49
  currentlyDeployedProviderVersionNumber: The version number of the currently deployed provider version (when used in a template, the webhook will be triggered once for each currently deployed provider version)
48
50
  no_webhooks_enabled_for_event: No enabled webhooks found for the detected events
49
51
  webhook_triggered_for_event: Webhook %{webhook_description} triggered for event %{event_name}.
@@ -29,9 +29,11 @@ module PactBroker
29
29
  end
30
30
 
31
31
  if params[:ignore].is_a?(Array)
32
- options[:ignore_selectors] = params[:ignore].collect do | pacticipant_name |
33
- if pacticipant_name.is_a?(String)
34
- PactBroker::Matrix::UnresolvedSelector.new(pacticipant_name: pacticipant_name)
32
+ options[:ignore_selectors] = params[:ignore].collect do | param |
33
+ if param.is_a?(String)
34
+ PactBroker::Matrix::UnresolvedSelector.new(pacticipant_name: param)
35
+ elsif param.is_a?(Hash) && param.key?(:pacticipant)
36
+ PactBroker::Matrix::UnresolvedSelector.new({ pacticipant_name: param[:pacticipant], pacticipant_version_number: param[:version] }.compact)
35
37
  end
36
38
  end.compact
37
39
  else
@@ -95,7 +95,7 @@ module PactBroker
95
95
  end
96
96
 
97
97
  def search_by_name(pacticipant_name)
98
- terms = pacticipant_name.split.map { |v| v.gsub("_", '\\_') }
98
+ terms = pacticipant_name.split.map { |v| v.gsub("_", "\\_") }
99
99
  string_match_query = Sequel.|( *terms.map { |term| Sequel.ilike(Sequel[:pacticipants][:name], "%#{term}%") })
100
100
  PactBroker::Domain::Pacticipant.where(string_match_query)
101
101
  end
@@ -5,7 +5,7 @@ module PactBroker
5
5
 
6
6
  MAPPINGS = [
7
7
  [:consumer_version_tags, "cvt"],
8
- [:consumer_version_number, "cvn"], # for old urls
8
+ [:consumer_version_number, "cvn"], # for old urls and build_metadata_for_consumer_version_number
9
9
  [:consumer_version_id, "cv"],
10
10
  [:wip, "w"],
11
11
  [:pending, "p"],
@@ -33,6 +33,12 @@ module PactBroker
33
33
  end
34
34
  end
35
35
 
36
+ def build_metadata_for_consumer_version_number(consumer_version_number)
37
+ {
38
+ "cvn" => consumer_version_number
39
+ }
40
+ end
41
+
36
42
  # When a pact is published, and a webhook is triggered, this stores
37
43
  # the current tags and consumer version number in the metadata parameter of the
38
44
  # pact version URL that is made available in the webhook template
@@ -132,6 +132,7 @@ module PactBroker
132
132
  selectors = selector_for_latest_main_version_or_overall_latest(provider)
133
133
  selectors << Selector.for_currently_deployed
134
134
  selectors << Selector.for_currently_supported
135
+ logger.debug("Default selectors", payload: selectors)
135
136
  selectors
136
137
  end
137
138
 
@@ -140,9 +141,9 @@ module PactBroker
140
141
  consumers = integration_service.find_for_provider(provider).collect(&:consumer)
141
142
 
142
143
  consumers.collect do | consumer |
143
- if consumer.main_branch && PactBroker::Domain::Version.for_selector(PactBroker::Matrix::UnresolvedSelector.new(branch: consumer.main_branch, latest: true)).any?
144
+ if consumer.main_branch && PactBroker::Domain::Version.for_selector(PactBroker::Matrix::UnresolvedSelector.new(branch: consumer.main_branch, pacticipant_name: consumer.name, latest: true)).any?
144
145
  selectors << Selector.for_main_branch.for_consumer(consumer.name)
145
- elsif consumer.main_branch && PactBroker::Domain::Version.for_selector(PactBroker::Matrix::UnresolvedSelector.new(tag: consumer.main_branch, latest: true)).any?
146
+ elsif consumer.main_branch && PactBroker::Domain::Version.for_selector(PactBroker::Matrix::UnresolvedSelector.new(tag: consumer.main_branch, pacticipant_name: consumer.name, latest: true)).any?
146
147
  selectors << Selector.latest_for_tag(consumer.main_branch).for_consumer(consumer.name)
147
148
  else
148
149
  selectors << Selector.overall_latest.for_consumer(consumer.name)
@@ -56,7 +56,7 @@ module PactBroker
56
56
  existing_pact = pact_repository.find_by_version_and_provider(consumer_version.id, provider.id)
57
57
 
58
58
  if existing_pact
59
- update_pact params, existing_pact
59
+ create_pact_revision params, existing_pact
60
60
  else
61
61
  create_pact params, consumer_version, provider
62
62
  end
@@ -72,7 +72,7 @@ module PactBroker
72
72
  existing_pact.json_content, params[:json_content]
73
73
  )
74
74
 
75
- update_pact params, existing_pact
75
+ create_pact_revision params, existing_pact
76
76
  end
77
77
 
78
78
  def find_all_pact_versions_between consumer, options
@@ -155,7 +155,7 @@ module PactBroker
155
155
  end
156
156
 
157
157
  # Overwriting an existing pact with the same consumer/provider/consumer version number
158
- def update_pact params, existing_pact
158
+ def create_pact_revision params, existing_pact
159
159
  logger.info "Updating existing pact publication with params #{params.reject{ |k, _v| k == :json_content}}"
160
160
  logger.debug "Content #{params[:json_content]}"
161
161
  pact_version_sha = generate_sha(params[:json_content])
@@ -177,12 +177,12 @@ module PactBroker
177
177
  updated_pact
178
178
  end
179
179
 
180
+ private :create_pact_revision
181
+
180
182
  def disallowed_modification?(existing_pact, new_json_content)
181
183
  !PactBroker.configuration.allow_dangerous_contract_modification && existing_pact && existing_pact.pact_version_sha != generate_sha(new_json_content)
182
184
  end
183
185
 
184
- private :update_pact
185
-
186
186
  # When no publication for the given consumer/provider/consumer version number exists
187
187
  def create_pact params, version, provider
188
188
  logger.info "Creating new pact publication with params #{params.reject{ |k, _v| k == :json_content}}"
@@ -38,7 +38,7 @@ module PactBroker
38
38
  first_letter = separators.shift
39
39
  end
40
40
 
41
- separators = ["_", '\s'] if separators.empty?
41
+ separators = ["_", "\\s"] if separators.empty?
42
42
 
43
43
  str = self.dup
44
44
 
@@ -20,6 +20,7 @@ module PactBroker
20
20
  logger.filter(/(Authorization: ).*/,'\1[REMOVED]')
21
21
  end
22
22
  end
23
+ faraday.basic_auth(auth[:username], auth[:password]) if auth[:username]
23
24
  faraday.headers["Authorization"] = "Bearer #{auth[:token]}" if auth[:token]
24
25
  faraday.adapter Faraday.default_adapter
25
26
  end
@@ -229,6 +230,7 @@ module PactBroker
229
230
  "providerVersionBranch" => "${pactbroker.providerVersionBranch}",
230
231
  "providerName" => "${pactbroker.providerName}",
231
232
  "providerVersionNumber" => "${pactbroker.providerVersionNumber}",
233
+ "providerVersionDescriptions" => "${pactbroker.providerVersionDescriptions}",
232
234
  "consumerVersionBranch" => "${pactbroker.consumerVersionBranch}",
233
235
  }
234
236
  request_body = {
@@ -18,6 +18,18 @@ module PactBroker
18
18
  def matrix_url consumer_name, provider_name, base_url = ""
19
19
  "#{base_url}/matrix/provider/#{ERB::Util.url_encode(provider_name)}/consumer/#{ERB::Util.url_encode(consumer_name)}"
20
20
  end
21
+
22
+ def matrix_url_for_consumer_version consumer_name, consumer_version_number, provider_name, base_url = ""
23
+ query = {
24
+ q:
25
+ [
26
+ { pacticipant: consumer_name, version: consumer_version_number },
27
+ { pacticipant: provider_name }
28
+ ],
29
+ latestby: "cvpv"
30
+ }
31
+ "#{base_url}/matrix?" + Rack::Utils.build_nested_query(query)
32
+ end
21
33
  end
22
34
  end
23
35
  end
@@ -3,6 +3,8 @@ require "pact_broker/ui/helpers/url_helper"
3
3
  require "pact_broker/date_helper"
4
4
  require "pact_broker/versions/abbreviate_number"
5
5
  require "pact_broker/configuration"
6
+ require "pact_broker/ui/view_models/index_item_branch_head"
7
+ require "pact_broker/ui/view_models/index_item_provider_branch_head"
6
8
  require "forwardable"
7
9
 
8
10
  module PactBroker
@@ -66,6 +68,12 @@ module PactBroker
66
68
  @relationship.latest?
67
69
  end
68
70
 
71
+ def consumer_version_branch_heads
72
+ @relationship.consumer_version_branch_heads.collect do | branch_head |
73
+ IndexItemBranchHead.new(branch_head, consumer_name)
74
+ end
75
+ end
76
+
69
77
  def consumer_version_latest_tag_names
70
78
  @relationship.tag_names
71
79
  end
@@ -74,6 +82,12 @@ module PactBroker
74
82
  @relationship.latest_verification_latest_tags.collect(&:name)
75
83
  end
76
84
 
85
+ def provider_version_branch_heads
86
+ @relationship.provider_version_branch_heads.collect do | branch_head |
87
+ IndexItemProviderBranchHead.new(branch_head, provider_name)
88
+ end
89
+ end
90
+
77
91
  def consumer_group_url
78
92
  Helpers::URLHelper.group_url(consumer_name, base_url)
79
93
  end
@@ -95,7 +109,7 @@ module PactBroker
95
109
  end
96
110
 
97
111
  def pact_matrix_url
98
- Helpers::URLHelper.matrix_url(consumer_name, provider_name, base_url)
112
+ Helpers::URLHelper.matrix_url_for_consumer_version(consumer_name, consumer_version_number, provider_name, base_url)
99
113
  end
100
114
 
101
115
  def any_webhooks?
@@ -0,0 +1,39 @@
1
+ require "pact_broker/api/pact_broker_urls"
2
+ require "pact_broker/ui/helpers/url_helper"
3
+ require "pact_broker/date_helper"
4
+
5
+ module PactBroker
6
+ module UI
7
+ module ViewDomain
8
+ class IndexItemBranchHead
9
+
10
+ include PactBroker::Api::PactBrokerUrls
11
+
12
+ def initialize branch_head, pacticipant_name
13
+ @branch_head = branch_head
14
+ @pacticipant_name = pacticipant_name
15
+ end
16
+
17
+ def branch_name
18
+ branch_head.branch_name
19
+ end
20
+
21
+ def tooltip
22
+ if branch_head.branch_version.auto_created
23
+ "This is the latest pact from branch \"#{branch_name}\". This branch was automatically inferred from the first tag because the Pact Broker configuration setting `use_first_tag_as_branch` was true."
24
+ else
25
+ "This is the latest pact from branch \"#{branch_name}\"."
26
+ end
27
+ end
28
+
29
+ def latest?
30
+ true
31
+ end
32
+
33
+ private
34
+
35
+ attr_reader :branch_head, :pacticipant_name
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,39 @@
1
+ require "pact_broker/api/pact_broker_urls"
2
+ require "pact_broker/ui/helpers/url_helper"
3
+ require "pact_broker/date_helper"
4
+
5
+ module PactBroker
6
+ module UI
7
+ module ViewDomain
8
+ class IndexItemProviderBranchHead
9
+
10
+ include PactBroker::Api::PactBrokerUrls
11
+
12
+ def initialize branch_head, pacticipant_name
13
+ @branch_head = branch_head
14
+ @pacticipant_name = pacticipant_name
15
+ end
16
+
17
+ def branch_name
18
+ branch_head.branch_name
19
+ end
20
+
21
+ def tooltip
22
+ if branch_head.branch_version.auto_created
23
+ "The latest verification is from branch \"#{branch_name}\". This branch was automatically inferred from the first tag because the Pact Broker configuration setting `use_first_tag_as_branch` was true."
24
+ else
25
+ "The latest verification is from branch \"#{branch_name}\"."
26
+ end
27
+ end
28
+
29
+ def latest?
30
+ true
31
+ end
32
+
33
+ private
34
+
35
+ attr_reader :branch_head, :pacticipant_name
36
+ end
37
+ end
38
+ end
39
+ end
@@ -85,9 +85,9 @@
85
85
  %button.clippy.invisible{ title: "Copy to clipboard" }
86
86
  %span.copy-icon
87
87
  - if view == "branch" || view == "all"
88
- - index_item.consumer_version_branches.each do | branch_name |
89
- %div{"class": "tag badge badge-dark"}
90
- = "branch: " + branch_name
88
+ - index_item.consumer_version_branch_heads.each do | branch_head |
89
+ %div{"class": "tag badge badge-dark", "title": branch_head.tooltip, "data-toggle": "tooltip", "data-placement": "right"}
90
+ = "branch: " + branch_head.branch_name
91
91
  - if view == "tag" || view == "all"
92
92
  - index_item.consumer_version_latest_tag_names.each do | tag_name |
93
93
  .tag.badge.badge-primary
@@ -106,9 +106,9 @@
106
106
  %button.clippy.invisible{ title: "Copy to clipboard" }
107
107
  %span.copy-icon
108
108
  - if view == "branch" || view == "all"
109
- - index_item.provider_version_branches.each do | branch_name |
110
- %div{"class": "tag badge badge-dark"}
111
- = "branch: " + branch_name
109
+ - index_item.provider_version_branch_heads.each do | branch_head |
110
+ %div{"class": "tag badge badge-dark", "title": branch_head.tooltip, "data-toggle": "tooltip", "data-placement": "right"}
111
+ = "branch: " + branch_head.branch_name
112
112
  - if view == "tag" || view == "all"
113
113
  - index_item.provider_version_latest_tag_names.each do | tag_name |
114
114
  .tag.badge.badge-primary
@@ -159,8 +159,15 @@
159
159
  $('td[data-toggle="tooltip"]').each(function(index, td){
160
160
  //appended tooltip div screws up table if it's appended after a
161
161
  //td, so need to append it to a div
162
- $(td).tooltip({container: $(td).first()});
162
+ $(td).tooltip({ container: $(td).first() });
163
163
  });
164
+
165
+ // https://www.w3schools.com/bootstrap/bootstrap_ref_js_tooltip.asp
166
+
167
+ $('div[data-toggle="tooltip"]').each(function(index, div){
168
+ $(div).tooltip()
169
+ });
170
+
164
171
  });
165
172
 
166
173
  $(".reset-search").on("click", function() {
@@ -138,7 +138,7 @@ module PactBroker
138
138
  latest_version_from_main_branch = [version_service.find_latest_version_from_main_branch(pact_version.provider)].compact
139
139
 
140
140
  latest_version_from_main_branch.collect do | main_branch_version |
141
- identify_required_verification(pact_version, main_branch_version, "latest version from main branch")
141
+ identify_required_verification(pact_version, main_branch_version, "latest from main branch")
142
142
  end.compact
143
143
  end
144
144
  private :required_verifications_for_main_branch
@@ -148,7 +148,7 @@ module PactBroker
148
148
  unscoped_service.find_currently_deployed_versions_for_pacticipant(pact_version.provider)
149
149
  end
150
150
  deployed_versions.collect do | deployed_version |
151
- identify_required_verification(pact_version, deployed_version.version, "currently deployed version (#{deployed_version.environment_name})")
151
+ identify_required_verification(pact_version, deployed_version.version, "deployed in #{deployed_version.environment_name}")
152
152
  end.compact
153
153
  end
154
154
  private :required_verifications_for_deployed_versions
@@ -158,7 +158,7 @@ module PactBroker
158
158
  unscoped_service.find_currently_supported_versions_for_pacticipant(pact_version.provider)
159
159
  end
160
160
  released_versions.collect do | released_version |
161
- identify_required_verification(pact_version, released_version.version, "currently released version (#{released_version.environment_name})")
161
+ identify_required_verification(pact_version, released_version.version, "released in #{released_version.environment_name}")
162
162
  end.compact
163
163
  end
164
164
  private :required_verifications_for_released_versions
@@ -1,3 +1,3 @@
1
1
  module PactBroker
2
- VERSION = "2.86.0"
2
+ VERSION = "2.87.0"
3
3
  end
@@ -28,14 +28,12 @@ end
28
28
 
29
29
  # Table: branch_heads
30
30
  # Columns:
31
- # id | integer | PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY
32
31
  # branch_id | integer | NOT NULL
33
32
  # branch_version_id | integer | NOT NULL
34
33
  # version_id | integer | NOT NULL
35
34
  # pacticipant_id | integer | NOT NULL
36
35
  # branch_name | text | NOT NULL
37
36
  # Indexes:
38
- # branch_heads_pkey | PRIMARY KEY btree (id)
39
37
  # branch_heads_branch_id_index | UNIQUE btree (branch_id)
40
38
  # branch_heads_branch_name_index | btree (branch_name)
41
39
  # branch_heads_pacticipant_id_index | btree (pacticipant_id)
@@ -51,6 +51,7 @@ end
51
51
  # branch_name | text | NOT NULL
52
52
  # created_at | timestamp without time zone | NOT NULL
53
53
  # updated_at | timestamp without time zone | NOT NULL
54
+ # auto_created | boolean | DEFAULT false
54
55
  # Indexes:
55
56
  # branch_versions_pkey | PRIMARY KEY btree (id)
56
57
  # branch_versions_branch_id_version_id_index | UNIQUE btree (branch_id, version_id)
@@ -53,7 +53,6 @@ module PactBroker
53
53
 
54
54
  # There may be a race condition if two simultaneous requests come in to create the same version
55
55
  def create(args)
56
- logger.info "Upserting version #{args[:number]} for pacticipant_id=#{args[:pacticipant_id]}"
57
56
  version_params = {
58
57
  number: args[:number],
59
58
  pacticipant_id: args[:pacticipant_id],