pact_broker 2.41.0 → 2.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/lib/pact_broker/api/decorators/verifiable_pact_decorator.rb +11 -0
- data/lib/pact_broker/doc/views/webhooks.markdown +5 -1
- data/lib/pact_broker/domain/webhook.rb +8 -0
- data/lib/pact_broker/pacts/all_pact_publications.rb +1 -1
- data/lib/pact_broker/pacts/repository.rb +69 -18
- data/lib/pact_broker/test/test_data_builder.rb +18 -2
- data/lib/pact_broker/verifications/service.rb +2 -2
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/webhooks/trigger_service.rb +25 -0
- data/lib/pact_broker/webhooks/webhook_event.rb +10 -3
- data/script/seed.rb +10 -2
- data/spec/features/wip_pacts_spec.rb +7 -4
- data/spec/lib/pact_broker/api/decorators/verifiable_pact_decorator_spec.rb +14 -4
- data/spec/lib/pact_broker/pacts/repository_find_wip_pact_versions_for_provider_spec.rb +73 -6
- data/spec/lib/pact_broker/pacts/service_spec.rb +6 -1
- data/spec/lib/pact_broker/verifications/service_spec.rb +3 -3
- data/spec/lib/pact_broker/webhooks/trigger_service_spec.rb +33 -0
- metadata +2 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 1beb82704006c0aa9708a9b4e9af93075bfc3bf9
         | 
| 4 | 
            +
              data.tar.gz: 8cb7b7148ce8a3152d6ccbe35e49f3e646f5e628
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: b289766c4bc421c975fefc7a109f97eb6bc5f31eac99d1dd6e7754d7f2c7cf7f7dca21652d55d28a1e64d5eacd5f26e16f30ac1af3e2111eefc9a38bb42128f4
         | 
| 7 | 
            +
              data.tar.gz: d6ce416cd0133c2d8278e1addc4f99814a118d9a800a74d1937168ac132e9f7ff27c3a48d63866ffaac0ec0424bd433f468812695e133edbf7a6698edbc9ba09
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,3 +1,17 @@ | |
| 1 | 
            +
            <a name="v2.42.0"></a>
         | 
| 2 | 
            +
            ### v2.42.0 (2019-12-05)
         | 
| 3 | 
            +
             | 
| 4 | 
            +
             | 
| 5 | 
            +
            #### Features
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            * **pacts for verification**
         | 
| 8 | 
            +
              * include list of notices to print rather than inclusionReason and pendingReason	 ([eed0120e](/../../commit/eed0120e))
         | 
| 9 | 
            +
              * only include WIP pacts that were published after the provider tag was first used	 ([673fcb8c](/../../commit/673fcb8c))
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            * **webhooks**
         | 
| 12 | 
            +
              * allow webhooks to be triggered for verification successes and failures	 ([6735da32](/../../commit/6735da32))
         | 
| 13 | 
            +
             | 
| 14 | 
            +
             | 
| 1 15 | 
             
            <a name="v2.41.0"></a>
         | 
| 2 16 | 
             
            ### v2.41.0 (2019-11-21)
         | 
| 3 17 |  | 
| @@ -28,6 +28,9 @@ module PactBroker | |
| 28 28 | 
             
                      property :pending_reason, as: :pendingReason, exec_context: :decorator,
         | 
| 29 29 | 
             
                        if: ->(context) { context[:options][:user_options][:include_pending_status] }
         | 
| 30 30 |  | 
| 31 | 
            +
                      property :notices, getter: -> (context) { context[:decorator].notices(context[:options][:user_options]) }
         | 
| 32 | 
            +
                      property :noteToDevelopers, getter: -> (_) { "Please print out the text from the 'notices' rather than using the inclusionReason and the pendingReason fields. These will be removed when this API moves out of beta."}
         | 
| 33 | 
            +
             | 
| 31 34 | 
             
                      def inclusion_reason
         | 
| 32 35 | 
             
                        PactBroker::Pacts::VerifiablePactMessages.new(represented).inclusion_reason
         | 
| 33 36 | 
             
                      end
         | 
| @@ -35,6 +38,14 @@ module PactBroker | |
| 35 38 | 
             
                      def pending_reason
         | 
| 36 39 | 
             
                        PactBroker::Pacts::VerifiablePactMessages.new(represented).pending_reason
         | 
| 37 40 | 
             
                      end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                      def notices(user_options)
         | 
| 43 | 
            +
                        mess = [{
         | 
| 44 | 
            +
                          text: inclusion_reason
         | 
| 45 | 
            +
                        }]
         | 
| 46 | 
            +
                        mess << { text: pending_reason } if user_options[:include_pending_status]
         | 
| 47 | 
            +
                        mess
         | 
| 48 | 
            +
                      end
         | 
| 38 49 | 
             
                    end
         | 
| 39 50 |  | 
| 40 51 | 
             
                    link :self do | context |
         | 
| @@ -80,7 +80,11 @@ To specify an XML body, you will need to use a correctly escaped string (or use | |
| 80 80 |  | 
| 81 81 | 
             
            `contract_content_changed:` triggered when the content of the contract, or tags applied to the contract have changed since the previous publication. If `base_equality_only_on_content_that_affects_verification_results` is set to `true` in the configuration (the default), any changes to whitespace, ordering of keys, or the ordering of the `interactions` or `messages` will be ignored, and will not trigger this event. It is recommended to trigger a provider verification build for this event.
         | 
| 82 82 |  | 
| 83 | 
            -
            `provider_verification_published:` triggered whenever a provider publishes a verification.
         | 
| 83 | 
            +
            `provider_verification_published:` triggered whenever a provider publishes a verification result.
         | 
| 84 | 
            +
             | 
| 85 | 
            +
            `provider_verification_succeeded:` triggered whenever a provider publishes a successful verification result.
         | 
| 86 | 
            +
             | 
| 87 | 
            +
            `provider_verification_failed:` triggered whenever a provider publishes a failed verification result.
         | 
| 84 88 |  | 
| 85 89 | 
             
            ### Dynamic variable substitution
         | 
| 86 90 |  | 
| @@ -85,6 +85,14 @@ module PactBroker | |
| 85 85 | 
             
                    events.any?(&:provider_verification_published?)
         | 
| 86 86 | 
             
                  end
         | 
| 87 87 |  | 
| 88 | 
            +
                  def trigger_on_provider_verification_succeeded?
         | 
| 89 | 
            +
                    events.any?(&:provider_verification_succeeded?)
         | 
| 90 | 
            +
                  end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                  def trigger_on_provider_verification_failed?
         | 
| 93 | 
            +
                    events.any?(&:provider_verification_failed?)
         | 
| 94 | 
            +
                  end
         | 
| 95 | 
            +
             | 
| 88 96 | 
             
                  private
         | 
| 89 97 |  | 
| 90 98 | 
             
                  def execute_request(webhook_request)
         | 
| @@ -109,7 +109,7 @@ module PactBroker | |
| 109 109 | 
             
                  def head_tag_names
         | 
| 110 110 | 
             
                    # Avoid circular dependency
         | 
| 111 111 | 
             
                    require 'pact_broker/pacts/latest_tagged_pact_publications'
         | 
| 112 | 
            -
                    LatestTaggedPactPublications.where(id: id).select(:tag_name).collect{|t| t[:tag_name]}
         | 
| 112 | 
            +
                    @head_tag_names ||= LatestTaggedPactPublications.where(id: id).select(:tag_name).collect{|t| t[:tag_name]}
         | 
| 113 113 | 
             
                  end
         | 
| 114 114 |  | 
| 115 115 | 
             
                  def to_domain_with_content
         | 
| @@ -125,22 +125,57 @@ module PactBroker | |
| 125 125 | 
             
                    end
         | 
| 126 126 | 
             
                  end
         | 
| 127 127 |  | 
| 128 | 
            -
                   | 
| 129 | 
            -
             | 
| 128 | 
            +
                  # To find the work in progress pacts for this verification execution:
         | 
| 129 | 
            +
                  # For each provider tag that will be applied to this verification result (usually there will just be one, but
         | 
| 130 | 
            +
                  # we have to allow for multiple tags),
         | 
| 131 | 
            +
                  # find the head pacts (the pacts that are the latest for their tag) that have been successfully
         | 
| 132 | 
            +
                  # verified against the provider tag.
         | 
| 133 | 
            +
                  # Then, find all the head pacts, and remove the ones that have been successfully verified by ALL
         | 
| 134 | 
            +
                  # of the provider tags supplied.
         | 
| 135 | 
            +
                  # Then, for all of the head pacts that are remaining (these are the WIP ones) work out which
         | 
| 136 | 
            +
                  # provider tags they are pending for.
         | 
| 137 | 
            +
                  # Don't include pact publications that were created
         | 
| 138 | 
            +
                  def find_wip_pact_versions_for_provider provider_name, provider_tags_names = [], options = {}
         | 
| 139 | 
            +
                    return [] if provider_tags_names.empty?
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                    provider = pacticipant_repository.find_by_name(provider_name)
         | 
| 142 | 
            +
             | 
| 143 | 
            +
                    # Hash of provider tag names => list of head pacts
         | 
| 144 | 
            +
                    successfully_verified_head_pacts_for_provider_tags = find_successfully_verified_head_pacts_by_provider_tag(provider_name, provider_tags_names, options)
         | 
| 145 | 
            +
                    successfully_verified_head_pact_publication_ids_for_each_provider_tag = successfully_verified_head_pacts_for_provider_tags.each_with_object({}) do | (provider_tag_name, head_pacts), hash |
         | 
| 146 | 
            +
                      hash[provider_tag_name] = head_pacts.collect(&:id)
         | 
| 147 | 
            +
                    end
         | 
| 130 148 |  | 
| 131 | 
            -
                    #  | 
| 132 | 
            -
                     | 
| 149 | 
            +
                    # list of pact_publication_ids that are NOT work in progress
         | 
| 150 | 
            +
                    head_pact_publication_ids_successully_verified_by_all_provider_tags = successfully_verified_head_pacts_for_provider_tags.values.collect{ |head_pacts| head_pacts.collect(&:id) }.reduce(:&)
         | 
| 133 151 |  | 
| 134 152 | 
             
                    pact_publication_ids = find_head_pacts_that_have_not_been_successfully_verified_by_all_provider_tags(
         | 
| 135 153 | 
             
                      provider_name,
         | 
| 136 | 
            -
                       | 
| 154 | 
            +
                      head_pact_publication_ids_successully_verified_by_all_provider_tags,
         | 
| 137 155 | 
             
                      options)
         | 
| 138 156 |  | 
| 139 | 
            -
                    pacts = AllPactPublications.where(id: pact_publication_ids).order_ignore_case(:consumer_name).order_append(:consumer_version_order) | 
| 157 | 
            +
                    pacts = AllPactPublications.where(id: pact_publication_ids).order_ignore_case(:consumer_name).order_append(:consumer_version_order)
         | 
| 158 | 
            +
             | 
| 159 | 
            +
                    # The first instance (by date) of each provider tag with that name
         | 
| 160 | 
            +
                    provider_tag_collection = PactBroker::Domain::Tag
         | 
| 161 | 
            +
                      .select_group(Sequel[:tags][:name], Sequel[:pacticipant_id])
         | 
| 162 | 
            +
                      .select_append(Sequel.function(:min, Sequel[:tags][:created_at]).as(:created_at))
         | 
| 163 | 
            +
                      .distinct
         | 
| 164 | 
            +
                      .join(:versions, { Sequel[:tags][:version_id] => Sequel[:versions][:id] } )
         | 
| 165 | 
            +
                      .where(pacticipant_id: provider.id)
         | 
| 166 | 
            +
                      .where(name: provider_tags_names)
         | 
| 167 | 
            +
                      .all
         | 
| 168 | 
            +
             | 
| 140 169 | 
             
                    pacts.collect do | pact|
         | 
| 141 | 
            -
                       | 
| 142 | 
            -
                       | 
| 143 | 
            -
             | 
| 170 | 
            +
                      pending_tag_names = find_provider_tags_for_which_pact_publication_id_is_pending(pact, successfully_verified_head_pact_publication_ids_for_each_provider_tag)
         | 
| 171 | 
            +
                      pre_existing_tag_names = find_provider_tag_names_that_were_first_used_before_pact_published(pact, provider_tag_collection)
         | 
| 172 | 
            +
             | 
| 173 | 
            +
                      pre_existing_pending_tags = pending_tag_names & pre_existing_tag_names
         | 
| 174 | 
            +
             | 
| 175 | 
            +
                      if pre_existing_pending_tags.any?
         | 
| 176 | 
            +
                        VerifiablePact.new(pact.to_domain, true, pre_existing_pending_tags, [], pact.head_tag_names, nil, true)
         | 
| 177 | 
            +
                      end
         | 
| 178 | 
            +
                    end.compact
         | 
| 144 179 | 
             
                  end
         | 
| 145 180 |  | 
| 146 181 | 
             
                  def find_pact_versions_for_provider provider_name, tag = nil
         | 
| @@ -333,13 +368,27 @@ module PactBroker | |
| 333 368 | 
             
                    query
         | 
| 334 369 | 
             
                  end
         | 
| 335 370 |  | 
| 336 | 
            -
                  def find_provider_tags_for_which_pact_publication_id_is_pending( | 
| 371 | 
            +
                  def find_provider_tags_for_which_pact_publication_id_is_pending(pact_publication, successfully_verified_head_pact_publication_ids_for_each_provider_tag)
         | 
| 337 372 | 
             
                    successfully_verified_head_pact_publication_ids_for_each_provider_tag
         | 
| 338 | 
            -
                      .select do |  | 
| 339 | 
            -
                        !pact_publication_ids.include?( | 
| 373 | 
            +
                      .select do | _, pact_publication_ids |
         | 
| 374 | 
            +
                        !pact_publication_ids.include?(pact_publication.id)
         | 
| 340 375 | 
             
                      end.keys
         | 
| 341 376 | 
             
                  end
         | 
| 342 377 |  | 
| 378 | 
            +
                  def find_provider_tag_names_that_were_first_used_before_pact_published(pact_publication, provider_tag_collection)
         | 
| 379 | 
            +
                    provider_tag_collection.select { | tag| to_datetime(tag.created_at) < pact_publication.created_at }.collect(&:name)
         | 
| 380 | 
            +
                  end
         | 
| 381 | 
            +
             | 
| 382 | 
            +
                  # Note: created_at is coming back as a string for sqlite
         | 
| 383 | 
            +
                  # Can't work out how to to tell Sequel that this should be a date
         | 
| 384 | 
            +
                  def to_datetime string_or_datetime
         | 
| 385 | 
            +
                    if string_or_datetime.is_a?(String)
         | 
| 386 | 
            +
                      Sequel.string_to_datetime(string_or_datetime)
         | 
| 387 | 
            +
                    else
         | 
| 388 | 
            +
                      string_or_datetime
         | 
| 389 | 
            +
                    end
         | 
| 390 | 
            +
                  end
         | 
| 391 | 
            +
             | 
| 343 392 | 
             
                  def find_head_pacts_that_have_not_been_successfully_verified_by_all_provider_tags(provider_name, pact_publication_ids_successfully_verified_by_all_provider_tags, options)
         | 
| 344 393 | 
             
                    # Exclude the head pacts that have been successfully verified by all the specified provider tags
         | 
| 345 394 | 
             
                    pact_publication_ids = LatestTaggedPactPublications
         | 
| @@ -349,18 +398,20 @@ module PactBroker | |
| 349 398 | 
             
                      .select_for_subquery(:id)
         | 
| 350 399 | 
             
                  end
         | 
| 351 400 |  | 
| 401 | 
            +
                  # Find the head pacts that have been successfully verified by a provider version with the specified tags
         | 
| 402 | 
            +
                  # Returns a Hash of provider_tag => LatestTaggedPactPublications with only id and tag_name populated
         | 
| 352 403 | 
             
                  def find_successfully_verified_head_pacts_by_provider_tag(provider_name, provider_tags, options)
         | 
| 353 | 
            -
                    provider_tags.compact.each_with_object({}) do | provider_tag,  | 
| 354 | 
            -
                       | 
| 404 | 
            +
                    provider_tags.compact.each_with_object({}) do | provider_tag, hash |
         | 
| 405 | 
            +
                      head_pacts = LatestTaggedPactPublications
         | 
| 355 406 | 
             
                        .join(:verifications, { pact_version_id: :pact_version_id })
         | 
| 356 407 | 
             
                        .join(:tags, { Sequel[:verifications][:provider_version_id] => Sequel[:provider_tags][:version_id] }, {table_alias: :provider_tags})
         | 
| 357 408 | 
             
                        .where(Sequel[:provider_tags][:name] => provider_tag)
         | 
| 358 409 | 
             
                        .provider(provider_name)
         | 
| 359 410 | 
             
                        .where(Sequel[:verifications][:success] => true)
         | 
| 360 | 
            -
                        . | 
| 361 | 
            -
                        .select(Sequel[:latest_tagged_pact_publications][:id].as(:id))
         | 
| 362 | 
            -
                        . | 
| 363 | 
            -
                       | 
| 411 | 
            +
                        .or(Sequel.lit('latest_tagged_pact_publications.created_at < ?', options.fetch(:include_wip_pacts_since)))
         | 
| 412 | 
            +
                        .select(Sequel[:latest_tagged_pact_publications][:id].as(:id), :tag_name)
         | 
| 413 | 
            +
                        .all
         | 
| 414 | 
            +
                      hash[provider_tag] = head_pacts
         | 
| 364 415 | 
             
                    end
         | 
| 365 416 | 
             
                  end
         | 
| 366 417 | 
             
                end
         | 
| @@ -46,6 +46,7 @@ module PactBroker | |
| 46 46 | 
             
                  attr_reader :triggered_webhook
         | 
| 47 47 |  | 
| 48 48 | 
             
                  def initialize(params = {})
         | 
| 49 | 
            +
                    @now = DateTime.now
         | 
| 49 50 | 
             
                  end
         | 
| 50 51 |  | 
| 51 52 | 
             
                  def comment *args
         | 
| @@ -73,8 +74,10 @@ module PactBroker | |
| 73 74 | 
             
                  end
         | 
| 74 75 |  | 
| 75 76 | 
             
                  def create_pact_with_hierarchy consumer_name = "Consumer", consumer_version = "1.2.3", provider_name = "Provider", json_content = default_json_content
         | 
| 76 | 
            -
                     | 
| 77 | 
            -
                     | 
| 77 | 
            +
                    use_consumer(consumer_name)
         | 
| 78 | 
            +
                    create_consumer(consumer_name) if !consumer
         | 
| 79 | 
            +
                    use_provider(provider_name)
         | 
| 80 | 
            +
                    create_provider provider_name if !provider
         | 
| 78 81 | 
             
                    create_consumer_version consumer_version
         | 
| 79 82 | 
             
                    create_pact json_content: json_content
         | 
| 80 83 | 
             
                    self
         | 
| @@ -246,6 +249,14 @@ module PactBroker | |
| 246 249 | 
             
                    create_webhook(parameters.merge(consumer: nil, provider: nil, event_names: [PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED]))
         | 
| 247 250 | 
             
                  end
         | 
| 248 251 |  | 
| 252 | 
            +
                  def create_global_verification_succeeded_webhook parameters = {}
         | 
| 253 | 
            +
                    create_webhook(parameters.merge(consumer: nil, provider: nil, event_names: [PactBroker::Webhooks::WebhookEvent::VERIFICATION_SUCCEEDED]))
         | 
| 254 | 
            +
                  end
         | 
| 255 | 
            +
             | 
| 256 | 
            +
                  def create_global_verification_failed_webhook parameters = {}
         | 
| 257 | 
            +
                    create_webhook(parameters.merge(consumer: nil, provider: nil, event_names: [PactBroker::Webhooks::WebhookEvent::VERIFICATION_FAILED]))
         | 
| 258 | 
            +
                  end
         | 
| 259 | 
            +
             | 
| 249 260 | 
             
                  def create_provider_webhook parameters = {}
         | 
| 250 261 | 
             
                    create_webhook(parameters.merge(consumer: nil))
         | 
| 251 262 | 
             
                  end
         | 
| @@ -334,6 +345,11 @@ module PactBroker | |
| 334 345 | 
             
                    self
         | 
| 335 346 | 
             
                  end
         | 
| 336 347 |  | 
| 348 | 
            +
                  def add_minute
         | 
| 349 | 
            +
                    @now = @now + (1.0/(24*60))
         | 
| 350 | 
            +
                    self
         | 
| 351 | 
            +
                  end
         | 
| 352 | 
            +
             | 
| 337 353 | 
             
                  def add_five_minutes
         | 
| 338 354 | 
             
                    @now = @now + (1.0/(24*60)*5)
         | 
| 339 355 | 
             
                    self
         | 
| @@ -31,9 +31,9 @@ module PactBroker | |
| 31 31 | 
             
                    execution_configuration = webhook_options[:webhook_execution_configuration]
         | 
| 32 32 | 
             
                                                .with_webhook_context(provider_version_tags: verification.provider_version_tag_names)
         | 
| 33 33 |  | 
| 34 | 
            -
                     | 
| 34 | 
            +
                    webhook_trigger_service.trigger_webhooks_for_verification_results_publication(
         | 
| 35 | 
            +
                      pact,
         | 
| 35 36 | 
             
                      verification,
         | 
| 36 | 
            -
                      PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED,
         | 
| 37 37 | 
             
                      webhook_options.deep_merge(webhook_execution_configuration: execution_configuration)
         | 
| 38 38 | 
             
                    )
         | 
| 39 39 | 
             
                    verification
         | 
    
        data/lib/pact_broker/version.rb
    CHANGED
    
    
| @@ -29,6 +29,31 @@ module PactBroker | |
| 29 29 | 
             
                    end
         | 
| 30 30 | 
             
                  end
         | 
| 31 31 |  | 
| 32 | 
            +
                  def trigger_webhooks_for_verification_results_publication(pact, verification, webhook_options)
         | 
| 33 | 
            +
                    if verification.success
         | 
| 34 | 
            +
                      webhook_service.trigger_webhooks(
         | 
| 35 | 
            +
                        pact,
         | 
| 36 | 
            +
                        verification,
         | 
| 37 | 
            +
                        PactBroker::Webhooks::WebhookEvent::VERIFICATION_SUCCEEDED,
         | 
| 38 | 
            +
                        webhook_options
         | 
| 39 | 
            +
                      )
         | 
| 40 | 
            +
                    else
         | 
| 41 | 
            +
                      webhook_service.trigger_webhooks(
         | 
| 42 | 
            +
                        pact,
         | 
| 43 | 
            +
                        verification,
         | 
| 44 | 
            +
                        PactBroker::Webhooks::WebhookEvent::VERIFICATION_FAILED,
         | 
| 45 | 
            +
                        webhook_options
         | 
| 46 | 
            +
                      )
         | 
| 47 | 
            +
                    end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                    webhook_service.trigger_webhooks(
         | 
| 50 | 
            +
                      pact,
         | 
| 51 | 
            +
                      verification,
         | 
| 52 | 
            +
                      PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED,
         | 
| 53 | 
            +
                      webhook_options
         | 
| 54 | 
            +
                    )
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
             | 
| 32 57 | 
             
                  private
         | 
| 33 58 |  | 
| 34 59 | 
             
                  def pact_is_new_or_newly_tagged_or_pact_has_changed_since_previous_version? pact
         | 
| @@ -8,11 +8,11 @@ module PactBroker | |
| 8 8 | 
             
                  CONTRACT_PUBLISHED = 'contract_published'
         | 
| 9 9 | 
             
                  CONTRACT_CONTENT_CHANGED = 'contract_content_changed'
         | 
| 10 10 | 
             
                  VERIFICATION_PUBLISHED = 'provider_verification_published'
         | 
| 11 | 
            +
                  VERIFICATION_SUCCEEDED = 'provider_verification_succeeded'
         | 
| 12 | 
            +
                  VERIFICATION_FAILED = 'provider_verification_failed'
         | 
| 11 13 | 
             
                  DEFAULT_EVENT_NAME = CONTRACT_CONTENT_CHANGED
         | 
| 12 | 
            -
                  #CONTRACT_VERIFIABLE_CONTENT_CHANGED = 'contract_verifiable_content_changed'
         | 
| 13 | 
            -
                  #VERIFICATION_STATUS_CHANGED = 'verification_status_changed'
         | 
| 14 14 |  | 
| 15 | 
            -
                  EVENT_NAMES = [CONTRACT_PUBLISHED, CONTRACT_CONTENT_CHANGED, VERIFICATION_PUBLISHED]
         | 
| 15 | 
            +
                  EVENT_NAMES = [CONTRACT_PUBLISHED, CONTRACT_CONTENT_CHANGED, VERIFICATION_PUBLISHED, VERIFICATION_FAILED]
         | 
| 16 16 |  | 
| 17 17 | 
             
                  dataset_module do
         | 
| 18 18 | 
             
                    include PactBroker::Repositories::Helpers
         | 
| @@ -30,6 +30,13 @@ module PactBroker | |
| 30 30 | 
             
                    name == VERIFICATION_PUBLISHED
         | 
| 31 31 | 
             
                  end
         | 
| 32 32 |  | 
| 33 | 
            +
                  def provider_verification_succeeded?
         | 
| 34 | 
            +
                    name == VERIFICATION_SUCCEEDED
         | 
| 35 | 
            +
                  end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  def provider_verification_failed?
         | 
| 38 | 
            +
                    name == VERIFICATION_FAILED
         | 
| 39 | 
            +
                  end
         | 
| 33 40 | 
             
                end
         | 
| 34 41 |  | 
| 35 42 | 
             
                WebhookEvent.plugin :timestamps, update_on_create: true
         | 
    
        data/script/seed.rb
    CHANGED
    
    | @@ -42,9 +42,17 @@ webhook_body = { | |
| 42 42 | 
             
              'githubVerificationStatus' => '${pactbroker.githubVerificationStatus}'
         | 
| 43 43 | 
             
            }
         | 
| 44 44 |  | 
| 45 | 
            +
              # .create_global_webhook(
         | 
| 46 | 
            +
              #   method: 'POST',
         | 
| 47 | 
            +
              #   url: "http://localhost:9292/pact-changed-webhook",
         | 
| 48 | 
            +
              #   body: webhook_body.to_json,
         | 
| 49 | 
            +
              #   username: "foo",
         | 
| 50 | 
            +
              #   password: "bar")
         | 
| 45 51 | 
             
            TestDataBuilder.new
         | 
| 46 | 
            -
              . | 
| 47 | 
            -
             | 
| 52 | 
            +
              .create_global_verification_succeeded_webhook(
         | 
| 53 | 
            +
                method: 'POST',
         | 
| 54 | 
            +
                url: "http://localhost:9292/verification-published-webhook",
         | 
| 55 | 
            +
                body: webhook_body.to_json)
         | 
| 48 56 | 
             
              # .create_certificate(path: 'spec/fixtures/certificates/self-signed.badssl.com.pem')
         | 
| 49 57 | 
             
              # .create_consumer("Bethtest")
         | 
| 50 58 | 
             
              # .create_verification_webhook(method: 'GET', url: "http://localhost:9292", body: webhook_body, username: "foo", password: "bar", headers: {"Accept" => "application/json"})
         | 
| @@ -1,4 +1,10 @@ | |
| 1 1 | 
             
            RSpec.describe "the lifecycle of a WIP pact" do
         | 
| 2 | 
            +
              before do
         | 
| 3 | 
            +
                td.set_now(DateTime.now - 100)
         | 
| 4 | 
            +
                  .create_provider("Bar")
         | 
| 5 | 
            +
                  .create_provider_version("1")
         | 
| 6 | 
            +
                  .create_provider_version_tag("master")
         | 
| 7 | 
            +
              end
         | 
| 2 8 | 
             
              let(:pact_content_1) { { interactions: [{ some: 'interaction'}] }.to_json }
         | 
| 3 9 | 
             
              let(:pact_content_2) { { interactions: [{ some: 'other interaction'}] }.to_json }
         | 
| 4 10 | 
             
              let(:request_headers) { { "CONTENT_TYPE" => "application/json", "HTTP_ACCEPT" => "application/hal+json"} }
         | 
| @@ -122,7 +128,6 @@ RSpec.describe "the lifecycle of a WIP pact" do | |
| 122 128 | 
             
                      verification_results_url = verification_results_url_from(pact_response)
         | 
| 123 129 | 
             
                      publish_verification_results_with_tag_master(verification_results_url, successful_verification_results)
         | 
| 124 130 |  | 
| 125 | 
            -
             | 
| 126 131 | 
             
                      # ANOTHER PROVIDER BUILD 2
         | 
| 127 132 | 
             
                      # get pacts for verification
         | 
| 128 133 | 
             
                      # publish successful verification results
         | 
| @@ -131,8 +136,6 @@ RSpec.describe "the lifecycle of a WIP pact" do | |
| 131 136 | 
             
                      expect(wip_pacts_from(pacts_for_verification_response).size).to eq 0
         | 
| 132 137 | 
             
                    end
         | 
| 133 138 | 
             
                  end
         | 
| 134 | 
            -
             | 
| 135 | 
            -
              end
         | 
| 136 | 
            -
             | 
| 139 | 
            +
                end
         | 
| 137 140 | 
             
              end
         | 
| 138 141 | 
             
            end
         | 
| @@ -6,15 +6,23 @@ module PactBroker | |
| 6 6 | 
             
                  describe VerifiablePactDecorator do
         | 
| 7 7 | 
             
                    before do
         | 
| 8 8 | 
             
                      allow(decorator).to receive(:pact_version_url).and_return('/pact-version-url')
         | 
| 9 | 
            -
                      allow_any_instance_of(PactBroker::Pacts::VerifiablePactMessages).to receive(:inclusion_reason).and_return(" | 
| 10 | 
            -
                      allow_any_instance_of(PactBroker::Pacts::VerifiablePactMessages).to receive(:pending_reason).and_return( | 
| 9 | 
            +
                      allow_any_instance_of(PactBroker::Pacts::VerifiablePactMessages).to receive(:inclusion_reason).and_return("the inclusion reason")
         | 
| 10 | 
            +
                      allow_any_instance_of(PactBroker::Pacts::VerifiablePactMessages).to receive(:pending_reason).and_return(pending_reason)
         | 
| 11 11 | 
             
                    end
         | 
| 12 | 
            +
                    let(:pending_reason) { "the pending reason" }
         | 
| 12 13 | 
             
                    let(:expected_hash) do
         | 
| 13 14 | 
             
                      {
         | 
| 14 15 | 
             
                        "verificationProperties" => {
         | 
| 15 16 | 
             
                          "pending" => true,
         | 
| 16 | 
            -
                          " | 
| 17 | 
            -
             | 
| 17 | 
            +
                          "notices" => [
         | 
| 18 | 
            +
                            {
         | 
| 19 | 
            +
                              "text" => "the inclusion reason"
         | 
| 20 | 
            +
                            }, {
         | 
| 21 | 
            +
                              "text" => pending_reason
         | 
| 22 | 
            +
                            }
         | 
| 23 | 
            +
                          ],
         | 
| 24 | 
            +
                          "pendingReason" => pending_reason,
         | 
| 25 | 
            +
                          "inclusionReason" => "the inclusion reason"
         | 
| 18 26 | 
             
                        },
         | 
| 19 27 | 
             
                        "_links" => {
         | 
| 20 28 | 
             
                          "self" => {
         | 
| @@ -55,6 +63,7 @@ module PactBroker | |
| 55 63 |  | 
| 56 64 | 
             
                    context "when include_pending_status is false" do
         | 
| 57 65 | 
             
                      let(:include_pending_status) { false }
         | 
| 66 | 
            +
                      let(:notices) { subject['verificationProperties']['notices'].collect{ | notice | notice['text'] } }
         | 
| 58 67 |  | 
| 59 68 | 
             
                      it "does not include the pending flag" do
         | 
| 60 69 | 
             
                        expect(subject['verificationProperties']).to_not have_key('pending')
         | 
| @@ -62,6 +71,7 @@ module PactBroker | |
| 62 71 |  | 
| 63 72 | 
             
                      it "does not include the pending reason" do
         | 
| 64 73 | 
             
                        expect(subject['verificationProperties']).to_not have_key('pendingReason')
         | 
| 74 | 
            +
                        expect(notices).to_not include(pending_reason)
         | 
| 65 75 | 
             
                      end
         | 
| 66 76 | 
             
                    end
         | 
| 67 77 |  | 
| @@ -39,7 +39,13 @@ module PactBroker | |
| 39 39 |  | 
| 40 40 | 
             
                    context "when the latest pact for a tag has been successfully verified by one of the given provider tags, but not the other" do
         | 
| 41 41 | 
             
                      before do
         | 
| 42 | 
            -
                        td. | 
| 42 | 
            +
                        td.create_provider("bar")
         | 
| 43 | 
            +
                          .create_provider_version("44")
         | 
| 44 | 
            +
                          .create_provider_version_tag("feat-1")
         | 
| 45 | 
            +
                          .add_day
         | 
| 46 | 
            +
                          .create_consumer("foo")
         | 
| 47 | 
            +
                          .create_consumer_version("1")
         | 
| 48 | 
            +
                          .create_pact
         | 
| 43 49 | 
             
                          .create_consumer_version_tag("prod")
         | 
| 44 50 | 
             
                          .create_verification(provider_version: "3", tag_names: %w[dev], comment: "not included because already verified")
         | 
| 45 51 | 
             
                      end
         | 
| @@ -57,7 +63,11 @@ module PactBroker | |
| 57 63 |  | 
| 58 64 | 
             
                    context "when the latest pact for a tag has failed verification from the specified provider version" do
         | 
| 59 65 | 
             
                      before do
         | 
| 60 | 
            -
                        td. | 
| 66 | 
            +
                        td.create_provider("bar")
         | 
| 67 | 
            +
                          .create_provider_version("333")
         | 
| 68 | 
            +
                          .create_provider_version_tag("dev")
         | 
| 69 | 
            +
                          .add_day
         | 
| 70 | 
            +
                          .create_pact_with_hierarchy("foo", "1", "bar")
         | 
| 61 71 | 
             
                          .create_consumer_version_tag("feat-1")
         | 
| 62 72 | 
             
                          .create_verification(provider_version: "3", success: false, tag_names: %[dev])
         | 
| 63 73 | 
             
                      end
         | 
| @@ -84,7 +94,11 @@ module PactBroker | |
| 84 94 |  | 
| 85 95 | 
             
                    context "when the latest pact for a tag has successful and failed verifications" do
         | 
| 86 96 | 
             
                      before do
         | 
| 87 | 
            -
                        td. | 
| 97 | 
            +
                        td.create_provider("bar")
         | 
| 98 | 
            +
                          .create_provider_version("333")
         | 
| 99 | 
            +
                          .create_provider_version_tag("dev")
         | 
| 100 | 
            +
                          .add_day
         | 
| 101 | 
            +
                          .create_pact_with_hierarchy("foo", "1", "bar")
         | 
| 88 102 | 
             
                          .create_consumer_version_tag("dev")
         | 
| 89 103 | 
             
                          .create_verification(provider_version: "3", success: true, tag_names: %[dev])
         | 
| 90 104 | 
             
                          .create_verification(provider_version: "5", success: false, number: 2, tag_names: %[dev])
         | 
| @@ -97,8 +111,12 @@ module PactBroker | |
| 97 111 |  | 
| 98 112 | 
             
                    context "when the latest pact for a tag has not been verified" do
         | 
| 99 113 | 
             
                      before do
         | 
| 100 | 
            -
                        td. | 
| 101 | 
            -
                          . | 
| 114 | 
            +
                        td.create_provider("bar")
         | 
| 115 | 
            +
                          .create_provider_version("333")
         | 
| 116 | 
            +
                          .create_provider_version_tag("dev")
         | 
| 117 | 
            +
                          .add_day
         | 
| 118 | 
            +
                          .create_pact_with_hierarchy("foo", "1", "bar")
         | 
| 119 | 
            +
                          .create_consumer_version_tag("feat-1")
         | 
| 102 120 | 
             
                      end
         | 
| 103 121 |  | 
| 104 122 | 
             
                      it "is included" do
         | 
| @@ -123,7 +141,11 @@ module PactBroker | |
| 123 141 |  | 
| 124 142 | 
             
                    context "when the pact was published before the specified include_wip_pacts_since" do
         | 
| 125 143 | 
             
                      before do
         | 
| 126 | 
            -
                        td. | 
| 144 | 
            +
                        td.create_provider("bar")
         | 
| 145 | 
            +
                          .create_provider_version("333")
         | 
| 146 | 
            +
                          .create_provider_version_tag("dev")
         | 
| 147 | 
            +
                          .add_day
         | 
| 148 | 
            +
                          .create_pact_with_hierarchy("foo", "1", "bar")
         | 
| 127 149 | 
             
                          .create_consumer_version_tag("prod")
         | 
| 128 150 | 
             
                      end
         | 
| 129 151 |  | 
| @@ -133,6 +155,51 @@ module PactBroker | |
| 133 155 | 
             
                        expect(subject.size).to be 0
         | 
| 134 156 | 
             
                      end
         | 
| 135 157 | 
             
                    end
         | 
| 158 | 
            +
             | 
| 159 | 
            +
                    context "when the first provider tag with a given name was created after the head pact was created" do
         | 
| 160 | 
            +
                      before do
         | 
| 161 | 
            +
                        td.create_pact_with_hierarchy("foo", "1", "bar")
         | 
| 162 | 
            +
                          .create_consumer_version_tag("feat-x")
         | 
| 163 | 
            +
                          .add_day
         | 
| 164 | 
            +
                          .create_provider_version("5")
         | 
| 165 | 
            +
                          .create_provider_version_tag(provider_tags.first)
         | 
| 166 | 
            +
                      end
         | 
| 167 | 
            +
             | 
| 168 | 
            +
                      it "doesn't return any pacts" do
         | 
| 169 | 
            +
                        expect(subject.size).to be 0
         | 
| 170 | 
            +
                      end
         | 
| 171 | 
            +
                    end
         | 
| 172 | 
            +
             | 
| 173 | 
            +
                    context "when the provider tag does not exist yet" do
         | 
| 174 | 
            +
                      before do
         | 
| 175 | 
            +
                        td.create_pact_with_hierarchy("foo", "1", "bar")
         | 
| 176 | 
            +
                          .create_consumer_version_tag("feat-x")
         | 
| 177 | 
            +
                      end
         | 
| 178 | 
            +
             | 
| 179 | 
            +
                      it "doesn't return any pacts" do
         | 
| 180 | 
            +
                        expect(subject.size).to be 0
         | 
| 181 | 
            +
                      end
         | 
| 182 | 
            +
                    end
         | 
| 183 | 
            +
             | 
| 184 | 
            +
                    context "when a pact was published between the first creation date of two provider tags" do
         | 
| 185 | 
            +
                      let(:provider_tags) { %w[dev feat-1] }
         | 
| 186 | 
            +
             | 
| 187 | 
            +
                      before do
         | 
| 188 | 
            +
                        td.create_provider("bar")
         | 
| 189 | 
            +
                          .create_provider_version("4")
         | 
| 190 | 
            +
                          .create_provider_version_tag(provider_tags.first)
         | 
| 191 | 
            +
                          .add_day
         | 
| 192 | 
            +
                          .create_pact_with_hierarchy("foo", "1", "bar")
         | 
| 193 | 
            +
                          .create_consumer_version_tag("feat-x")
         | 
| 194 | 
            +
                          .add_day
         | 
| 195 | 
            +
                          .create_provider_version("5")
         | 
| 196 | 
            +
                          .create_provider_version_tag(provider_tags.last)
         | 
| 197 | 
            +
                      end
         | 
| 198 | 
            +
             | 
| 199 | 
            +
                      it "is wip for the first tag but not the second" do
         | 
| 200 | 
            +
                        expect(subject.first.pending_provider_tags).to eq [provider_tags.first]
         | 
| 201 | 
            +
                      end
         | 
| 202 | 
            +
                    end
         | 
| 136 203 | 
             
                  end
         | 
| 137 204 | 
             
                end
         | 
| 138 205 | 
             
              end
         | 
| @@ -158,7 +158,11 @@ module PactBroker | |
| 158 158 |  | 
| 159 159 | 
             
                  describe "find_for_verification integration test" do
         | 
| 160 160 | 
             
                    before do
         | 
| 161 | 
            -
                      td. | 
| 161 | 
            +
                      td.create_provider("Bar")
         | 
| 162 | 
            +
                        .create_provider_version
         | 
| 163 | 
            +
                        .create_provider_version_tag("master")
         | 
| 164 | 
            +
                        .add_minute
         | 
| 165 | 
            +
                        .create_pact_with_hierarchy("Foo", "1", "Bar")
         | 
| 162 166 | 
             
                        .create_consumer_version_tag("feat-1", comment: "latest for feat-1")
         | 
| 163 167 | 
             
                        .create_consumer_version("2")
         | 
| 164 168 | 
             
                        .create_pact(comment: "overall latest")
         | 
| @@ -189,6 +193,7 @@ module PactBroker | |
| 189 193 | 
             
                          include_wip_pacts_since: (Date.today - 1).to_datetime
         | 
| 190 194 | 
             
                        }
         | 
| 191 195 | 
             
                      end
         | 
| 196 | 
            +
             | 
| 192 197 | 
             
                      it "returns the WIP pacts as well as the specified pacts" do
         | 
| 193 198 | 
             
                        expect(subject.size).to eq 2
         | 
| 194 199 | 
             
                        expect(subject.last.consumer_version_number).to eq "1"
         | 
| @@ -1,6 +1,7 @@ | |
| 1 1 | 
             
            require 'pact_broker/verifications/service'
         | 
| 2 2 | 
             
            require 'pact_broker/verifications/repository'
         | 
| 3 3 | 
             
            require 'pact_broker/webhooks/execution_configuration'
         | 
| 4 | 
            +
            require 'pact_broker/webhooks/trigger_service'
         | 
| 4 5 |  | 
| 5 6 | 
             
            module PactBroker
         | 
| 6 7 |  | 
| @@ -16,7 +17,7 @@ module PactBroker | |
| 16 17 |  | 
| 17 18 | 
             
                  describe "#create" do
         | 
| 18 19 | 
             
                    before do
         | 
| 19 | 
            -
                      allow(PactBroker::Webhooks:: | 
| 20 | 
            +
                      allow(PactBroker::Webhooks::TriggerService).to receive(:trigger_webhooks_for_verification_results_publication)
         | 
| 20 21 | 
             
                      allow(webhook_execution_configuration).to receive(:with_webhook_context).and_return(webhook_execution_configuration)
         | 
| 21 22 | 
             
                    end
         | 
| 22 23 |  | 
| @@ -61,10 +62,9 @@ module PactBroker | |
| 61 62 |  | 
| 62 63 | 
             
                    it "invokes the webhooks for the verification" do
         | 
| 63 64 | 
             
                      verification = create_verification
         | 
| 64 | 
            -
                      expect(PactBroker::Webhooks:: | 
| 65 | 
            +
                      expect(PactBroker::Webhooks::TriggerService).to have_received(:trigger_webhooks_for_verification_results_publication).with(
         | 
| 65 66 | 
             
                        pact,
         | 
| 66 67 | 
             
                        verification,
         | 
| 67 | 
            -
                        PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED,
         | 
| 68 68 | 
             
                        options
         | 
| 69 69 | 
             
                      )
         | 
| 70 70 | 
             
                    end
         | 
| @@ -136,6 +136,39 @@ module PactBroker | |
| 136 136 | 
             
                      include_examples "not triggering a contract_content_changed event"
         | 
| 137 137 | 
             
                    end
         | 
| 138 138 | 
             
                  end
         | 
| 139 | 
            +
             | 
| 140 | 
            +
                  describe "#trigger_webhooks_for_verification_results_publication" do
         | 
| 141 | 
            +
                    let(:verification) { double("verification", success: success) }
         | 
| 142 | 
            +
                    let(:success) { true }
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                    subject { TriggerService.trigger_webhooks_for_verification_results_publication(pact, verification, webhook_options) }
         | 
| 145 | 
            +
             | 
| 146 | 
            +
                    context "when the verification is successful" do
         | 
| 147 | 
            +
                      it "triggers a provider_verification_succeeded webhook" do
         | 
| 148 | 
            +
                        expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_SUCCEEDED, webhook_options)
         | 
| 149 | 
            +
                        subject
         | 
| 150 | 
            +
                      end
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                      it "triggers a provider_verification_published webhook" do
         | 
| 153 | 
            +
                        expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED, webhook_options)
         | 
| 154 | 
            +
                        subject
         | 
| 155 | 
            +
                      end
         | 
| 156 | 
            +
                    end
         | 
| 157 | 
            +
             | 
| 158 | 
            +
                    context "when the verification is not successful" do
         | 
| 159 | 
            +
                      let(:success) { false }
         | 
| 160 | 
            +
             | 
| 161 | 
            +
                      it "triggers a provider_verification_failed webhook" do
         | 
| 162 | 
            +
                        expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_FAILED, webhook_options)
         | 
| 163 | 
            +
                        subject
         | 
| 164 | 
            +
                      end
         | 
| 165 | 
            +
             | 
| 166 | 
            +
                      it "triggeres a provider_verification_published webhook" do
         | 
| 167 | 
            +
                        expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED, webhook_options)
         | 
| 168 | 
            +
                        subject
         | 
| 169 | 
            +
                      end
         | 
| 170 | 
            +
                    end
         | 
| 171 | 
            +
                  end
         | 
| 139 172 | 
             
                end
         | 
| 140 173 | 
             
              end
         | 
| 141 174 | 
             
            end
         | 
    
        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.42.0
         | 
| 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: 2019-12- | 
| 13 | 
            +
            date: 2019-12-05 00:00:00.000000000 Z
         | 
| 14 14 | 
             
            dependencies:
         | 
| 15 15 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 16 16 | 
             
              name: httparty
         |