Implementation:MaterializeInc Materialize Mzcompose Run Command
| Knowledge Sources | misc/python/materialize/cli/mzcompose.py
|
|---|---|
| Domains | Integration Testing, CLI Tooling, Docker Compose |
| Last Updated | 2026-02-08 |
Overview
Concrete CLI tool for running Materialize integration tests and Docker Compose workflows, provided by the mzcompose command in materialize.cli.mzcompose.
Description
The mzcompose CLI is the entry point for executing Materialize integration tests. The main() function sets up an argument parser with global options and registers subcommands including RunCommand, BuildCommand, DownCommand, SqlCommand, and many more that mirror Docker Compose commands.
The RunCommand.handle_composition() method is the primary entry point for test execution. It implements smart dispatch: when the workflow argument matches a named workflow in the composition, it executes the Python workflow function wrapped in a test case; otherwise, it delegates to Docker Compose's run command for service-level execution. For workflow execution, it also injects CI extra arguments from the CI_EXTRA_ARGS environment variable and generates JUnit XML reports.
Usage
Use this CLI when:
- Running a specific integration test locally:
mzcompose --find test/my-test run default. - Listing available workflows:
mzcompose --find test/my-test list-workflows. - Debugging by running individual services:
mzcompose --find test/my-test up materialized. - Tearing down test environments:
mzcompose --find test/my-test down -v.
Code Reference
Source Location
| Component | File | Lines |
|---|---|---|
main() |
misc/python/materialize/cli/mzcompose.py |
L57-166 |
RunCommand.handle_composition() |
misc/python/materialize/cli/mzcompose.py |
L743-801 |
Signature
main():
def main(argv: list[str]) -> None
RunCommand.handle_composition():
def handle_composition(
self, args: argparse.Namespace, composition: Composition
) -> None
Import
from materialize.cli.mzcompose import main
I/O Contract
Inputs
| Parameter | Type | Description |
|---|---|---|
argv (main) |
list[str] |
Command-line arguments, typically sys.argv[1:]
|
--find DIR |
CLI flag | Directory containing the mzcompose.py file to use
|
--preserve-ports |
CLI flag | Bind container ports to matching host ports instead of random ports |
--project-name |
CLI flag | Override the Docker Compose project name |
--host-network |
CLI flag | Use host networking instead of Docker bridge networking |
--sanity-restart-mz |
CLI flag | Restart Materialized at end of tests for sanity checking; enabled by default on non-PR test pipelines and release branches |
args.workflow (handle_composition) |
str |
The workflow name or Docker Compose service to run |
args.unknown_subargs |
list[str] |
Additional arguments passed through to the workflow function |
CI_EXTRA_ARGS |
Environment variable | JSON dict mapping Buildkite step keys to extra argument strings |
Outputs
| Output | Type | Description |
|---|---|---|
| Exit code | int |
0 on success, non-zero on failure |
| JUnit XML report | File | Generated when running in CI; contains test case results with timing |
UIError |
Exception | Raised when at least one test case fails, with message "at least one test case failed"
|
| stdout/stderr | Stream | Test output including SQL statements, testdrive output, and Docker Compose logs |
Usage Examples
Running the default workflow for a test:
# From the repository root
bin/mzcompose --find test/testdrive run default
Running a specific workflow with extra arguments:
bin/mzcompose --find test/cluster run default --num-replicas=3
Running with preserved ports for debugging:
bin/mzcompose --find test/testdrive --preserve-ports run default
Listing available workflows:
bin/mzcompose --find test/testdrive list-workflows
Programmatic invocation:
from materialize.cli.mzcompose import main
# Equivalent to: mzcompose --find test/testdrive run default
main(["--find", "test/testdrive", "run", "default"])
How CI invokes a test (via the mzcompose plugin):
# The Buildkite mzcompose plugin effectively runs:
mzcompose --find test/testdrive run default
How handle_composition dispatches workflows:
# Inside RunCommand.handle_composition():
# If args.workflow is a known workflow name:
with composition.test_case(f"workflow-{args.workflow}"):
composition.workflow(args.workflow, *args.unknown_subargs[1:], *extra_args)
# If args.workflow is NOT a known workflow (it's a Docker Compose service):
composition.invoke("up", "-d", "--scale", f"{args.workflow}=0", args.workflow)
# Then delegates to docker compose run