{"id":13875881,"url":"https://github.com/pact-foundation/pact-plugins","last_synced_at":"2025-06-20T00:33:41.574Z","repository":{"id":52191430,"uuid":"388319964","full_name":"pact-foundation/pact-plugins","owner":"pact-foundation","description":"🏰 Architecture to support Plugins 🔌 with Pact 🔗","archived":false,"fork":false,"pushed_at":"2025-05-29T00:24:42.000Z","size":23944,"stargazers_count":19,"open_issues_count":16,"forks_count":12,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-06-03T23:58:10.806Z","etag":null,"topics":["contract-testing","grpc","java","kotlin","pact","pact-plugin","pact-plugin-framework","plugins","rust","smartbear-supported"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pact-foundation.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"open_collective":"pact-foundation","custom":["https://pactflow.io"]}},"created_at":"2021-07-22T03:53:44.000Z","updated_at":"2025-05-29T00:24:45.000Z","dependencies_parsed_at":"2023-12-19T01:01:26.588Z","dependency_job_id":"71da03da-c270-41ce-96cb-291ca14f0519","html_url":"https://github.com/pact-foundation/pact-plugins","commit_stats":{"total_commits":999,"total_committers":17,"mean_commits":58.76470588235294,"dds":0.5755755755755756,"last_synced_commit":"5def99c8dc41c70e97ed1ae04bcb8e2961c95332"},"previous_names":[],"tags_count":107,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pact-foundation%2Fpact-plugins","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pact-foundation%2Fpact-plugins/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pact-foundation%2Fpact-plugins/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pact-foundation%2Fpact-plugins/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pact-foundation","download_url":"https://codeload.github.com/pact-foundation/pact-plugins/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pact-foundation%2Fpact-plugins/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":258352752,"owners_count":22687515,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["contract-testing","grpc","java","kotlin","pact","pact-plugin","pact-plugin-framework","plugins","rust","smartbear-supported"],"created_at":"2024-08-06T06:00:48.726Z","updated_at":"2025-06-20T00:33:41.563Z","avatar_url":"https://github.com/pact-foundation.png","language":"Rust","readme":"# Pact Plugins\n\u003e Architecture to support plugins with Pact\n\n* Pact Specification tracking issue: https://github.com/pact-foundation/pact-specification/issues/83\n* Plugin Project Board: https://github.com/pact-foundation/pact-plugins/projects/1\n\n[![Pact Plugin Build (Gradle)](https://github.com/pact-foundation/pact-plugins/actions/workflows/gradle.yml/badge.svg)](https://github.com/pact-foundation/pact-plugins/actions/workflows/gradle.yml)\n[![Pact Plugin Build (Rust)](https://github.com/pact-foundation/pact-plugins/actions/workflows/rust.yml/badge.svg)](https://github.com/pact-foundation/pact-plugins/actions/workflows/rust.yml)\n\n## Plugin architecture\n\nThe plugins are enabled via a message passing mechanism over gRPC. Each language implements a driver which provides the\nmechanism to locate and load plugins, as well as a catalogue of features (like mock servers, matchers and provider\nverifiers) and a central message bus to enable communication between the language implementation and the plugins.\n\n### Plugin driver\n\nThe plugin driver is responsible for providing access to the plugins from the language implementation (which is where the\npact tests are being executed). \n\nMain responsibilities:\n* The ability to find plugins.\n* Load plugins and extract the plugin manifests that describe what the plugin provides.\n* Provide a catalogue of features provided by the plugins.\n* Provide a messaging bus to facilitate communication between the language implementation and the plugins.\n* Manage the plugin lifecycles.\n\nSee [Plugin driver design docs](docs/plugin-driver-design.md).\n\nThere are two implementations of plugin drivers: [JVM](drivers/jvm) and [Rust](drivers/rust).\n\n### Plugins\n\nPlugins are required to start up a gRPC server when loaded, and respond to messages from the plugin driver. They provide\na manifest that describes the features they provide and the mechanism needed to load them.  \n\nMain responsibilities:\n* Have a plugin manifest that describes the plugin and how to load it.\n* Start a gRPC server on load and provide the port to the driver that loaded it.\n* Provide a catalogue of features the plugin provides when the driver requests it.\n* Respond to messages from the driver.\n\nSee the [guide to writing a Pact plugin](docs/writing-plugin-guide.md).\n\n#### Plugins that provide protocol transport implementations\n\nPlugins can provide support for new protocols. The main features that the plugin would provide is to be\nable to create the protocol transport payloads and create a mock server that can deal with them.\n\nSee [Protocol design docs](docs/protocol-plugin-design.md).\n\nFor an example, see the [gRPC plugin](https://github.com/pactflow/pact-protobuf-plugin), it supports gRPC over HTTP/2.\n\n#### Plugins that provide support for different types of content\n\nThese plugins provide the ability to match and generate different types of contents which are used\nwith existing protocol implementations. \n\nSee [Content matcher design docs](docs/content-matcher-design.md).\n\nThere are two example prototype plugins that support matching different types of content: [Protobuf](plugins/protobuf) and \n[CSV](plugins/csv).\n\nSee [PactFlow Protobuf/gRPC plugin](https://github.com/pactflow/pact-protobuf-plugin) for a PactFlow supported plugin.\n\n#### Plugins that provide matchers/generators (WIP)\n\nTODO 🚧\nSee [V2 plugin interface proposal](./docs/proposals/001_V2_Plugin_Interface.md)\n\n## Background\n\nPact was created initially to support the rise of RESTful microservices and has grown to be the de-facto API contract \ntesting tool.\n\nOne of the strengths of Pact is its specification, allowing anybody to create a new language binding in an interoperable\nway. Whilst this has been great at unifying compatibility, the sprawl of languages makes it hard to add significant new\nfeatures/behaviour into the framework quickly (e.g. GraphQL or Protobuf support).\n\n**The \"shared core\"**\n\nWe have attempted to combat this time-to-market problem, by focussing on a shared implementation (the \"shared  core\")\nin many of the languages. We initially [bundled Ruby](https://docs.pact.io/wrapper_implementations), because it was \nconvenient, but have been slowly moving to our [Rust core](https://github.com/pact-foundation/pact-reference) which \nsolves many of the challenges that bundling Ruby presented.\n\nIt is worth noting that the \"shared core\" approach has largely been a successful exercise in this regard. There are \nmany data points, but the implementation of [WIP/Pending pacts](http://docs.pact.io/pending) was released (elapsed, \nnot effort) in just a few weeks for the libraries that wrapped Ruby. In most cases, an update of the Ruby \"binaries\", \nmapping flags from the language specific API to dispatch to the underlying Ruby process, a README update and a release\nwas all that was required. In many cases, new functionality is still published with an update to the Ruby binary, which\nhas been automated through a script.\n\n**Moving beyond HTTP**\n\nBut, the industry has continued to innovate since Pact was created in 2013, and RESTful microservices are only one of \nthe key use cases these days - protocols such as Protobufs and Graphql, transports such as TCP, UDP and HTTP/2 and \ninteraction modes (e.g. streaming or server initiated) are starting to become the norm. Standards such as AsyncAPI and \nCloudEvent are also starting to emerge.\n\nFor example, Pact is still a rather HTTP centric library, and the [mixed success](https://docs.pact.io/roadmap/feature_support)\nin retrofitting \"message support\" into all languages shows that extensions outside of this boundary aren't trivial, \nand in some respects are a second class citizen.\n\nThe reason is simple: HTTP doesn't change very often, so once a language has implemented a sensible DSL for it and \nintegrated to the core, it's more a matter of fine tuning things. Adding message pact is a paradigm shift relative to \nHTTP, and requires a whole new developer experience of authoring tests, integrating to the core and so on, for the \nlanguage author to consider.\n\nBeing able to mix and match `protocol`, `transport` and `interaction mode` would be helpful in expanding the use cases. \n\nFurther, being able to add custom contract testing behaviour for bespoke use cases would be helpful in situations where \nwe can't justify the effort to build into the framework itself (custom protocols in banking such as AS2805 come to mind).\n\nTo give some sense of magnitude to the challenge, this table shows some of the Pact deficiencies across popular \nmicroservice deployments.\n\n![83211994-ced39200-a1a1-11ea-8804-19b633cbb1d6](https://user-images.githubusercontent.com/53900/103729694-1e7e1400-5035-11eb-8d4e-641939791552.png)\n\nThe \"shared core\" approach can only take us so far, and we need another mechanism for extending behaviour outside of \nthe responsibilities of this core. This is where I see a plugin approach working with our \"shared core\" model.\n","funding_links":["https://opencollective.com/pact-foundation","https://pactflow.io"],"categories":["Rust","rust"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpact-foundation%2Fpact-plugins","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpact-foundation%2Fpact-plugins","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpact-foundation%2Fpact-plugins/lists"}