RepoPilotOpen in app →

pact-foundation/pact-ruby

Enables consumer driven contract testing, providing a mock service and DSL for the consumer project, and interaction playback and verification for the service provider project.

Healthy

Healthy across the board

Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 3w ago
  • 7 active contributors
  • MIT licensed
Show 3 more →
  • CI configured
  • Tests present
  • Concentrated ownership — top contributor handles 59% of recent commits

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/pact-foundation/pact-ruby)](https://repopilot.app/r/pact-foundation/pact-ruby)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/pact-foundation/pact-ruby on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: pact-foundation/pact-ruby

Generated by RepoPilot · 2026-05-10 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/pact-foundation/pact-ruby shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across the board

  • Last commit 3w ago
  • 7 active contributors
  • MIT licensed
  • CI configured
  • Tests present
  • ⚠ Concentrated ownership — top contributor handles 59% of recent commits

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live pact-foundation/pact-ruby repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/pact-foundation/pact-ruby.

What it runs against: a local clone of pact-foundation/pact-ruby — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in pact-foundation/pact-ruby | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 49 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>pact-foundation/pact-ruby</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of pact-foundation/pact-ruby. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/pact-foundation/pact-ruby.git
#   cd pact-ruby
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of pact-foundation/pact-ruby and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "pact-foundation/pact-ruby(\\.git)?\\b" \\
  && ok "origin remote is pact-foundation/pact-ruby" \\
  || miss "origin remote is not pact-foundation/pact-ruby (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "lib/pact.rb" \\
  && ok "lib/pact.rb" \\
  || miss "missing critical file: lib/pact.rb"
test -f "lib/pact/consumer.rb" \\
  && ok "lib/pact/consumer.rb" \\
  || miss "missing critical file: lib/pact/consumer.rb"
test -f "lib/pact/configuration.rb" \\
  && ok "lib/pact/configuration.rb" \\
  || miss "missing critical file: lib/pact/configuration.rb"
test -f "lib/pact/matchers.rb" \\
  && ok "lib/pact/matchers.rb" \\
  || miss "missing critical file: lib/pact/matchers.rb"
test -f "lib/pact/consumer/mock_server.rb" \\
  && ok "lib/pact/consumer/mock_server.rb" \\
  || miss "missing critical file: lib/pact/consumer/mock_server.rb"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 49 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~19d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/pact-foundation/pact-ruby"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Pact Ruby is a consumer-driven contract testing framework built on pact-ffi and pact-ruby-ffi that enables both consumers and providers to verify API contracts. It provides RSpec DSL support for writing contract tests across HTTP, gRPC, and async message transports (Kafka), generating shareable Pact specification files (v4) that serve as executable contracts between microservices without requiring the actual provider to run. Monorepo structure: lib/ contains the core DSL and matcher implementations; example/zoo-app (consumer) and example/animal-service (provider) demonstrate the two-sided interaction; spec/pact/providers/ follows the convention for consumer tests (which paradoxically live under 'providers' subdirectory). Pact files are generated to doc/pacts/. The bin/pact CLI wraps core functionality; .github/workflows/ orchestrates releases and testing.

👥Who it's for

Ruby/RSpec developers building microservices who need to verify API contracts between consumers (e.g., Zoo App) and providers (e.g., Animal Service) without tight coupling or running full integration tests. Both frontend teams writing consumer tests and backend teams verifying provider compliance use this.

🌱Maturity & risk

Production-ready and actively maintained. The project has moved from v1 (pure Ruby) to v2+ (pact-ffi based) with comprehensive CI/CD pipelines (.github/workflows/test.yml, release_gem.yml), a detailed CHANGELOG.md and RELEASING.md, and example applications (example/zoo-app, example/animal-service) demonstrating all transport types. Recent architecture is documented in documentation/ with pact architecture diagrams.

Low risk for established use cases (HTTP contract testing), but moderate risk for newer transport types (gRPC, async messages) which are less mature in the Ruby ecosystem. Dependency on pact-ffi binary gems limits platform support (8 platforms listed in README); musl/arm64 users may face friction. The v2 migration introduced breaking changes requiring users to update from v1, suggesting API stability concerns.

Active areas of work

Actively maintained with focus on v2 maturity: supporting mixed v4 pact interactions, expanding non-HTTP transport support (gRPC, messages), and ensuring all transport types have parity in the DSL. The ROADMAP.md and recent release workflows suggest ongoing work on stability and cross-platform binary support.

🚀Get running

Clone and install: git clone https://github.com/pact-foundation/pact-ruby.git && cd pact-ruby && bundle install. Examine example projects: cd example/zoo-app && bundle install && bundle exec rspec spec/pact --tag pact to see consumer tests, and cd ../animal-service && bundle exec rspec spec/pact to see provider verification.

Daily commands: For consumer tests (Zoo App): cd example/zoo-app && bundle exec rspec spec/pact --tag pact. For provider verification (Animal Service): cd example/animal-service && bundle exec rspec spec/pact --tag pact. For the full gem release workflow: bundle exec rake (see Rakefile for test targets).

🗺️Map of the codebase

  • lib/pact.rb — Main entry point that exports all public Pact APIs; every consumer and provider test imports from here
  • lib/pact/consumer.rb — Consumer-side DSL entry point; defines the interaction builder interface and contract setup for consumer tests
  • lib/pact/configuration.rb — Global configuration system managing mock server ports, log levels, and pact file output paths
  • lib/pact/matchers.rb — Matcher DSL facade; exposes v1–v4 matchers for flexible contract assertions across pact specification versions
  • lib/pact/consumer/mock_server.rb — Core mock server orchestrator; manages lifecycle and request/response mocking for HTTP and gRPC providers
  • lib/pact/consumer/http_interaction_builder.rb — HTTP interaction DSL builder; translates Ruby fluent API into pact-ffi interaction objects for HTTP contracts
  • lib/pact/consumer/pact_config.rb — Configuration registry for multiple transport types (HTTP, gRPC, Message); routes interaction building to correct handler

🛠️How to make changes

Add a new HTTP consumer contract

  1. Create a new RSpec file under example/*/spec/pact/consumers/ (or your test folder) (example/zoo-app/spec/pact/consumers/http_client_spec.rb)
  2. Import Pact and use Pact.define_interaction to set up request/response expectations (lib/pact/consumer.rb)
  3. Use lib/pact/consumer/http_interaction_builder.rb API methods (.given, .upon_request, .will_respond_with) to define interactions (lib/pact/consumer/http_interaction_builder.rb)
  4. Use matchers from lib/pact/matchers.rb (e.g., string, integer, array_containing) to assert flexible payloads (lib/pact/matchers.rb)
  5. Run RSpec; pact file automatically written to pact_dir (configured in lib/pact/configuration.rb) (lib/pact/configuration.rb)

Add support for a new transport type (e.g., WebSocket)

  1. Create a new interaction builder class at lib/pact/consumer/websocket_interaction_builder.rb, inheriting from base pattern (lib/pact/consumer/http_interaction_builder.rb)
  2. Create a new pact config handler at lib/pact/consumer/pact_config/websocket.rb (lib/pact/consumer/pact_config/http.rb)
  3. Register the handler in lib/pact/consumer/pact_config.rb factory method (load_transport_config) (lib/pact/consumer/pact_config.rb)
  4. Call pact-ffi binding for WebSocket interaction creation; ensure mock_server.rb routes WebSocket requests (lib/pact/consumer/mock_server.rb)

Add a new v3+ matcher

  1. Create a new class at lib/pact/matchers/v3/my_matcher.rb (or v4/) inheriting from lib/pact/matchers/base.rb (lib/pact/matchers/v3/integer.rb)
  2. Implement to_json and to_hash to serialize into pact-ffi matcher JSON format (lib/pact/matchers/base.rb)
  3. Export factory method from lib/pact/matchers.rb (e.g., Pact.my_matcher(arg)) (lib/pact/matchers.rb)
  4. Add test under spec/pact/matchers/ and verify serialization format matches Pact spec (lib/pact/matchers/v3/boolean.rb)

Verify a provider against a pact file

  1. Create a provider verification spec under example/animal-service/spec/pact/ or use Rakefile tasks (example/animal-service/spec/pact/consumers/http_spec.rb)
  2. Load pact file(s) from pact_dir using Pact::Provider API (not directly in repo, handled by pact-ffi) (lib/pact/configuration.rb)
  3. Start provider server (e.g., Rails API) on known port (example/animal-service/lib/animal_service/api.rb)
  4. Run RSpec with provider verification task; pact-ffi replays interactions and validates provider responses (Rakefile)

🔧Why these technologies

  • pact-ffi + FFI gem — Wraps Rust pact-core library for cross-language compatibility and modern pact specification support (v3–v4); avoids reimplementing matcher logic and mock server in pure Ruby

🪤Traps & gotchas

  1. Consumer tests must live in spec/pact/providers/** (not spec/pact/consumers) — the 'providers' subdirectory is intentional because consumer tests run against different provider mocks. 2. :pact tag is required (RSpec.describe 'name', :pact) so tests don't run in normal CI/CD pipelines. 3. pact-ffi binary gems must match your platform exactly (x86_64-linux, arm64-darwin, etc.) or bundle install will fail; musl/aarch64 users need specific gems. 4. Mock servers are transport-specific (HTTP, gRPC, message); mismatching DSL to transport causes cryptic errors. 5. Pact files generated in doc/pacts/ must be committed to git and shared with providers — they are source-of-truth contracts.

🏗️Architecture

💡Concepts to learn

  • Consumer-Driven Contract Testing — The core philosophy of Pact: consumers define what they expect from providers via contracts, inverted from traditional provider-first API specs; understanding this paradigm is essential to using pact-ruby effectively.
  • Pact Specification (V4) — pact-ruby v2 generates V4 spec files supporting mixed interaction types (HTTP, gRPC, async) in one Pact; you must understand the JSON structure to debug generated contracts and verify compliance.
  • FFI (Foreign Function Interface) — pact-ruby v2 delegates core logic to pact-ffi (Rust bindings via Ruby's FFI gem); understanding FFI limitations (platform-specific binaries, marshalling) explains why gem installation is platform-sensitive.
  • Mock Server / Verification — Pact uses embedded mock servers (HTTP, gRPC, async) to intercept interactions during consumer tests and verify them against provider implementations; understanding the server lifecycle is critical for debugging test failures.
  • Matchers (eachLike, like, term, uuid, etc.) — Matchers in Pact serialize special logic into the contract JSON so providers know to match by pattern, not exact value; misusing matchers breaks contract semantics.
  • Interaction Types (HTTP, gRPC, Async Message) — pact-ruby provides separate DSL variants (has_http_pact_between, has_grpc_pact_between, has_message_pact_between) because serialization, transport, and verification differ; choosing the wrong type causes silent failures.
  • Pact File Sharing & Broker Integration — Generated pact files in doc/pacts/ are version-controlled artifacts shared with providers (often via Pact Broker); understanding this artifact model is essential for CI/CD pipeline design, referenced in RELEASING.md.
  • pact-foundation/pact-reference — Rust/Go reference implementation of Pact spec; pact-ruby v2+ wraps its FFI bindings
  • pact-foundation/pact-js — JavaScript/TypeScript equivalent providing HTTP and message contract testing for Node.js ecosystems
  • pact-foundation/pact-python — Python implementation of Pact; users migrating between languages or in polyglot teams reference it
  • smartbear/pact-go — Go implementation of Pact; widely used for microservice contract testing in Go shops and referenced in companion tools
  • pact-foundation/pact-broker — Central repository for sharing pact files between consumer and provider teams; integral to Pact CI/CD workflows documented in RELEASING.md

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive unit tests for lib/pact/consumer/message_interaction_builder.rb

The message_interaction_builder.rb is a core DSL component for async message contract testing (Kafka, etc.), but there are no dedicated test files visible in the repo structure. Given that pact-ruby v2+ added async message support as a major feature (per README), this builder needs robust test coverage to ensure reliability across different message transport scenarios.

  • [ ] Create spec/pact/consumer/message_interaction_builder_spec.rb with unit tests
  • [ ] Test message payload definition with various data types
  • [ ] Test metadata/header assertions for message interactions
  • [ ] Test integration with Pact matchers for message content validation
  • [ ] Add tests for error cases (invalid message formats, missing required fields)
  • [ ] Reference example/zoo-app patterns if message testing examples exist

Add gRPC integration tests and documented examples in example/grpc-service

The lib/pact/consumer/grpc_interaction_builder.rb exists as a core feature for non-HTTP transport testing, but there's no corresponding example in the example/ directory (only animal-service and zoo-app which use HTTP). The README mentions gRPC support as a key v2+ feature but lacks concrete working examples.

  • [ ] Create example/grpc-service/ directory mirroring animal-service structure
  • [ ] Implement a simple gRPC service definition (proto file)
  • [ ] Add spec/pact/consumers/grpc_spec.rb demonstrating gRPC Pact DSL usage
  • [ ] Create documentation/grpc_example.md with step-by-step walkthrough
  • [ ] Include gRPC client implementation in example/grpc-service/lib/
  • [ ] Add Rakefile task to run gRPC example tests

Complete and test lib/pact/configuration.rb edge cases and add feature documentation

The configuration.rb file exists but there's no dedicated documentation (documentation/configuration.md exists in the file list but appears minimal). Configuration is critical for Pact's mock servers, verification modes, and output paths. New contributors need clear guidance on all available config options.

  • [ ] Audit lib/pact/configuration.rb for all configurable settings
  • [ ] Add unit tests in spec/pact/configuration_spec.rb for: default values, environment variable overrides, invalid config combinations, and mock server port binding
  • [ ] Expand documentation/configuration.md with a comprehensive table of all config options, defaults, and examples
  • [ ] Add tests for mock server configuration (HTTP, gRPC, message broker settings)
  • [ ] Document the interaction between global Pact.configure blocks and test-level overrides

🌿Good first issues

  • Add comprehensive matcher tests for gRPC transport: lib/pact/matchers/ currently has HTTP-focused specs; a contributor could add test coverage for how matchers serialize in protobuf contexts (example/animal-service lacks gRPC examples).
  • Document the consumer test directory convention (spec/pact/providers/...) with a diagram in documentation/configuration.md: current README mentions it briefly but new users consistently misplace tests.
  • Expand example/zoo-app/spec/pact/consumers/http_spec.rb with realistic async message interaction examples (Kafka, RabbitMQ) since has_message_pact_between is documented but no runnable example exists.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 2d2ab0a — docs: update docs for docusaurus upgrade (kevinrvaz)
  • 6d77e25 — chore(docs): Fix broken image link in README.md (#398) (samsm)
  • 0ca5246 — chore(deps): update dependency ruby to v3.4.9 (renovate[bot])
  • 9450678 — chore(deps): update actions/checkout action to v6 (renovate[bot])
  • 1f917ac — chore(release): version 2.0.0 (YOU54F)
  • 7f3dc96 — ci: add plugin for tests [skip ci] (YOU54F)
  • 448a043 — chore: revert version to v1.67.5 (YOU54F)
  • 1cc97ec — feat(v2): move pact/v2 to pact namespace (#397) (YOU54F)
  • 1658a0b — chore(docs): update link to v2 docs (YOU54F)
  • 6cb9a65 — chore(release): version 1.67.5 (YOU54F)

🔒Security observations

The pact-ruby repository demonstrates a generally secure posture for a testing framework library. The primary concerns are operational/configuration issues rather than inherent code vulnerabilities: a SQLite database file committed to version control, lack of formal security reporting policy, and potential risks from the plugin architecture that require code review. No hardcoded secrets or credentials were identified in the file structure. The library's focus on contract testing and mocking makes it lower-risk than production data processing systems, but the plugin system should be reviewed for potential untrusted code execution risks.

  • Medium · SQLite Database File in Version Control — example/animal-service/db/animal_db.sqlite3. The file 'example/animal-service/db/animal_db.sqlite3' appears to be a SQLite database file committed to the repository. Database files should not be stored in version control as they may contain sensitive data or test fixtures that could be exploited. Fix: Remove the database file from version control, add *.sqlite3 to .gitignore, and provide instructions for initializing the database schema instead.
  • Low · Missing CHANGELOG Security Notices — Repository root. The repository contains a CHANGELOG.md file but there is no evidence of a dedicated SECURITY.md file or security policy documentation visible in the file structure. This makes it difficult for security researchers to report vulnerabilities responsibly. Fix: Create a SECURITY.md file following GitHub's security policy template to provide clear instructions for reporting security vulnerabilities.
  • Low · Potential Insecure Deserialization in Mock Server — lib/pact/consumer/mock_server.rb. The codebase includes mock server implementations (lib/pact/consumer/mock_server.rb) that handle JSON/protocol interactions. Without reviewing the implementation, there's a potential risk of insecure deserialization if user-controlled data is processed without proper validation. Fix: Conduct code review to ensure all deserialization operations validate input data types and schemas. Use allowlists for expected data structures.
  • Low · Plugin System Potential Attack Vector — lib/pact/consumer/plugin_*_interaction_builder.rb files. The codebase includes plugin support (plugin_async_message_interaction_builder.rb, plugin_http_interaction_builder.rb, plugin_sync_message_interaction_builder.rb). Plugin systems can be security risks if plugins are loaded from untrusted sources or without proper validation. Fix: Implement strict plugin validation, sandboxing, and code signing. Document plugin security requirements and only load plugins from trusted sources.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.