Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,24 @@ jobs:
env:
PACTFLOW_PACT_FOUNDATION_TOKEN: ${{ secrets.PACTFLOW_PACT_FOUNDATION_TOKEN }}

pact-v2-verify:
runs-on: "ubuntu-latest"
strategy:
matrix:
pact_url:
- "https://raw.githubusercontent.com/pact-foundation/pact_broker-client/refs/heads/master/spec/pacts/Pact%20Broker%20Client%20V2-Pact%20Broker.json"
- "https://raw.githubusercontent.com/pact-foundation/pact_broker-client/refs/heads/master/spec/pacts/pact_broker_client-pact_broker.json"
steps:
- uses: actions/checkout@v4
- uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- run: bundle install
- name: Verify pacts
env:
PACT_URL: ${{ matrix.pact_url }}
run: "PACT_URL=${PACT_URL} bundle exec rake pact:v2:verify"

bundle-audit:
runs-on: "ubuntu-latest"
steps:
Expand Down
8 changes: 7 additions & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,13 @@ end

group :test do
gem "simplecov", :require => false
gem "pact", "~>1.14"
if ENV["X_PACT_DEVELOPMENT"] == "true"
gem "pact", path: "../pact-ruby"
gem "pact-ffi", path: "../pact-ruby-ffi"
else
gem "pact", "~>1.14"
gem "pact-ffi", "~>0.4.28"
end
gem "rspec-pact-matchers", "~>0.1"
gem "bundler-audit", "~>0.4"
gem "webmock", "~>3.9"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"status": 200,
"headers": {
"content-type": "application/hal+json;charset=utf-8",
"content-length": "840",
"content-length": "842",
"date": "<date>",
"server": "Webmachine-Ruby/2.0.1 Rack/3.2"
},
Expand All @@ -41,7 +41,7 @@
},
"_links": {
"self": {
"href": "http://example.org/pacts/provider/Provider/consumer/Consumer%202/pact-version/0f22f551a422b027066db7635cad8bd8a59ac869/metadata/cyU1QiU1RCU1QnQlNUQ9cHJvZCZzJTVCJTVEJTVCbCU1RD10cnVlJnMlNUIlNUQlNUJjdiU1RD0y",
"href": "http://example.org/pacts/provider/Provider/consumer/Consumer%202/pact-version/0f22f551a422b027066db7635cad8bd8a59ac869/metadata/cyU1QiU1RCU1QnQlNUQ9cHJvZCZzJTVCJTVEJTVCbCU1RD10cnVlJnMlNUIlNUQlNUJjdiU1RD0xMA",
"name": "Pact between Consumer 2 (4.5.6) and Provider"
}
}
Expand Down
98 changes: 98 additions & 0 deletions spec/pact/consumers/http_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# frozen_string_literal: true

require "pact_broker"
require "pact_broker/app"
require "rspec/mocks"
include RSpec::Mocks::ExampleMethods
require_relative "../../service_consumers/hal_relation_proxy_app"

PactBroker.configuration.base_urls = ["http://example.org"]

pact_broker = PactBroker::App.new { |c| c.database_connection = PactBroker::TestDatabase.connection_for_test_database }
app_to_verify = HalRelationProxyApp.new(pact_broker)

require "pact"
require "pact/v2/rspec"
require_relative "../../service_consumers/shared_provider_states"
RSpec.describe "Verify consumers for Pact Broker", :pact_v2 do

http_pact_provider "Pact Broker", opts: {

# rails apps should be automatically detected
# if you need to configure your own app, you can do so here

app: app_to_verify,
# start rackup with a different port. Useful if you already have something
# running on the default port *9292*
http_port: 9393,

# Set the log level, default is :info

log_level: :info,
logger: Logger.new(File.expand_path("../../../pact_verification.log", __dir__)),

fail_if_no_pacts_found: true,

# Pact Sources

# 1. Local pacts from a directory

# Default is pacts directory in the current working directory
# pact_dir: File.expand_path('../../../../consumer/spec/internal/pacts', __dir__),

# 2. Broker based pacts

# Broker credentials

# broker_username: "pact_workshop", # can be set via PACT_BROKER_USERNAME env var
# broker_password: "pact_workshop", # can be set via PACT_BROKER_PASSWORD env var
# broker_token: "pact_workshop", # can be set via PACT_BROKER_TOKEN env var

# Remote pact via a uri, traditionally triggered via webhooks
# when a pact that requires verification is published

# 2a. Webhook triggered pacts
# Can be a local file or a remote URL
# Most used via webhooks
# Can be set via PACT_URL env var
# pact_uri: File.expand_path("../../../pacts/pact.json", __dir__),
pact_uri: "https://raw.githubusercontent.com/pact-foundation/pact_broker-client/refs/heads/master/spec/pacts/Pact%20Broker%20Client%20V2-Pact%20Broker.json",

# 2b. Dynamically fetched pacts from broker

# i. Set the broker url
# broker_url: "http://localhost:9292", # can be set via PACT_BROKER_URL env var

# ii. Set the consumer version selectors
# Consumer version selectors
# The pact broker will return the following pacts by default, if no selectors are specified
# For the recommended setup, you dont _actually_ need to specify these selectors in ruby
# consumer_version_selectors: [{"deployedOrReleased" => true},{"mainBranch" => true},{"matchingBranch" => true}],

# iii. Set additional dynamic selection verification options
# additional dynamic selection verification options
enable_pending: true,
include_wip_pacts_since: "2021-01-01",

# Publish verification results to the broker
publish_verification_results: ENV["PACT_PUBLISH_VERIFICATION_RESULTS"] == "true",
provider_version: `git rev-parse HEAD`.strip,
provider_version_branch: `git rev-parse --abbrev-ref HEAD`.strip,
provider_version_tags: [`git rev-parse --abbrev-ref HEAD`.strip],
# provider_build_uri: "YOUR CI URL HERE - must be a valid url",

}

before_state_setup do
PactBroker::TestDatabase.truncate
end

after_state_teardown do
PactBroker::TestDatabase.truncate
end

shared_provider_states

end


60 changes: 60 additions & 0 deletions spec/service_consumers/hal_relation_proxy_app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,72 @@ class HalRelationProxyApp
RESPONSE_BODY_REPLACEMENTS = {
}

# query strings sent from the v2 ruby pact, is re-ordered by the rust app?
# so we need to re-order them here to match the expected query string
# PASS
# curl 'localhost:9292/matrix?ignore%5B%5D%5Bpacticipant%5D=Foo&ignore%5B%5D%5Bversion%5D=3.4.5&latestby=cvpv&q%5B%5D%5Bpacticipant%5D=Bar&q%5B%5D%5Bversion%5D=4.5.6&q%5B%5D%5Bpacticipant%5D=Foo&q%5B%5D%5Btag%5D=prod' | jq .
# FAIL
# curl 'localhost:9292/matrix?ignore%5B%5D%5Bpacticipant%5D=Foo&ignore%5B%5D%5Bversion%5D=3.4.5&latestby=cvpv&q%5B%5D%5Bpacticipant%5D=Bar&q%5B%5D%5Bpacticipant%5D=Foo&q%5B%5D%5Btag%5D=prod&q%5B%5D%5Bversion%5D=4.5.6' | jq .
QUERY_STRING_REPLACEMENTS = {
# pact-ruby-v2 pact (as v2) verified by pact-ruby-v2
"ignore%5B%5D%5Bpacticipant%5D=Foo&ignore%5B%5D%5Bversion%5D=3.4.5&latestby=cvpv&q%5B%5D%5Bpacticipant%5D=Bar&q%5B%5D%5Bpacticipant%5D=Foo&q%5B%5D%5Btag%5D=prod&q%5B%5D%5Bversion%5D=4.5.6" =>
"q%5B%5D%5Bpacticipant%5D=Bar&q%5B%5D%5Bversion%5D=4.5.6&q%5B%5D%5Bpacticipant%5D=Foo&q%5B%5D%5Btag%5D=prod&latestby=cvpv&ignore%5B%5D%5Bpacticipant%5D=Foo&ignore%5B%5D%5Bversion%5D=3.4.5",
# pact-ruby-v2 pact (as v2) verified by pact-ruby-v1
"ignore[][pacticipant]=Foo&ignore[][version]=3%2e4%2e5&latestby=cvpv&q[][pacticipant]=Bar&q[][pacticipant]=Foo&q[][tag]=prod&q[][version]=4%2e5%2e6" =>
"q%5B%5D%5Bpacticipant%5D=Bar&q%5B%5D%5Bversion%5D=4.5.6&q%5B%5D%5Bpacticipant%5D=Foo&q%5B%5D%5Btag%5D=prod&latestby=cvpv&ignore%5B%5D%5Bpacticipant%5D=Foo&ignore%5B%5D%5Bversion%5D=3.4.5",

# pact-ruby-v2 pact (as v2) verified by pact-ruby-v2
"latestby=cvpv&q%5B%5D%5Bpacticipant%5D=Foo&q%5B%5D%5Bpacticipant%5D=Bar&q%5B%5D%5Bversion%5D=1.2.3&q%5B%5D%5Bversion%5D=4.5.6" =>
"q%5B%5D%5Bpacticipant%5D=Foo&q%5B%5D%5Bversion%5D=1.2.3&q%5B%5D%5Bpacticipant%5D=Bar&q%5B%5D%5Bversion%5D=4.5.6&latestby=cvpv",
# pact-ruby-v2 pact (as v2) verified by pact-ruby-v1
"latestby=cvpv&q[][pacticipant]=Foo&q[][pacticipant]=Bar&q[][version]=1%2e2%2e3&q[][version]=4%2e5%2e6" =>
"q%5B%5D%5Bpacticipant%5D=Foo&q%5B%5D%5Bversion%5D=1.2.3&q%5B%5D%5Bpacticipant%5D=Bar&q%5B%5D%5Bversion%5D=4.5.6&latestby=cvpv",

# pact-ruby-v2 pact (as v2) verified by pact-ruby-v2
"latestby=cvpv&q%5B%5D%5Bpacticipant%5D=Foo+Thing&q%5B%5D%5Bpacticipant%5D=Bar&q%5B%5D%5Bversion%5D=1.2.3&q%5B%5D%5Bversion%5D=4.5.6" =>
"q%5B%5D%5Bpacticipant%5D=Foo%20Thing&q%5B%5D%5Bversion%5D=1.2.3&q%5B%5D%5Bpacticipant%5D=Bar&q%5B%5D%5Bversion%5D=4.5.6&latestby=cvpv",
# pact-ruby-v2 pact (as v2) verified by pact-ruby-v1
"latestby=cvpv&q[][pacticipant]=Foo+Thing&q[][pacticipant]=Bar&q[][version]=1%2e2%2e3&q[][version]=4%2e5%2e6" =>
"q%5B%5D%5Bpacticipant%5D=Foo%20Thing&q%5B%5D%5Bversion%5D=1.2.3&q%5B%5D%5Bpacticipant%5D=Bar&q%5B%5D%5Bversion%5D=4.5.6&latestby=cvpv",

# pact-ruby-v2 pact (as v2) verified by pact-ruby-v2
"latestby=cvpv&q%5B%5D%5Bpacticipant%5D=Foo&q%5B%5D%5Bpacticipant%5D=Bar&q%5B%5D%5Bversion%5D=1.2.3&q%5B%5D%5Bversion%5D=9.9.9" =>
"q%5B%5D%5Bpacticipant%5D=Foo&q%5B%5D%5Bversion%5D=1.2.3&q%5B%5D%5Bpacticipant%5D=Bar&q%5B%5D%5Bversion%5D=9.9.9&latestby=cvpv",
# pact-ruby-v2 pact (as v2) verified by pact-ruby-v1
"latestby=cvpv&q[][pacticipant]=Foo&q[][pacticipant]=Bar&q[][version]=1%2e2%2e3&q[][version]=9%2e9%2e9" =>
"q%5B%5D%5Bpacticipant%5D=Foo&q%5B%5D%5Bversion%5D=1.2.3&q%5B%5D%5Bpacticipant%5D=Bar&q%5B%5D%5Bversion%5D=9.9.9&latestby=cvpv",

# pact-ruby-v2 pact (as v2) verified by pact-ruby-v2
"latestby=cvpv&q%5B%5D%5Blatest%5D=true&q%5B%5D%5Bpacticipant%5D=Foo&q%5B%5D%5Bpacticipant%5D=Bar&q%5B%5D%5Btag%5D=prod&q%5B%5D%5Bversion%5D=1.2.3" =>
"q%5B%5D%5Bpacticipant%5D=Foo&q%5B%5D%5Bversion%5D=1.2.3&q%5B%5D%5Bpacticipant%5D=Bar&q%5B%5D%5Blatest%5D=true&q%5B%5D%5Btag%5D=prod&latestby=cvpv",
# pact-ruby-v2 pact (as v2) verified by pact-ruby-v1
"latestby=cvpv&q[][latest]=true&q[][pacticipant]=Foo&q[][pacticipant]=Bar&q[][tag]=prod&q[][version]=1%2e2%2e3" =>
"q%5B%5D%5Bpacticipant%5D=Foo&q%5B%5D%5Bversion%5D=1.2.3&q%5B%5D%5Bpacticipant%5D=Bar&q%5B%5D%5Blatest%5D=true&q%5B%5D%5Btag%5D=prod&latestby=cvpv",

# pact-ruby-v2 pact (as v2) verified by pact-ruby-v2
"latestby=cvpv&q%5B%5D%5Blatest%5D=true&q%5B%5D%5Bpacticipant%5D=Foo&q%5B%5D%5Bpacticipant%5D=Bar&q%5B%5D%5Bversion%5D=1.2.4" =>
"q%5B%5D%5Bpacticipant%5D=Foo&q%5B%5D%5Bversion%5D=1.2.4&q%5B%5D%5Bpacticipant%5D=Bar&q%5B%5D%5Blatest%5D=true&latestby=cvpv",
# pact-ruby-v2 pact (as v2) verified by pact-ruby-v1
"latestby=cvpv&q[][latest]=true&q[][pacticipant]=Foo&q[][pacticipant]=Bar&q[][version]=1%2e2%2e4" =>
"q%5B%5D%5Bpacticipant%5D=Foo&q%5B%5D%5Bversion%5D=1.2.4&q%5B%5D%5Bpacticipant%5D=Bar&q%5B%5D%5Blatest%5D=true&latestby=cvpv",
}

def initialize(app)
@app = app
end

def call env
original_path = env["PATH_INFO"]
original_query = env["QUERY_STRING"]

QUERY_STRING_REPLACEMENTS.each do | (find, replace) |
env["QUERY_STRING"] = env["QUERY_STRING"].gsub(find, replace)
end

if env["QUERY_STRING"] != original_query
puts "Modified query string: #{env["QUERY_STRING"]}"
end

env_with_modified_path = env
PATH_REPLACEMENTS.each do | (find, replace) |
env_with_modified_path["PATH_INFO"] = env_with_modified_path["PATH_INFO"].gsub(find, replace)
Expand Down
2 changes: 1 addition & 1 deletion spec/service_consumers/pact_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,6 @@ def do_not_rollback? _response
end

honours_pact_with "Pact Broker Client" do
pact_uri "https://raw.githubusercontent.com/pact-foundation/pact_broker-client/master/spec/pacts/pact_broker_client-pact_broker.json"
pact_uri "https://raw.githubusercontent.com/pact-foundation/pact_broker-client/refs/heads/master/spec/pacts/Pact%20Broker%20Client%20V2-Pact%20Broker.json"
end
end
Loading