From 3d7b74bc7c3fd5b17e78e8c8e8900b5a845232c1 Mon Sep 17 00:00:00 2001 From: Yousaf Nabi Date: Tue, 18 Nov 2025 16:34:59 +0000 Subject: [PATCH 1/2] chore: add simple pact-python v3 verifier --- Makefile | 4 ++++ README.md | 5 ++--- app/test/app_spec.py | 20 ++++++++++++++++++++ docker-compose.yml | 4 ++-- requirements.txt | 1 + 5 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 app/test/app_spec.py diff --git a/Makefile b/Makefile index 945c2c7..f5533f3 100644 --- a/Makefile +++ b/Makefile @@ -47,6 +47,10 @@ test: .env test_native: .env docker compose up pact_verifier_native --exit-code-from pact_verifier_native docker compose logs pact_verifier_native +run_api: + docker compose up api +run_test_local: + python3 app/test/app_spec.py ## ===================== ## Deploy tasks diff --git a/README.md b/README.md index f2c573b..75ba03e 100644 --- a/README.md +++ b/README.md @@ -39,8 +39,7 @@ make test To run the "fake ci" task: ``` -export PACT_BROKER_BASE_URL=https://test.pactflow.io -export PACT_BROKER_USERNAME=dXfltyFMgNOFZAxr8io9wJ37iUpY42M -export PACT_BROKER_PASSWORD=O5AIZWxelWbLvqMd8PkAVycBJh2Psyg1 +export PACT_BROKER_BASE_URL="https://test.pactflow.io" +export PACT_BROKER_TOKEN="129cCdfCWhMzcC9pFwb4bw" make fake_ci ``` \ No newline at end of file diff --git a/app/test/app_spec.py b/app/test/app_spec.py new file mode 100644 index 0000000..490fea3 --- /dev/null +++ b/app/test/app_spec.py @@ -0,0 +1,20 @@ +import os +from pact import Verifier +import pact_ffi + +def test_provider(): + """Test the provider against the consumer contract.""" + pact_ffi.log_to_stderr("DEBUG") + verifier = ( + Verifier("pactflow-example-provider-python") # Provider name + .add_transport(url="http://localhost:8000") + .broker_source( + os.environ.get("PACT_BROKER_BASE_URL", "https://broker.pactflow.io/"), + token=os.environ.get("PACT_BROKER_TOKEN", "broker-token"), # or use token="bearer-token" + ) + ) + + verifier.verify() + +if __name__ == "__main__": + test_provider() \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 56598b0..850199e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,8 +4,8 @@ services: context: . volumes: - ./app:/app - expose: - - "8000" + ports: + - 8000:8000 environment: - PORT=8000 diff --git a/requirements.txt b/requirements.txt index 0907dc7..cc5fe56 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ fastapi==0.121.2 uvicorn==0.38.0 +pact-python==3.1.0 From ac1a719d275a53cb952c8ccaf1cd919caa2445dd Mon Sep 17 00:00:00 2001 From: Yousaf Nabi Date: Tue, 18 Nov 2025 16:42:40 +0000 Subject: [PATCH 2/2] chore: set reproducer based on https://github.com/pact-foundation/pact-python/issues/1333 --- app/test/app_spec.py | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/app/test/app_spec.py b/app/test/app_spec.py index 490fea3..051c871 100644 --- a/app/test/app_spec.py +++ b/app/test/app_spec.py @@ -2,18 +2,45 @@ from pact import Verifier import pact_ffi +from typing import Literal, Any + +def provider_state_handler( + state: str, + action: Literal["setup", "teardown"], + parameters: dict[str, Any] | None, +) -> None: + """Handle all provider state changes.""" + parameters = parameters or {} + if state == "a product with ID 10 exists": + if action == "setup": + return + if action == "teardown": + return + msg = f"Unknown state/action: {state}/{action}" + raise ValueError(msg) + + def test_provider(): """Test the provider against the consumer contract.""" pact_ffi.log_to_stderr("DEBUG") verifier = ( Verifier("pactflow-example-provider-python") # Provider name .add_transport(url="http://localhost:8000") + .state_handler(provider_state_handler, teardown=False) .broker_source( - os.environ.get("PACT_BROKER_BASE_URL", "https://broker.pactflow.io/"), - token=os.environ.get("PACT_BROKER_TOKEN", "broker-token"), # or use token="bearer-token" + url=os.environ.get("PACT_BROKER_BASE_URL", "https://broker.pactflow.io/"), + token=os.environ.get("PACT_BROKER_TOKEN", "broker-token"), + selector=True ) + .consumer_versions('{"mainBranch": true}', '{"deployedOrReleased": true}') + .include_pending() + .include_wip_since("2025-11-10") + .build() ) - + # verifier.set_publish_options( + # version="123", + # branch="foo", + # ) verifier.verify() if __name__ == "__main__":