kylekatarnls/multi-tester
multi-tester runs the unit tests of dependent projects against your local package changes by swapping your code into their vendor directory, with Travis CI support.
Release gating for shared Composer packages. The core capability is: take the current working copy of your package, drop it into each known consumer's vendor/ directory, and run that consumer's suite. This turns "we believe this is backwards compatible" into an evidenced ship/no-ship decision. It's the artifact you point at when a downstream team reports breakage the day after a tag — or the evidence that prevents the tag.
Support-matrix policy: what we actually claim to support. .multi-tester.yml lets you pin a consumer to a constraint (symfony/symfony:5.4.*) or run the same package at several versions via the package:constraint entry syntax. That makes "we support Laravel 10 and 11" or "we support Symfony 5.4 through 7" a tested assertion instead of a README sentence. It also forces an explicit product decision: how wide is the matrix before CI minutes and maintainer attention become the real constraint?
Build vs. buy for cross-repo integration testing. The alternative is a bespoke CI job per consumer — clone, patch vendor/, composer install, run tests — duplicated N times and owned by whoever wrote it. Here that's one YAML file and a dev dependency. The honest framing is a cheap experiment, not a platform commitment: a sub-hour spike (--add=org/project, accept defaults) that you can throw away if it doesn't pay for itself.
Monorepo vs. multi-repo, and internal package strategy. If you're debating splitting a package out of an application, or consolidating several packages, the precondition is being able to prove the split doesn't break consumers on every commit. Lowering the cost of that verification lowers the cost of the structural decision — which is often the decision that actually matters.
CI topology and budget. One job covering N downstream projects (with stop_on_failure for fast feedback and success_only to avoid chasing already-red upstreams) versus N duplicated pipeline definitions. Relevant when CI minutes are a line item, and more so for open-source maintainers paying in volunteer time.
PR review quality on dependency changes. Widening a constraint or bumping a major dependency is exactly the change where reviewers lack information. A multi-tester run attached to the PR converts a "looks fine, semver says minor" approval into a verified one.
Open-source maintainer triage. For a package with external consumers, this reduces the "works on my machine, breaks for them" support load — the most expensive kind of issue because it's rarely reproducible from the report alone.
Adopt when most of these hold:
--add path plus defaults is a genuine spike, and the config is declarative enough to delete without residue.Look elsewhere when:
script you hand it — it is not a test framework, fixture manager, or environment orchestrator. Consumers needing databases, queues, or browsers need their own harness; multi-tester becomes a fragile wrapper around it.For executives — one paragraph: We ship a Composer package that other teams depend on. Today, we find out we broke them after release, usually from a support ticket. This tool lets us run our customers' test suites against our unreleased code before we tag — the same way we'd run our own tests, but for the people downstream. Cost is one dev dependency and a YAML file; the alternative is a custom CI harness we'd build and own. The payoff is fewer post-release incidents and a defensible answer to "did we check?" It is a small, single-maintainer open-source tool, so we should treat it as a time-boxed pilot with a pin, not a platform bet — and we should not adopt it at all until we can name the consumers whose tests we'd actually run.
For engineering — the substance:
composer installs it, overwrites your package in its vendor/ directory with your working copy, runs its script. Defaults are composer install --no-interaction and vendor/bin/phpunit --no-coverage; both are overridable, and install: travis / script: travis (or the travis shorthand) reuses a consumer's existing Travis commands.stop_on_failure and success_only to keep signal high, and budget for the possibility that we fork it. Keep the consumer list short and deliberately curated — a matrix that's too wide gets muted, and a muted gate is no gate.How can I help you explore Laravel packages today?