feat(provider): add SoftFail mode for downstream-gated verification#580
Open
stan-is-hate wants to merge 1 commit into
Open
feat(provider): add SoftFail mode for downstream-gated verification#580stan-is-hate wants to merge 1 commit into
stan-is-hate wants to merge 1 commit into
Conversation
Callers that have a downstream authoritative gate (e.g. a Pact Broker
can-i-merge / can-i-deploy check) want verification mismatches to be
recorded to the broker and reported in the test framework, but NOT to
fail CI locally — the downstream gate makes the real decision.
Previously the only way to suppress local failure was at the shell
layer (turning off pipefail around `go test`), which also silenced
verifier panics, broker auth failures, and any other infrastructure
problem. That made "tests didn't actually run but CI is green" a
common failure mode.
New behavior — `VerifyRequest.SoftFail` (default false, preserves
existing behavior):
- SoftFail = false (default):
err == nil → subtest PASS
err != nil → subtest FAIL (t.Error)
- SoftFail = true:
err == nil → subtest PASS
ErrVerifierFailed → subtest SKIP (t.Skipf, message preserved)
any other err → subtest FAIL (t.Error)
Infrastructure errors (ErrVerifierFailedToRun, panics, broker auth)
always fail the subtest, regardless of SoftFail — they signal the
verifier could not produce a result for the downstream gate to act on.
The discrimination uses `errors.Is(err, native.ErrVerifierFailed)`,
which leverages the mutual-exclusivity invariant of the two verifier
sentinels documented in pact-foundation#579.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Add
VerifyRequest.SoftFailto let callers render verification mismatches as a SKIPped subtest instead of a failed one when a downstream gate (e.g. a Pact Brokercan-i-merge/can-i-deploycheck) owns the authoritative compatibility decision.Motivation
Callers wrapping pact-go in a larger contract-testing system commonly want this contract:
Today, the only way to achieve this is at the shell layer (turning off
set -o pipefailaroundgo test), which silences everything, including:That makes "tests didn't actually run but CI is green" a common silent failure mode. We want suppression to be scoped to verification mismatches only — infrastructure failures should still fail loudly.
This PR provides that scope via a per-request flag.
API
A single new bool field on
VerifyRequest:SoftFailsits next to the other per-request behavior toggles. Defaultfalsepreserves existing behavior — no caller currently using pact-go sees any change.Behavior matrix
SoftFailfalse(default)falseErrVerifierFailed(mismatch)falseErrVerifierFailedToRun(infra)truetrueErrVerifierFailed(mismatch)trueErrVerifierFailedToRun(infra)trueDiscrimination uses
errors.Is(err, native.ErrVerifierFailed), leveraging the mutual-exclusivity invariant of the two verifier sentinels documented in #579.Implementation
Two-file change.
provider/verify_request.gogets the new field with a thorough doc comment.provider/verifier.goswitches the existingif err != nil { t.Error(err) }body of the subtest to a 3-way switch:Why SKIP (not PASS) for the soft-fail mismatch case
Go's stdlib
testingpackage has three outcome states: PASS, FAIL, SKIP. Once a subtest callst.Error/t.Fatal, the failure propagates to every ancestor and cannot be cleared —c.failed = trueis set on the parent chain inFail()(Go stdlib source, search forfunc (c *common) Fail()).That leaves three options for "verification ran, found mismatches, results published, caller deferred to downstream gate":
t.Logf: dishonest — the test report claims verification passed, but verification actually reported mismatches.<skipped message="..."/>, which test dashboards already recognize as "look here for context." Maps cleanly to pytest'sxfailsemantic.Backwards compatibility
Pure addition. Zero behavior change for any existing caller (
SoftFaildefaults tofalse, which is the existing branch).Test plan
go build ./provider/...cleango vet ./provider/...clean (one pre-existing IPv6 warning unrelated to this PR)go test ./provider/ -shortcleanDownstream
Confluent's
service-runtime-golibrary will adopt this immediately once the release ships, replacing its current shell-layer workaround with a singleSoftFail: truesetting onVerifyRequest. Tracking PR in confluentinc/service-runtime-go#1099 (the strict-mode env var) — this pact-go change is what makes that work correctly under all conditions.🤖 Generated with Claude Code