Skip to content

Commit 68ea40f

Browse files
committed
chore(test): use pact ruby v2 (rust core) to verify pacts, alongside ruby core
1 parent 33bb018 commit 68ea40f

File tree

11 files changed

+605
-388
lines changed

11 files changed

+605
-388
lines changed

.github/workflows/test.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,24 @@ jobs:
112112
env:
113113
PACTFLOW_PACT_FOUNDATION_TOKEN: ${{ secrets.PACTFLOW_PACT_FOUNDATION_TOKEN }}
114114

115+
pact-v2-verify:
116+
runs-on: "ubuntu-latest"
117+
strategy:
118+
matrix:
119+
pact_url:
120+
- "https://raw.githubusercontent.com/pact-foundation/pact_broker-client/refs/heads/master/spec/pacts/Pact%20Broker%20Client%20V2-Pact%20Broker.json"
121+
- "https://raw.githubusercontent.com/pact-foundation/pact_broker-client/refs/heads/master/spec/pacts/pact_broker_client-pact_broker.json"
122+
steps:
123+
- uses: actions/checkout@v4
124+
- uses: ruby/setup-ruby@v1
125+
with:
126+
bundler-cache: true
127+
- run: bundle install
128+
- name: Verify pacts
129+
env:
130+
PACT_URL: ${{ matrix.pact_url }}
131+
run: "PACT_URL=${PACT_URL} bundle exec rake pact:v2:verify"
132+
115133
bundle-audit:
116134
runs-on: "ubuntu-latest"
117135
steps:

Gemfile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,13 @@ end
2121

2222
group :test do
2323
gem "simplecov", :require => false
24-
gem "pact", "~>1.14"
24+
if ENV["X_PACT_DEVELOPMENT"] == "true"
25+
gem "pact", path: "../pact-ruby"
26+
gem "pact-ffi", path: "../pact-ruby-ffi"
27+
else
28+
gem "pact", "~>1.14"
29+
gem "pact-ffi", "~>0.4.28"
30+
end
2531
gem "rspec-pact-matchers", "~>0.1"
2632
gem "bundler-audit", "~>0.4"
2733
gem "webmock", "~>3.9"

spec/pact/consumers/http_spec.rb

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# frozen_string_literal: true
2+
3+
require "pact_broker"
4+
require "pact_broker/app"
5+
require "rspec/mocks"
6+
include RSpec::Mocks::ExampleMethods
7+
require_relative "../../service_consumers/hal_relation_proxy_app"
8+
9+
PactBroker.configuration.base_urls = ["http://example.org"]
10+
11+
pact_broker = PactBroker::App.new { |c| c.database_connection = PactBroker::TestDatabase.connection_for_test_database }
12+
app_to_verify = HalRelationProxyApp.new(pact_broker)
13+
14+
require "pact"
15+
require "pact/v2/rspec"
16+
require_relative "../../service_consumers/shared_provider_states"
17+
RSpec.describe "Verify consumers for Pact Broker", :pact_v2 do
18+
19+
http_pact_provider "Pact Broker", opts: {
20+
21+
# rails apps should be automatically detected
22+
# if you need to configure your own app, you can do so here
23+
24+
app: app_to_verify,
25+
# start rackup with a different port. Useful if you already have something
26+
# running on the default port *9292*
27+
http_port: 9393,
28+
29+
# Set the log level, default is :info
30+
31+
log_level: :info,
32+
logger: Logger.new(File.expand_path("../../../pact_verification.log", __dir__)),
33+
34+
fail_if_no_pacts_found: true,
35+
36+
# Pact Sources
37+
38+
# 1. Local pacts from a directory
39+
40+
# Default is pacts directory in the current working directory
41+
# pact_dir: File.expand_path('../../../../consumer/spec/internal/pacts', __dir__),
42+
43+
# 2. Broker based pacts
44+
45+
# Broker credentials
46+
47+
# broker_username: "pact_workshop", # can be set via PACT_BROKER_USERNAME env var
48+
# broker_password: "pact_workshop", # can be set via PACT_BROKER_PASSWORD env var
49+
# broker_token: "pact_workshop", # can be set via PACT_BROKER_TOKEN env var
50+
51+
# Remote pact via a uri, traditionally triggered via webhooks
52+
# when a pact that requires verification is published
53+
54+
# 2a. Webhook triggered pacts
55+
# Can be a local file or a remote URL
56+
# Most used via webhooks
57+
# Can be set via PACT_URL env var
58+
# pact_uri: File.expand_path("../../../pacts/pact.json", __dir__),
59+
pact_uri: "https://raw.githubusercontent.com/pact-foundation/pact_broker-client/refs/heads/master/spec/pacts/Pact%20Broker%20Client%20V2-Pact%20Broker.json",
60+
61+
# 2b. Dynamically fetched pacts from broker
62+
63+
# i. Set the broker url
64+
# broker_url: "http://localhost:9292", # can be set via PACT_BROKER_URL env var
65+
66+
# ii. Set the consumer version selectors
67+
# Consumer version selectors
68+
# The pact broker will return the following pacts by default, if no selectors are specified
69+
# For the recommended setup, you dont _actually_ need to specify these selectors in ruby
70+
# consumer_version_selectors: [{"deployedOrReleased" => true},{"mainBranch" => true},{"matchingBranch" => true}],
71+
72+
# iii. Set additional dynamic selection verification options
73+
# additional dynamic selection verification options
74+
enable_pending: true,
75+
include_wip_pacts_since: "2021-01-01",
76+
77+
# Publish verification results to the broker
78+
publish_verification_results: ENV["PACT_PUBLISH_VERIFICATION_RESULTS"] == "true",
79+
provider_version: `git rev-parse HEAD`.strip,
80+
provider_version_branch: `git rev-parse --abbrev-ref HEAD`.strip,
81+
provider_version_tags: [`git rev-parse --abbrev-ref HEAD`.strip],
82+
# provider_build_uri: "YOUR CI URL HERE - must be a valid url",
83+
84+
}
85+
86+
before_state_setup do
87+
PactBroker::TestDatabase.truncate
88+
end
89+
90+
after_state_teardown do
91+
PactBroker::TestDatabase.truncate
92+
end
93+
94+
shared_provider_states
95+
96+
end
97+
98+

spec/service_consumers/hal_relation_proxy_app.rb

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,72 @@ class HalRelationProxyApp
3535
RESPONSE_BODY_REPLACEMENTS = {
3636
}
3737

38+
# query strings sent from the v2 ruby pact, is re-ordered by the rust app?
39+
# so we need to re-order them here to match the expected query string
40+
# PASS
41+
# 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 .
42+
# FAIL
43+
# 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 .
44+
QUERY_STRING_REPLACEMENTS = {
45+
# pact-ruby-v2 pact (as v2) verified by pact-ruby-v2
46+
"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" =>
47+
"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",
48+
# pact-ruby-v2 pact (as v2) verified by pact-ruby-v1
49+
"ignore[][pacticipant]=Foo&ignore[][version]=3%2e4%2e5&latestby=cvpv&q[][pacticipant]=Bar&q[][pacticipant]=Foo&q[][tag]=prod&q[][version]=4%2e5%2e6" =>
50+
"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",
51+
52+
# pact-ruby-v2 pact (as v2) verified by pact-ruby-v2
53+
"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" =>
54+
"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",
55+
# pact-ruby-v2 pact (as v2) verified by pact-ruby-v1
56+
"latestby=cvpv&q[][pacticipant]=Foo&q[][pacticipant]=Bar&q[][version]=1%2e2%2e3&q[][version]=4%2e5%2e6" =>
57+
"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",
58+
59+
# pact-ruby-v2 pact (as v2) verified by pact-ruby-v2
60+
"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" =>
61+
"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",
62+
# pact-ruby-v2 pact (as v2) verified by pact-ruby-v1
63+
"latestby=cvpv&q[][pacticipant]=Foo+Thing&q[][pacticipant]=Bar&q[][version]=1%2e2%2e3&q[][version]=4%2e5%2e6" =>
64+
"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",
65+
66+
# pact-ruby-v2 pact (as v2) verified by pact-ruby-v2
67+
"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" =>
68+
"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",
69+
# pact-ruby-v2 pact (as v2) verified by pact-ruby-v1
70+
"latestby=cvpv&q[][pacticipant]=Foo&q[][pacticipant]=Bar&q[][version]=1%2e2%2e3&q[][version]=9%2e9%2e9" =>
71+
"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",
72+
73+
# pact-ruby-v2 pact (as v2) verified by pact-ruby-v2
74+
"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" =>
75+
"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",
76+
# pact-ruby-v2 pact (as v2) verified by pact-ruby-v1
77+
"latestby=cvpv&q[][latest]=true&q[][pacticipant]=Foo&q[][pacticipant]=Bar&q[][tag]=prod&q[][version]=1%2e2%2e3" =>
78+
"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",
79+
80+
# pact-ruby-v2 pact (as v2) verified by pact-ruby-v2
81+
"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" =>
82+
"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",
83+
# pact-ruby-v2 pact (as v2) verified by pact-ruby-v1
84+
"latestby=cvpv&q[][latest]=true&q[][pacticipant]=Foo&q[][pacticipant]=Bar&q[][version]=1%2e2%2e4" =>
85+
"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",
86+
}
87+
3888
def initialize(app)
3989
@app = app
4090
end
4191

4292
def call env
4393
original_path = env["PATH_INFO"]
94+
original_query = env["QUERY_STRING"]
95+
96+
QUERY_STRING_REPLACEMENTS.each do | (find, replace) |
97+
env["QUERY_STRING"] = env["QUERY_STRING"].gsub(find, replace)
98+
end
99+
100+
if env["QUERY_STRING"] != original_query
101+
puts "Modified query string: #{env["QUERY_STRING"]}"
102+
end
103+
44104
env_with_modified_path = env
45105
PATH_REPLACEMENTS.each do | (find, replace) |
46106
env_with_modified_path["PATH_INFO"] = env_with_modified_path["PATH_INFO"].gsub(find, replace)

spec/service_consumers/pact_helper.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,6 @@ def do_not_rollback? _response
5656
end
5757

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

0 commit comments

Comments
 (0)