Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Pact Provider Bundle Laravel Package

tienvx/pact-provider-bundle

Pact provider bundle for PHP that helps verify your API against consumer-driven contracts. It streamlines provider states, verification endpoints, and test workflows so teams can catch breaking changes early and ship compatible services with confidence.

View on GitHub
Deep Wiki
Context7

Getting Started

tienvx/pact-provider-bundle is a Symfony bundle for Pact provider-side verification. In a Laravel codebase you will not get the usual package auto-discovery experience — the bundle registers a console command and a PHPUnit listener through Symfony's DI container, so on Laravel you either (a) run it inside a thin Symfony kernel you boot only for contract tests, or (b) treat it as a reference implementation and drive pact-php's ProviderVerifier yourself from an artisan command. Pick (a) if you already have a Symfony service definition lying around, (b) if you want zero extra framework surface in composer.json.

Minimal steps:

  1. composer require --dev tienvx/pact-provider-bundle — keep it in require-dev, it has no business in production.
  2. Publish/copy the bundle config (pact_provider.yaml in Symfony; on Laravel mirror the same keys into config/pact.php and read them in your own command).
  3. Point the config at either a Pact Broker (PACT_BROKER_BASE_URL, PACT_BROKER_TOKEN) or a local pacts/ directory of consumer JSON files.
  4. Ensure your app is reachable at a real HTTP URL during the test run — the verifier makes live HTTP calls, it does not invoke your router in-process.
  5. First use case: verify one consumer contract against a single endpoint locally, then wire the same invocation into CI. Don't start with the broker.

Look first at: the bundle's VerifyCommand (it is the whole product surface), its ProviderVerifier wrapper, and the PHPUnit listener class. Everything else is config plumbing.

Implementation Patterns

Local files first, broker second. Keep a pacts/ directory checked in (or downloaded in a CI step) and run verification against it while developing. Only add broker publishing/pulling once the local loop is green — broker failures (auth, version selectors, pending pacts) will otherwise mask real contract mismatches.

Provider states are the integration seam. The bundle's state handler receives a state name plus params from the consumer and must put your Laravel app into that state. Standard pattern: a PactStateHandler class with a match on state name that calls Eloquent factories/seeders, wrapped in DB::beginTransaction() / rollBack() so each state is isolated. Keep state names boring and stable — they are a public contract with every consumer team.

Boot the app once, not per request. The verifier will hit your HTTP endpoint N times. Use php artisan serve in a background process (or better, a pre-warmed Octane/php -S against public/index.php) for the duration of the run, and have the state handler talk to the same database the server uses. A common setup is a dedicated pact connection and a --env=pact boot so you never touch dev data.

CI shape. One job per consumer contract, or one job with a matrix over pact files, so a single failing consumer doesn't hide the others. Run it after your unit/feature suites — contract verification is slow (real HTTP + DB seeding) and you want fast feedback first. Publish results back to the broker on the main branch only, with the provider version set to the commit SHA.

Tagging and deployment gates. Use broker tags (main, production) with can-i-deploy in a pre-deploy step. This is where the package earns its keep: the provider build fails before deploy if a consumer's expectations are unmet, rather than at 2am.

Wrapper command. Regardless of entry point, expose a single php artisan pact:verify (or a composer pact script) so CI config, onboarding docs, and local dev all invoke the same thing. Put the bundle-specific flags in one place; nobody should be memorising verifier options.

Combine with consumer verification using pact-php's consumer side in your own JS/PHP clients' test suites, and treat the broker as the source of truth rather than passing pact files around between repos.

Gotchas and Tips

This is a Symfony bundle. There is no Laravel service provider. composer require alone will not register the command, and vendor/bin/… won't find it. Plan for the adapter work explicitly; if your team won't maintain it, use pact-php directly — the bundle is thin.

The verifier calls over the network. Forgetting to start the server (or starting it on a port that differs from PACT_PROVIDER_BASE_URL) produces connection-refused errors that look like contract failures. Assert server health with a curl step before verification.

Env var precedence is a trap. Broker URL/token, provider base URL, provider version, and consumer version selectors can come from config files, env vars, or CLI flags. When something behaves unexpectedly, dump the fully resolved config — the flags on the command line usually win, and CI often sets an env var that silently overrides your YAML.

State handlers are not sandboxed. If a state handler throws, the verifier reports a generic verification failure. Log loudly inside the handler and rethrow with the state name in the message. Transactional rollback does not cover Redis, queues, or filesystem state — clean those up explicitly.

Time and randomness break contracts. Use Carbon::setTestNow() and fixed seeds in state handlers; otherwise a date-formatting mismatch fails intermittently against an otherwise-correct contract.

Don't assert on your own response in provider tests. The provider's job is to satisfy the consumer's matchers, not to re-specify its own behaviour. Duplicating expectations here means every provider change requires double edits — and it's how teams conclude "contract testing is too much work."

Broker publishing is easy to get wrong. Publish consumer versions from the consumer pipeline, provider verification results from the provider pipeline, and never publish from a developer laptop — junk versions pollute the matrix and make can-i-deploy untrustworthy.

Debugging: run with verbose output and inspect the individual request/response diff, not just the summary. Most "mismatch" reports are one extra/missing field or a type drift (int vs string) that a strict JSON comparison catches immediately.

Extension points are limited by design: state handlers, a custom verifier/output formatter, and the config surface. If you need more than that (custom matchers, request mutations), you're outside this package and into pact-php internals — accept that and pin the version.

On this release (v1.0.4): changes are test renames, a doc return-type fix, and an internal refactor removing a condition. No API, config, or command-line changes — no action required beyond the normal patch bump, and no reason to change the patterns above.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums