pact-foundation / pact_broker-client

A Ruby and CLI client for the Pact Broker. Publish and retrieve pacts and verification results.
MIT License
69 stars 47 forks source link

Spec `v3` Pact files cannot be merged when publishing #131

Closed martinslota closed 1 year ago

martinslota commented 1 year ago

Software versions

Issue Checklist

Please confirm the following:

Expected behaviour

Several v3 Pact files can be merged and published using the Publisher.

Actual behaviour

Merging fails because the merger seems to assume to be merging spec v2 Pact files.

Steps to reproduce

See https://github.com/martinslota/pact-js-bug-cannot-merge-v3-pacts.

Relevant log files

failure.log

mefellows commented 1 year ago

Thanks for the repro.

I think the issue here is the ruby pact broker client that detected two contracts for the same provider and is merging themz but doesn't know how to do so with pact specs > version 2.

The solution here is not to write to two separate pact files and merge on publish. It's safe to point both providers at the same output directory

Could you please see if that works?

martinslota commented 1 year ago

I think the issue here is the ruby pact broker client that detected two contracts for the same provider and is merging themz but doesn't know how to do so with pact specs > version 2.

Yes, I believe it is this script that only really works for spec version 2.

The solution here is not to write to two separate pact files and merge on publish. It's safe to point both providers at the same output directory

Could you please see if that works?

We parallelize our consumer tests on several workers that each produce a pact file. We do need to merge those files somehow to publish a single pact for that version of the consumer. Also, duplicate removal is really cool to have in our case. If we merge the files in a naive way (just concatenating the interactions arrays), then the resulting pact file has lots of duplicates and verification of the provider becomes a lot slower.

martinslota commented 1 year ago

I would also argue that since the Publisher takes an argument called pactFilesOrDirs, it should be able to deal with more than one file.

mefellows commented 1 year ago

I would also argue that since the Publisher takes an argument called pactFilesOrDirs, it should be able to deal with more than one file.

The usual practice here would be to have 1 file per provider. So a consumer can have multiple providers, each contained within a single pact file.

The bug here is upstream as you said. But it is easily worked around by not producing more than one pact file per provider.

mefellows commented 1 year ago

I've moved the issue to the upstream source of the problem.

bethesque commented 1 year ago

Sorry, I know this is super old, but yes, you should be able to merge multiple files for the same consumer and provider before publishing, and it should work for v3. Can you provide a couple of sample files for me @martinslota

martinslota commented 1 year ago

Hi @bethesque!

I just re-ran npm ci && npm test in https://github.com/martinslota/pact-js-bug-cannot-merge-v3-pacts and got these files:

The error logged out looked like this:

[20:10:47.021] INFO (95049): pact-core@13.13.6: Publishing pacts to broker at: http://localhost:9292
[20:10:54.859] WARN (95049): pact-core@13.13.6: Pact exited with code 1.
[20:10:54.861] ERROR (95049): pact-core@13.13.6: Pact publication failed with non-zero exit code. Full output was:
Merging /Users/msl/code/pact-js-bug-cannot-merge-v3-pacts/pacts1/MyConsumer-MyProvider.json, /Users/msl/code/pact-js-bug-cannot-merge-v3-pacts/pacts2/MyConsumer-MyProvider.json

PactBroker::Client::PactMergeError - Two interactions have been found with same description ("request") and provider state (nil) but a different request or response. Please use a different description or provider state, or hard-code any random data.

{"description":"request","providerStates":[{"name":"state 1"}],"request":{"method":"GET","path":"/1"},"response":{"status":200}}

{"description":"request","providerStates":[{"name":"state 2"}],"request":{"method":"GET","path":"/2"},"response":{"status":200}}

/Users/msl/code/pact-js-bug-cannot-merge-v3-pacts/node_modules/@pact-foundation/pact-core/src/publisher.js:111
                    return reject(new Error(message));
                                  ^

Error: Pact publication failed with non-zero exit code. Full output was:
Merging /Users/msl/code/pact-js-bug-cannot-merge-v3-pacts/pacts1/MyConsumer-MyProvider.json, /Users/msl/code/pact-js-bug-cannot-merge-v3-pacts/pacts2/MyConsumer-MyProvider.json

PactBroker::Client::PactMergeError - Two interactions have been found with same description ("request") and provider state (nil) but a different request or response. Please use a different description or provider state, or hard-code any random data.

{"description":"request","providerStates":[{"name":"state 1"}],"request":{"method":"GET","path":"/1"},"response":{"status":200}}

{"description":"request","providerStates":[{"name":"state 2"}],"request":{"method":"GET","path":"/2"},"response":{"status":200}}

    at ChildProcess.<anonymous> (/Users/msl/code/pact-js-bug-cannot-merge-v3-pacts/node_modules/@pact-foundation/pact-core/src/publisher.js:111:35)
    at Object.onceWrapper (node:events:629:26)
    at ChildProcess.emit (node:events:526:35)
    at maybeClose (node:internal/child_process:1091:16)
    at ChildProcess._handle.onexit (node:internal/child_process:302:5)

Node.js v18.17.0