Skip to content

Conversation

@YOU54F
Copy link
Member

@YOU54F YOU54F commented Oct 8, 2025

📝 Summary of Changes

Changes proposed in this pull request:

  • Modifications to allow pact_verifier_cli to be consumed as a library pact_verifier_cli so it can be composed in other clis

⚠️ Items of Note

Part of a series of pull requests

💁 Example

Composed cli: https://github.com/YOU54F/pact_cli/blob/259a268dd9e7fa48ad03c088f7244af7a4c89493/src/cli.rs#L11-L29

pub fn build_cli() -> Command {
    let app = Command::new("pact_cli")
        .about("A pact cli tool")
        .subcommand(
            pact_broker_cli::cli::pact_broker_client::add_pact_broker_client_command()
                .name("pact-broker")
                .subcommand(add_standalone_broker_subcommand())
                .subcommand(add_docker_broker_subcommand()),
        )
        .args(pact_broker_cli::cli::add_logging_arguments())
        .subcommand(
            pact_broker_cli::cli::pactflow_client::add_pactflow_client_command().name("pactflow"),
        )
        .subcommand(add_completions_subcommand())
        .subcommand(pact_plugin_cli::Cli::command().name("plugin"))
        .subcommand(pact_mock_server_cli::setup_args().name("mock"))
        .subcommand(pact_verifier_cli::args::setup_app().name("verifier"))
        .subcommand(pact_stub_server_cli::build_args().name("stub"));
    app
}

Cargo toml: https://github.com/YOU54F/pact_cli/blob/259a268dd9e7fa48ad03c088f7244af7a4c89493/Cargo.toml#L67-L71

pact-stub-server = { version = "*", git = "https://github.com/YOU54F/pact-stub-server.git", branch = "feat/cli_as_lib"}
pact_mock_server_cli = { version = "2.0.0-beta.1", git = "https://github.com/YOU54F/pact-core-mock-server.git", branch = "feat/cli_as_lib"}
pact-plugin-cli = { version = "*", git = "https://github.com/YOU54F/pact-plugins", branch = "feat/cli_as_lib"}
pact_verifier_cli = { version = "*",  git = "https://github.com/YOU54F/pact-reference", branch = "feat/cli_as_lib"}
pact-broker-cli = { version = "*", git = "https://github.com/YOU54F/pact-broker-cli", branch = "main"}

🔨 How To Test

git clone [email protected]:YOU54F/pact_cli.git
cd pact_cli
git checkout multi-cli
RUSTFLAGS=-Awarnings cargo run -q --

output

A pact cli tool

Usage: pact_cli [OPTIONS] [COMMAND]

Commands:
  pact-broker  
  pactflow     
  completions  Generates completion scripts for your shell
  plugin       CLI utility for Pact plugins
  mock         Standalone Pact mock server
  verifier     Standalone pact verifier for provider pact verification
  stub         Pact Stub Server 0.6.3
  help         Print this message or the help of the given subcommand(s)

Options:
      --log-level <LEVEL>  Set the log level (none, off, error, warn, info, debug, trace) [default: off] [possible values: off, none, error, warn, info, debug, trace]
  -h, --help               Print help

usage

Standalone pact verifier for provider pact verification

Usage: pact_cli verifier [OPTIONS]

Options:
      --help               Print help and exit
      --log-level <LEVEL>  Set the log level (none, off, error, warn, info, debug, trace) [default: off] [possible values: off, none, error, warn, info, debug, trace]
  -v, --version            Print version information and exit

Logging options:
  -l, --loglevel <loglevel>  Log level to emit log events at (defaults to warn) [possible values: error, warn, info, debug, trace, none]
      --pretty-log           Emits excessively pretty, multi-line logs, optimized for human readability.
      --full-log             This emits human-readable, single-line logs for each event that occurs, with the current span context displayed before the formatted representation of the event.
      --compact-log          Emit logs optimized for short line lengths.
  -j, --json <json-file>     Generate a JSON report of the verification [env: PACT_VERIFIER_JSON_REPORT=]
  -x, --junit <junit-file>   Generate a JUnit XML report of the verification (requires the junit feature) [env: PACT_VERIFIER_JUNIT_REPORT=]
      --no-colour            Disables ANSI escape codes in the output [aliases: --no-color]

Loading pacts options:
  -f, --file <file>
          Pact file to verify (can be repeated)
  -d, --dir <dir>
          Directory of pact files to verify (can be repeated)
  -u, --url <url>
          URL of pact file to verify (can be repeated)
  -b, --broker-url <broker-url>
          URL of the pact broker to fetch pacts from to verify (requires the provider name parameter) [env: PACT_BROKER_BASE_URL=]
      --webhook-callback-url <webhook-callback-url>
          URL of a Pact to verify via a webhook callback. Requires the broker-url to be set. [env: PACT_WEBHOOK_CALLBACK_URL=]
      --ignore-no-pacts-error
          Do not fail if no pacts are found to verify

Authentication options:
      --user <user>          Username to use when fetching pacts from URLS [env: PACT_BROKER_USERNAME=]
      --password <password>  Password to use when fetching pacts from URLS [env: PACT_BROKER_PASSWORD=]
  -t, --token <token>        Bearer token to use when fetching pacts from URLS [env: PACT_BROKER_TOKEN=]

Provider options:
  -h, --hostname <hostname>
          Provider hostname (defaults to localhost) [env: PACT_PROVIDER_HOSTNAME=]
  -p, --port <port>
          Provider port (defaults to protocol default 80/443) [env: PACT_PROVIDER_PORT=]
      --transport <transport>
          Provider protocol transport to use (http, https, grpc, etc.) [env: PACT_PROVIDER_TRANSPORT=] [default: http]
      --transports <transports>
          Allows multiple protocol transports to be configured (http, https, grpc, etc.) with their associated port numbers separated by a colon. For example, use --transports http:8080 grpc:5555 to configure both.
  -n, --provider-name <provider-name>
          Provider name (defaults to provider) [env: PACT_PROVIDER_NAME=]
      --base-path <base-path>
          Base path to add to all requests [env: PACT_PROVIDER_BASE_PATH=]
      --request-timeout <request-timeout>
          Sets the HTTP request timeout in milliseconds for requests to the target API and for state change requests. [env: PACT_PROVIDER_REQUEST_TIMEOUT=]
  -H, --header <custom-header>
          Add a custom header to be included in the calls to the provider. Values must be in the form KEY=VALUE, where KEY and VALUE contain ASCII characters (32-127) only. Can be repeated.
      --disable-ssl-verification
          Disables validation of SSL certificates

Provider state options:
  -s, --state-change-url <state-change-url>
          URL to post state change requests to [env: PACT_PROVIDER_STATE_CHANGE_URL=]
      --state-change-as-query
          State change request data will be sent as query parameters instead of in the request body [env: PACT_PROVIDER_STATE_CHANGE_AS_QUERY=]
      --state-change-teardown
          State change teardown requests are to be made after each interaction [env: PACT_PROVIDER_STATE_CHANGE_TEARDOWN=]

Filtering interactions:
      --filter-description <filter-description>
          Only validate interactions whose descriptions match this filter (regex format) [env: PACT_DESCRIPTION=]
      --filter-state <filter-state>
          Only validate interactions whose provider states match this filter (regex format) [env: PACT_PROVIDER_STATE=]
      --filter-no-state
          Only validate interactions that have no defined provider state [env: PACT_PROVIDER_NO_STATE=]
  -c, --filter-consumer <filter-consumer>
          Consumer name to filter the pacts to be verified (can be repeated)

Publishing options:
      --publish
          Enables publishing of verification results back to the Pact Broker. Requires the broker-url and provider-version parameters.
      --provider-version <provider-version>
          Provider version that is being verified. This is required when publishing results.
      --build-url <build-url>
          URL of the build to associate with the published verification results.
      --provider-tags <provider-tags>
          Provider tags to use when publishing results. Accepts comma-separated values.
      --provider-branch <provider-branch>
          Provider branch to use when publishing results

Pact Broker options:
      --consumer-version-tags <consumer-version-tags>
          Consumer tags to use when fetching pacts from the Broker. Accepts comma-separated values.
      --consumer-version-selectors <consumer-version-selectors>
          Consumer version selectors to use when fetching pacts from the Broker. Accepts a JSON string as per https://docs.pact.io/pact_broker/advanced_topics/consumer_version_selectors/. Can be repeated.
      --enable-pending
          Enables Pending Pacts
      --include-wip-pacts-since <include-wip-pacts-since>
          Allow pacts that don't match given consumer selectors (or tags) to  be verified, without causing the overall task to fail. For more information, see https://pact.io/wip

Development options:
      --exit-on-first-error  Stops the verifier at the first failure
      --last-failed          Only runs the interactions that failed on the previous verifier run. Requires --json-file to have been set

@YOU54F
Copy link
Member Author

YOU54F commented Oct 22, 2025

todo - rename bin to pact-verifier

Copy link
Contributor

@JP-Ellis JP-Ellis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a couple of questions, but looking good!


```console
$ pact_verifier_cli,ignore
$ pact-verifier,ignore
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the ,ignore meant to be there?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it is there to prevent trycmd from failing, as pact-verifier with no args, prints help but with an exit code of 2

Updating to be --help would probably be better, as it will allow to auto testing and updating with TRYCMD_OVERWRITE=true cargo test

@@ -1,2 +1,2 @@
[package]
name = "pact_verifier_cli"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering... should we take the opportunity to rename this pact-verifier as well? Rust will automatically convert this to pact_verifier within the code.

To preserve compatibility, we can still have a library called pact_verifier_cli which is a shim to pact-verifier?

Copy link
Member Author

@YOU54F YOU54F Oct 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the idea of a shim, but we already have a pact_verifier crate, so that rename might be awkward.

for the mock-server and verifier they have

  • pact_verifier / pact_verifier_cli
  • pact_mock_server / pact_mock_server_cli

so maybe

  • pact-verifier / pact-verifier-cli
  • pact-mock-server / pact-mock-server-cli

unless we consolidate the cli functionality into their respective crates.

do we also consider the same the convention for the other crates

  • pact-models
  • pact-matching

etc

How would the shim work in practise? Interested.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do definitely agree with using the hyphens given that the majority of our tools are already using hyphens, but it also just slipped my mind that we have a separate pact-verifier crate already... You can disregard my previous comment 😅

I think that separate the CLI and library logic into separate crates make complete sense. E.g., pact-verifier and pact-verifier-cli. So the library can be used without pulling the (typically much heaver) CLI dependencies, and keeping the code clean.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hehe no worries, it a reasonable sized ecosystem so easy to forget!

we have a mix, i would say more snake_case ( pact-plugin-cli / pact-plugin-driver / pact-stub-server / pact-broker-cli are the only kebabs )

https://docs.pact.io/diagrams/ecosystem#rust-goldberg-machine

tl;dr - we can’t change case of existing crates, as they can’t be published to cargo. we can only provide guidance for new crates.

cli in a lib crate could work if deps and code are feature gated, but does increase complexity. a cli suffixed repo is clear in its purpose. if it is also available as a lib, it is for the purpose of composing cli libs.

snake_case here for me is fine as a crate name, as it matches up with how it will be used in rust code, as you need to downcase to import.

it will feel odd when doing cargo install pact_mock_server_cli to install the bin pact-mock-server, but most end users won’t use the binaries with cargo/rust projects, they will install via prebuilt means

anyway after doing some reading of rust rfcs, there is no consensus on convention.

a point that does make renaming moot, we can’t publish crates where they clash with existing name, kebab or snake case

pact_verifier cannot be uploaded to crates to pact-verifier.

if it wasn’t depended on, it could be deleted and republished with the new kebab case name, but our crate popularity precludes that

pact_verifier and pact-verifier are not equiv in cargo. they won’t normalise via cargo install or cargo add, in a Cargo.toml but is normalised to snake case in rust code for imports

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The namespace clash is interesting, and turns out, both are translated:

❯ cargo add serde-yaml
    Updating crates.io index
warning: translating `serde-yaml` to `serde_yaml`
      Adding serde_yaml v0.9.34 to dependencies
    Updating crates.io index
     Locking 14 packages to latest Rust 1.90.0 compatible versions
❯ cargo add serde_json_fmt
    Updating crates.io index
warning: translating `serde_json_fmt` to `serde-json-fmt`
      Adding serde-json-fmt v0.1.0 to dependencies
    Updating crates.io index
     Locking 7 packages to latest Rust 1.90.0 compatible versions
      Adding autocfg v1.5.0
      Adding memchr v2.7.6
      Adding serde-json-fmt v0.1.0
      Adding serde_json v1.0.145
      Adding smartstring v1.0.1
      Adding static_assertions v1.1.0
      Adding version_check v0.9.5

So perhaps I'm overthinking it 😅

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm works with cargo add but not cargo install, hmmm.

thanks for checking!

So perhaps I'm overthinking it 😅

If it worked both ways with cargo install, I think it would be quite nice. I think once the binaries are all renamed it'll be alright, it seems like rustaceans will be pretty aware of the wild west of snakes and kebabs at large, and have to adjust accordingly. For everyone else, they just get normalised kebab-case in all the cli's 👍🏾 🎉

Always happy to ponder hehe, overthink away

@YOU54F YOU54F merged commit 7af650b into pact-foundation:master Oct 31, 2025
41 of 44 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants