sbmt-pact 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +62 -0
  4. data/Appraisals +23 -0
  5. data/CHANGELOG.md +96 -0
  6. data/Dockerfile +14 -0
  7. data/Gemfile +5 -0
  8. data/LICENSE +21 -0
  9. data/README.md +212 -0
  10. data/Rakefile +12 -0
  11. data/dip.yml +86 -0
  12. data/docker-compose.yml +40 -0
  13. data/docs/sbmt-pact-arch.png +0 -0
  14. data/lefthook-local.dip_example.yml +4 -0
  15. data/lefthook.yml +6 -0
  16. data/lib/sbmt/pact/configuration.rb +23 -0
  17. data/lib/sbmt/pact/consumer/grpc_interaction_builder.rb +193 -0
  18. data/lib/sbmt/pact/consumer/http_interaction_builder.rb +149 -0
  19. data/lib/sbmt/pact/consumer/interaction_contents.rb +47 -0
  20. data/lib/sbmt/pact/consumer/message_interaction_builder.rb +285 -0
  21. data/lib/sbmt/pact/consumer/mock_server.rb +92 -0
  22. data/lib/sbmt/pact/consumer/pact_config/base.rb +24 -0
  23. data/lib/sbmt/pact/consumer/pact_config/grpc.rb +26 -0
  24. data/lib/sbmt/pact/consumer/pact_config/http.rb +26 -0
  25. data/lib/sbmt/pact/consumer/pact_config/message.rb +17 -0
  26. data/lib/sbmt/pact/consumer/pact_config.rb +24 -0
  27. data/lib/sbmt/pact/consumer.rb +8 -0
  28. data/lib/sbmt/pact/matchers/base.rb +67 -0
  29. data/lib/sbmt/pact/matchers/v1/equality.rb +19 -0
  30. data/lib/sbmt/pact/matchers/v2/regex.rb +19 -0
  31. data/lib/sbmt/pact/matchers/v2/type.rb +17 -0
  32. data/lib/sbmt/pact/matchers/v3/boolean.rb +17 -0
  33. data/lib/sbmt/pact/matchers/v3/date.rb +18 -0
  34. data/lib/sbmt/pact/matchers/v3/date_time.rb +18 -0
  35. data/lib/sbmt/pact/matchers/v3/decimal.rb +17 -0
  36. data/lib/sbmt/pact/matchers/v3/each.rb +42 -0
  37. data/lib/sbmt/pact/matchers/v3/include.rb +17 -0
  38. data/lib/sbmt/pact/matchers/v3/integer.rb +17 -0
  39. data/lib/sbmt/pact/matchers/v3/number.rb +17 -0
  40. data/lib/sbmt/pact/matchers/v3/time.rb +18 -0
  41. data/lib/sbmt/pact/matchers/v4/each_key.rb +26 -0
  42. data/lib/sbmt/pact/matchers/v4/each_key_value.rb +32 -0
  43. data/lib/sbmt/pact/matchers/v4/each_value.rb +33 -0
  44. data/lib/sbmt/pact/matchers/v4/not_empty.rb +17 -0
  45. data/lib/sbmt/pact/matchers.rb +94 -0
  46. data/lib/sbmt/pact/native/blocking_verifier.rb +17 -0
  47. data/lib/sbmt/pact/native/logger.rb +25 -0
  48. data/lib/sbmt/pact/provider/async_message_verifier.rb +32 -0
  49. data/lib/sbmt/pact/provider/base_verifier.rb +158 -0
  50. data/lib/sbmt/pact/provider/grpc_verifier.rb +42 -0
  51. data/lib/sbmt/pact/provider/gruf_server.rb +75 -0
  52. data/lib/sbmt/pact/provider/http_server.rb +66 -0
  53. data/lib/sbmt/pact/provider/http_verifier.rb +46 -0
  54. data/lib/sbmt/pact/provider/message_provider_servlet.rb +80 -0
  55. data/lib/sbmt/pact/provider/pact_broker_proxy.rb +85 -0
  56. data/lib/sbmt/pact/provider/pact_broker_proxy_runner.rb +71 -0
  57. data/lib/sbmt/pact/provider/pact_config/async.rb +25 -0
  58. data/lib/sbmt/pact/provider/pact_config/base.rb +92 -0
  59. data/lib/sbmt/pact/provider/pact_config/grpc.rb +30 -0
  60. data/lib/sbmt/pact/provider/pact_config/http.rb +25 -0
  61. data/lib/sbmt/pact/provider/pact_config.rb +24 -0
  62. data/lib/sbmt/pact/provider/provider_server_runner.rb +89 -0
  63. data/lib/sbmt/pact/provider/provider_state_configuration.rb +32 -0
  64. data/lib/sbmt/pact/provider/provider_state_servlet.rb +84 -0
  65. data/lib/sbmt/pact/provider.rb +8 -0
  66. data/lib/sbmt/pact/railtie.rb +13 -0
  67. data/lib/sbmt/pact/rspec/support/pact_consumer_helpers.rb +46 -0
  68. data/lib/sbmt/pact/rspec/support/pact_message_helpers.rb +42 -0
  69. data/lib/sbmt/pact/rspec/support/pact_provider_helpers.rb +87 -0
  70. data/lib/sbmt/pact/rspec/support/waterdrop/pact_waterdrop_client.rb +27 -0
  71. data/lib/sbmt/pact/rspec/support/webmock/webmock_helpers.rb +30 -0
  72. data/lib/sbmt/pact/rspec.rb +17 -0
  73. data/lib/sbmt/pact/tasks/pact.rake +13 -0
  74. data/lib/sbmt/pact/version.rb +7 -0
  75. data/lib/sbmt/pact.rb +48 -0
  76. data/sbmt-pact.gemspec +59 -0
  77. metadata +462 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4e25420695b0554f5f33b616489005f728e0181586e0406da057fbd50bed1d06
4
+ data.tar.gz: 84972279401ef1a085806fc7e19a678bdd9b919edb306050c8c0432cf60c1cb3
5
+ SHA512:
6
+ metadata.gz: aa7672e3b37b7ed48827fca27ce7eb433318a1bc03e1ad9d41b00fde572d718d2989ab57ae90c298bbab991b0277565d5bc23ddb2862d1a762268256357e3f50
7
+ data.tar.gz: 1e3ae269dd85853864be55b2131556c09f16f61d81b8308a9b112a86d2ad834e3bf159bf80d3ac34b868a8d9dc232f5601fb18ccd18e724cb1535b0f4440d713
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --require spec_helper
3
+ --require rails_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,62 @@
1
+ # We want Exclude directives from different
2
+ # config files to get merged, not overwritten
3
+ inherit_mode:
4
+ merge:
5
+ - Exclude
6
+
7
+ AllCops:
8
+ TargetRubyVersion: 2.7
9
+ TargetRailsVersion: 6.0
10
+ NewCops: enable
11
+ SuggestExtensions: false
12
+ Exclude:
13
+ - spec/internal/pkg/**/*
14
+
15
+ require:
16
+ # Performance cops are bundled with Standard
17
+ - rubocop-performance
18
+ - rubocop-rails
19
+ - rubocop-rspec
20
+ # Standard's config uses custom cops,
21
+ # so it must be loaded
22
+ - standard
23
+
24
+ inherit_gem:
25
+ standard: config/base.yml
26
+
27
+ # rubocop-rails
28
+ Rails/SkipsModelValidations:
29
+ Enabled: false
30
+
31
+ # rubocop-rspec
32
+ RSpec/AnyInstance:
33
+ Enabled: false
34
+
35
+ RSpec/MultipleExpectations:
36
+ Enabled: false
37
+
38
+ RSpec/LetSetup:
39
+ Enabled: false
40
+
41
+ RSpec/StubbedMock:
42
+ Enabled: false
43
+
44
+ RSpec/MessageSpies:
45
+ Enabled: false
46
+
47
+ RSpec/NestedGroups:
48
+ Max: 10
49
+
50
+ RSpec/ExampleLength:
51
+ Max: 70
52
+
53
+ RSpec/MultipleMemoizedHelpers:
54
+ Max: 15
55
+
56
+ RSpec/DescribeClass:
57
+ Exclude:
58
+ - spec/sbmt/pact/tasks/*
59
+
60
+ RSpec/EmptyExampleGroup:
61
+ Exclude:
62
+ - spec/pact/**/*
data/Appraisals ADDED
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ # See compatibility table at https://www.fastruby.io/blog/ruby/rails/versions/compatibility-table.html
4
+
5
+ versions_map = {
6
+ "6.0" => %w[2.7],
7
+ "6.1" => %w[2.7 3.0],
8
+ "7.0" => %w[3.1],
9
+ "7.1" => %w[3.2],
10
+ "7.2" => %w[3.3]
11
+ }
12
+
13
+ current_ruby_version = RUBY_VERSION.split(".").first(2).join(".")
14
+
15
+ versions_map.each do |rails_version, ruby_versions|
16
+ ruby_versions.each do |ruby_version|
17
+ next if ruby_version != current_ruby_version
18
+
19
+ appraise "rails-#{rails_version}" do
20
+ gem "rails", "~> #{rails_version}.0"
21
+ end
22
+ end
23
+ end
data/CHANGELOG.md ADDED
@@ -0,0 +1,96 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](http://keepachangelog.com/)
6
+ and this project adheres to [Semantic Versioning](http://semver.org/).
7
+
8
+ ## [Unreleased] - yyyy-mm-dd
9
+
10
+ ### Added
11
+
12
+ ### Changed
13
+
14
+ - Remove sbmt-dev
15
+
16
+ ### Fixed
17
+
18
+ ## [0.11.1] - 2024-08-22
19
+
20
+ ### Fixed
21
+ - the `verify_only` config option is now set based on the `PACT_CONSUMER_FULL_NAME` environment variable.
22
+ - if the current `consumer_name` does not match the `verify_only` option, then the consumer verification is skipped
23
+
24
+ ## [0.11.0] - 2024-08-07
25
+
26
+ ### Added
27
+ - async messages support
28
+ - collection matchers
29
+ - support of additional includes of proto-files for grpc plugin
30
+
31
+ ## [0.10.0] - 2024-08-15
32
+
33
+ ### Added
34
+ - HTTP Rspec DSL
35
+
36
+ ## [0.9.0] - 2024-08-03
37
+
38
+ ### Added
39
+ - pact-broker-proxy to filter proper transport types in specs
40
+ - ability to run pact-tests on CI + dip
41
+
42
+ ### Fixed
43
+ - refactor matchers
44
+
45
+ ## [0.8.0] - 2024-07-04
46
+
47
+ ### Added
48
+ - Use `deployed: true` for default consumer selectors instead master branch
49
+
50
+ ## [0.7.0] - 2024-06-21
51
+
52
+ ### Added
53
+ - Ability to limit consumers to verify with provider
54
+
55
+ ### Fixed
56
+ - Changed pact-specs rspec meta (`type: :pact` => `pact: true`) for compatibility with legacy pact-ruby / older rspec
57
+ - Bump used pact-protobuf-plugin version to 0.4.0
58
+ - `match_any_string` now matches empty strings
59
+ - limit pact:verify specs only to consumer pact-tests dir
60
+
61
+ ## [0.6.0] - 2024-06-05
62
+
63
+ ### Fixed
64
+ - GRPC producer DSL (rspec) refined
65
+
66
+ ## [0.5.0] - 2024-06-05
67
+
68
+ ### Fixed
69
+ - GRPC consumer DSL (rspec) refined
70
+ - plugin matchers refined
71
+
72
+ ## [0.4.1] - 2024-06-06
73
+
74
+ ### Fixed
75
+ - Use proper consumer version for provider verification
76
+
77
+ ## [0.4.0] - 2024-05-29
78
+
79
+ ### Added
80
+ - Ability to verify provider specs against pact-broker
81
+
82
+ ## [0.3.0] - 2024-05-03
83
+
84
+ ### Added
85
+ - Provider specs base DSL/helpers
86
+
87
+ ## [0.2.0] - 2024-04-18
88
+
89
+ ### Added
90
+ - Consumer specs base DSL/helpers
91
+
92
+ ## [Unreleased]
93
+
94
+ ## [0.1.0] - 2024-04-12
95
+
96
+ - Initial release
data/Dockerfile ADDED
@@ -0,0 +1,14 @@
1
+ ARG RUBY_VERSION
2
+
3
+ FROM ruby:$RUBY_VERSION
4
+
5
+ ARG BUNDLER_VERSION
6
+ ARG RUBYGEMS_VERSION
7
+
8
+ ENV BUNDLE_JOBS=4 \
9
+ BUNDLE_RETRY=3
10
+
11
+ RUN gem update --system "${RUBYGEMS_VERSION}" \
12
+ && rm /usr/local/lib/ruby/gems/*/specifications/default/bundler*.gemspec \
13
+ && gem install --default bundler:${BUNDLER_VERSION} \
14
+ && gem install bundler -v ${BUNDLER_VERSION}
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ source ENV.fetch("RUBYGEMS_PUBLIC_SOURCE", "https://rubygems.org/")
4
+
5
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Kuper Tech
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,212 @@
1
+ # Sbmt Pact
2
+
3
+ **`sbmt-pact`** is a powerful Ruby gem designed to simplify and streamline [Pact](https://docs.pact.io/) testing between microservices. This gem provides a robust set of RSpec utilities to help developers implement consumer-driven contract testing in microservice architectures.
4
+
5
+ In the world of microservices, ensuring seamless communication between services is crucial. This gem leverages the Pact to enable effective contract testing, allowing you to catch integration issues early in the development cycle. Contract testing is a way to check if different parts of a system work well together. It's like making sure two puzzle pieces fit perfectly before assembling the whole puzzle. Each part is tested on its own to see if it follows a set of rules (the "contract") that everyone agreed on. This helps catch problems early and makes sure all parts of the system speak the same language.
6
+
7
+ ## Motivation
8
+
9
+ Currently, the existing version of the [pact-ruby](https://github.com/pact-foundation/pact-ruby) gem only supports Pact Specification versions v1 and v2, which doesn't allow for:
10
+ - Writing contract tests with non-HTTP transports (for example, gRPC)
11
+ - Writing contract tests for async messages (Kafka, etc.)
12
+
13
+ The `pact-ruby` gem is in maintenance mode, as there has been a transition to rust-core, which is intended to be used through FFI in non-Rust stacks.
14
+
15
+ This gem eliminates the above-mentioned limitations and implements support for the latest versions of Pact specifications:
16
+ - It's based on pact-ffi and pact-ruby-ffi
17
+ - It provides a convenient DSL, simplifying the writing of contract tests in Ruby/RSpec
18
+
19
+ ## Architecture
20
+
21
+ ![Pact tests architecture](docs/sbmt-pact-arch.png)
22
+
23
+ - DSL - implementation of RSpec-DSL for convenient writing of Pact tests
24
+ - Matchers - implementation of Pact matchers, which are convenient helpers used in consumer-DSL, encapsulating all the logic for serialization into Pact format
25
+ - Mock servers - mock servers that allow for correct execution of provider tests
26
+
27
+ ## Usage
28
+
29
+ For each type of interaction (due to their specific features), a separate version of DSL has been implemented. However, the general principles remain the same for each type of interaction.
30
+
31
+ ```ruby
32
+
33
+ # Declaration of a consumer test, always include the :pact tag
34
+ # This is used in CI/CD pipelines to separate Pact tests from other RSpec tests
35
+ # Pact tests are not run as part of the general RSpec pipeline
36
+ RSpec.describe "SomePactConsumerTestForAnyTransport", :pact do
37
+ # declaration of the type of interaction - here we determine which consumer and provider interact on which transport
38
+ has_http_pact_between "CONSUMER-NAME", "PROVIDER-NAME"
39
+ # or
40
+ has_grpc_pact_between "CONSUMER-NAME", "PROVIDER-NAME"
41
+ # or
42
+ has_message_pact_between "CONSUMER-NAME", "PROVIDER-NAME"
43
+
44
+ # the context for one of the interactions, for example GET /api/v2/stores
45
+ context "with GET /api/v2/stores" do
46
+ let(:interaction) do
47
+ # creating a new interaction - within which we describe the contract
48
+ new_interaction
49
+ # if you need to save any metadata for subsequent use by the test provider,
50
+ # for example, specify the entity ID that will need to be moved to the database in the test provider
51
+ # we use the provider states, see more at https://docs.pact.io/getting_started/provider_states
52
+ .given("UNIQUE PROVIDER STATE", key1: value1, key2: value2)
53
+ # the description of the interaction, used for identification inside the package binding,
54
+ # is optional in some cases, but it is recommended to always specify
55
+ .upon_receiving("UNIQUE INTERACTION DESCRIPTION")
56
+ # the description of the request using the matchers
57
+ # the name and parameters of the method differ for different transports
58
+ .with_request(...)
59
+ # the description of the response using the matchers
60
+ # the name and parameters of the method differ for different transports
61
+ .with_response(...)
62
+ # further, there are differences for different types of transports,
63
+ # for more information, see the relevant sections of the documentation
64
+ end
65
+
66
+ it "executes the pact test without errors" do
67
+ interaction.execute do
68
+ # here our client is called for the API being tested
69
+ # in this context, the client can be: http client, grpc client, kafka consumer
70
+ expect(make_request).to be_success
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ ```
77
+
78
+ Common DSL Methods:
79
+ - `new_interaction` - initializes a new interaction
80
+ - `given` - allows specifying a provider state with or without parameters, for more details see https://docs.pact.io/getting_started/provider_states
81
+ - `upon_receiving` - allows specifying the name of the interaction
82
+
83
+ ### HTTP consumers
84
+
85
+ Specific DSL methods:
86
+ - `with_request(HTTP_METHOD, QUERY_PATH, {headers: kv_hash, body: kv_hash})` - request definition
87
+ - `with_response(HTTP_STATUS, {headers: kv_hash, body: kv_hash})` - response definition
88
+
89
+ More at [http_client_spec.rb](spec/pact/providers/sbmt-pact-test-app/http_client_spec.rb)
90
+
91
+ ### gRPC consumers
92
+
93
+ Specific DSL methods:
94
+ - `with_service(PROTO_PATH, RPC_SERVICE_AND_ACTION)` - specifies the contract used, PROTO_PATH is relative from the app root
95
+ - `with_request(request_kv_hash)` - request definition
96
+ - `with_response(response_kv_hash)` - response definition
97
+
98
+ More at [grpc_client_spec.rb](spec/pact/providers/sbmt-pact-test-app/grpc_client_spec.rb)
99
+
100
+ ### Kafka consumers
101
+
102
+ Specific DSL methods:
103
+ - `with_headers(kv_hash)` - message-headers definition; you can use matchers
104
+ - `with_metadata(kv_hash)` - message-metadata definition (special keys are `key` and `topic`, where, respectively, you can specify the matchers for the partitioning key and the topic
105
+
106
+ Next, the specifics are one of two options for describing the format:
107
+
108
+ **JSON** (to describe a message in a JSON representation):
109
+ - `with_json_contents(kv_hash)` - message format definition
110
+
111
+ **PROTO** (to describe the message in the protobuf view):
112
+ - `with_proto_class(PROTO_PATH, PROTO_MESSAGE_NAME)` - specifies the contract used, PROTO_PATH is relative to the root, PROTO_MESSAGE_NAME is the name of the message used from the proto file
113
+ - `with_proto_contents(kv_hash)` - message format definition
114
+
115
+ More at [kafka_spec.rb](spec/pact/providers/sbmt-pact-test-app/kafka_spec.rb)
116
+
117
+ ### Matchers
118
+
119
+ Matchers are special helper methods that allow you to define rules for matching request/response parameters at the level of the pact manifest.
120
+ The matchers are described in the [Pact specifications](https://github.com/pact-foundation/pact-specification). In this gem, the matchers are implemented as RSpec helpers.
121
+
122
+ For details of the implementation, see [matchers.rb](lib/sbmt/pact/matchers.rb)
123
+
124
+ - `match_exactly(sample)` - match the exact value specified in the sample
125
+ - `match_type_of(sample)` - match the data type (integer, string, boolean) specified in the sample
126
+ - `match_include(sample)` - match a substring
127
+ - `match_any_string(sample)` - match any string, because of the peculiarities, null and empty strings will also be matched here
128
+ - `match_any_integer(sample)` - match any integer
129
+ - `match_any_decimal(sample)` - match any float/double
130
+ - `match_any_number(sample)` - match any integer/float/double
131
+ - `match_any_boolean(sample)` - match any true/false
132
+ - `match_uuid(sample)` - match any UUID (`match_regex` is used under the hood)
133
+ - `match_regex(regex, sample)` - match by regexp
134
+ - `match_datetime(format, sample)` - match any datetime
135
+ - `match_iso8601(sample)` - match datetime in ISO8601 (the matcher does not fully comply with ISO8601, matches only the most common variants, `match_regex` is used under the hood)
136
+ - `match_date(format, sample)` - match any date (rust datetime)
137
+ - `match_time(format, sample)` - match any time (rust datetime)
138
+ - `match_each(template)` - match all the elements of the array according to the specified template, you can use it for nested elements
139
+ - `match_each_regex(regex, sample)` - match all array elements by regex, used for arrays with string elements
140
+ - `match_each_key(template, key_matchers)` - match each hash key according to the specified template
141
+ - `match_each_value(template)` - match each hash value according to the specified template, can be used for nested elements
142
+ - `match_each_kv(template, key_matchers)` - match all the keys/values of Hash according to the specified template and key_matchers, can be used for nested elements
143
+
144
+ See the different uses of the matchers in [matchers_spec.rb](spec/sbmt/pact/matchers_spec.rb)
145
+
146
+ ## Development & Test
147
+
148
+ Install [Dip](https://github.com/bibendi/dip)
149
+
150
+ ### Setup
151
+
152
+ ```shell
153
+ dip provision
154
+ ```
155
+
156
+ ### Run unit tests
157
+
158
+ ```shell
159
+ dip rspec
160
+ ```
161
+
162
+ ### Run pact tests
163
+
164
+ The Pact tests are not run within the general rspec pipeline, they need to be run separately, see below
165
+
166
+ #### Consumer tests
167
+
168
+ ```shell
169
+ dip pact consumer
170
+ # or
171
+ bundle exec rspec -t pact spec/pact/providers/**/*_spec.rb
172
+ ```
173
+
174
+ **NOTE** If you have never run it, you need to run it at least once to generate json-pact manifests that will be used in provider tests (below)
175
+
176
+ #### Provider tests
177
+
178
+ ```shell
179
+ dip pact provider
180
+ # or
181
+ bundle exec rspec -t pact spec/pact/consumers/*_spec.rb
182
+ ```
183
+
184
+ #### Using Pact Broker locally
185
+
186
+ If you need to check the ability to work with a package broker locally, you need to do the following:
187
+
188
+ - Run the broker
189
+
190
+ ```shell
191
+ $ dip up pact-broker
192
+ ```
193
+
194
+ - Run consumer tests to generate a pact manifest (it will be created in `spec/internal/pacts` based on the results of successful completion of consumer tests)
195
+
196
+ ```shell
197
+ $ dip pact consumer
198
+ ```
199
+
200
+ - Publish the generated pact manifest in the pact broker
201
+
202
+ ```shell
203
+ $ dip pact-cli publish
204
+ ```
205
+
206
+ - Make sure that the manifest is published by opening it in a browser http://localhost:9292 (don't forget to forward port 9292 to localhost, see `docker-compose.yml`)
207
+
208
+ - run provider tests using a pact broker
209
+
210
+ ```shell
211
+ $ dip pact provider-with-local-broker
212
+ ```
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
data/dip.yml ADDED
@@ -0,0 +1,86 @@
1
+ version: '7'
2
+
3
+ environment:
4
+ RUBY_VERSION: '3.3'
5
+
6
+ compose:
7
+ files:
8
+ - docker-compose.yml
9
+
10
+ interaction:
11
+ bash:
12
+ description: Open the Bash shell in app's container
13
+ service: ruby
14
+ command: /bin/bash
15
+
16
+ bundle:
17
+ description: Run Bundler commands
18
+ service: ruby
19
+ command: bundle
20
+
21
+ rails:
22
+ description: Run RoR commands
23
+ service: ruby
24
+ command: bundle exec rails
25
+
26
+ appraisal:
27
+ description: Run Appraisal commands
28
+ service: ruby
29
+ command: bundle exec appraisal
30
+
31
+ rspec:
32
+ description: Run Rspec commands
33
+ service: ruby
34
+ command: bundle exec rspec
35
+ subcommands:
36
+ all:
37
+ command: bundle exec appraisal rspec
38
+ rails-6.0:
39
+ command: bundle exec appraisal rails-6.0 rspec
40
+ rails-6.1:
41
+ command: bundle exec appraisal rails-6.1 rspec
42
+ rails-7.0:
43
+ command: bundle exec appraisal rails-7.0 rspec
44
+
45
+ pact:
46
+ description: Run pact tests
47
+ service: ruby
48
+ environment:
49
+ RAILS_ENV: test
50
+ PACT_DO_NOT_TRACK: true
51
+ subcommands:
52
+ consumer:
53
+ command: bundle exec rspec -t pact spec/pact/providers/**/*_spec.rb
54
+ provider:
55
+ command: bundle exec rspec -t pact spec/pact/consumers/*_spec.rb
56
+ provider-with-local-broker:
57
+ command: /bin/sh -c 'PACT_CONSUMER_BRANCH=master PACT_CONSUMER_FULL_NAME=sbmt-pact-test-app PACT_BROKER_URL=http://pact-broker:9292 bundle exec rspec -t pact spec/pact/consumers/*_spec.rb'
58
+
59
+ pact-cli:
60
+ description: Run pact-broker commands
61
+ service: pact-cli
62
+ subcommands:
63
+ publish:
64
+ command: pact-broker publish --consumer-app-version 1.0.0 --branch master --broker-base-url http://pact-broker:9292 sbmt-pact-test-app-sbmt-pact-test-app.json
65
+
66
+ rubocop:
67
+ description: Run Ruby linter
68
+ service: ruby
69
+ command: bundle exec rubocop
70
+
71
+ setup:
72
+ description: Install deps
73
+ service: ruby
74
+ command: bin/setup
75
+
76
+ test:
77
+ description: Run linters, run all tests
78
+ service: ruby
79
+ command: bin/test
80
+
81
+ provision:
82
+ - dip compose down --volumes
83
+ - cp -f lefthook-local.dip_example.yml lefthook-local.yml
84
+ - rm -f Gemfile.lock
85
+ - rm -f gemfiles/*gemfile*
86
+ - dip setup
@@ -0,0 +1,40 @@
1
+ services:
2
+ ruby:
3
+ build:
4
+ context: .
5
+ dockerfile: Dockerfile
6
+ args:
7
+ RUBY_VERSION: ${RUBY_VERSION:-3.3}
8
+ BUNDLER_VERSION: 2.4.22
9
+ RUBYGEMS_VERSION: 3.4.22
10
+ image: sbmt-pact-dev:0.1.0-ruby_${RUBY_VERSION:-3.3}
11
+ environment:
12
+ HISTFILE: /app/tmp/.bash_history
13
+ BUNDLE_PATH: /usr/local/bundle
14
+ BUNDLE_CONFIG: /app/.bundle/config
15
+ command: bash
16
+ working_dir: /app
17
+ volumes:
18
+ - .:/app:cached
19
+ - ${SBMT_RUBYGEMS_PATH:-..}:/app/vendor/gems:cached
20
+ - bundler_data:/usr/local/bundle
21
+
22
+ pact-broker:
23
+ image: pactfoundation/pact-broker
24
+ ports:
25
+ - 9292
26
+ environment:
27
+ PACT_BROKER_DATABASE_ADAPTER: sqlite
28
+ PACT_BROKER_DATABASE_NAME: pact_broker.sqlite
29
+ PACT_BROKER_LOG_LEVEL: DEBUG
30
+
31
+ pact-cli:
32
+ image: pactfoundation/pact-cli
33
+ working_dir: /app
34
+ depends_on:
35
+ - pact-broker
36
+ volumes:
37
+ - ./spec/internal/pacts:/app:cached
38
+
39
+ volumes:
40
+ bundler_data:
Binary file
@@ -0,0 +1,4 @@
1
+ pre-commit:
2
+ commands:
3
+ rubocop:
4
+ run: dip {cmd}
data/lefthook.yml ADDED
@@ -0,0 +1,6 @@
1
+ pre-commit:
2
+ commands:
3
+ rubocop:
4
+ tags: backend
5
+ glob: "{*.rb,**/*.rb,Gemfile,Rakefile}"
6
+ run: bundle exec rubocop -A --force-exclusion {staged_files} && git add {staged_files}
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sbmt
4
+ module Pact
5
+ class Configuration
6
+ attr_reader :before_provider_state_proc, :after_provider_state_proc
7
+
8
+ class GlobalProviderConfigurationError < ::Sbmt::Pact::Error; end
9
+
10
+ def before_provider_state_setup(&block)
11
+ raise GlobalProviderConfigurationError, "no block given" unless block
12
+
13
+ @before_provider_state_proc = block
14
+ end
15
+
16
+ def after_provider_state_teardown(&block)
17
+ raise GlobalProviderConfigurationError, "no block given" unless block
18
+
19
+ @after_provider_state_proc = block
20
+ end
21
+ end
22
+ end
23
+ end