symplify/monorepo-builder
Toolkit for managing PHP monorepos: merge package composer.json files into the root, validate dependency versions, bump interdependencies, propagate versions back, manage package aliases, and automate releases. Configured via monorepo-builder.php; requires PHP 8.2+.
release patch|minor|major with --dry-run makes a predictable release train a commitment you can actually keep, and validate enforces a single shared version of Laravel, PHP, PHPUnit, and PHPStan across every sub-package — i.e., an enforceable "supported Laravel versions" policy rather than a wiki page.merge keeps root-level tooling working while packages are still separate, you can ship as one package today and split incrementally later without a big-bang migration sprint.composer install, one CI pipeline, and root-level PHPUnit/PHPStan/Pint across all packages directly affect contributor onboarding time and review throughput — measurable proxies for delivery velocity.disablePackageReplace() plus the section-and-type-aware disableAutoloadMerge() supports the "libraries symlinked via path repos, apps not required from root" topology — a real decision for teams whose Laravel app consumes its own packages.Adopt when:
replace-based single-surface publishing or path-repo symlink installs; both are first-class config options.ReleaseWorkerInterface) rather than a hosted service you can't fork.Look elsewhere when:
release script suffice.symplify/monorepo-builder:^11.2 branch works there — an unmaintained dependency in your build chain is a bad trade for a convenience tool.Diligence flags to price in:
composer require monorepo-php/monorepo --dev) diverges from the package name (symplify/monorepo-builder), which signals an in-flight rebrand. Confirm the canonical package name before it lands in internal docs, or you'll write stale onboarding material on day one.--dev tool that's partly a measurement artifact, but treat ecosystem support as thin and the maintainer-bus factor as real.For executives: This is build tooling, not shipped code — MIT-licensed, --dev only, zero runtime footprint in what customers install. What it buys is release velocity and version hygiene: one command to bump, tag, and push across N packages, plus a CI gate that stops sub-packages drifting onto different Laravel or PHPUnit versions. Cost is a single config file and a one-time migration; risk is a single-maintainer dependency in our build chain, which we contain by pinning versions and keeping our release-worker config thin enough to fork or replace in a day.
For engineering: It replaces hand-rolled Composer merge and release scripts with tested equivalents. merge folds each package's composer.json into the root so root PHPUnit/PHPStan resolve every namespace; validate enforces shared-dependency parity; propagate and bump-interdependency push versions back out; release runs a configurable worker pipeline (update replace, set deps, changelog, tag, push, next-dev alias) with --dry-run for preview. All configuration lives in one monorepo-builder.php. The autoload-skip and disablePackageReplace options cover mixed library/app layouts — but note autoload-dev must keep merging if root PHPUnit is to discover library test classes, since Composer never registers dev autoload from path-repo dependencies. Prerequisite is PHP 8.2+.
The ask: A one-day spike on a branch — run init, merge, and validate against our current packages, with release --dry-run as the acceptance test — then a go/no-go. Success criteria: root CI green on a single install, and a dry-run release that produces the tag sequence and changelog entries we'd actually want to publish.
How can I help you explore Laravel packages today?