symplify/monorepo-builder
Tools for PHP monorepos: discover packages, merge and propagate composer.json, validate dependency/version consistency, and automate releases. Configure via monorepo-builder.php and manage packages across /packages or custom directories.
Install the package:
composer require monorepo-php/monorepo --dev
(Note: The README uses symplify/monorepo-builder, but the description specifies monorepo-php/monorepo as the installable package.)
Initialize configuration:
vendor/bin/monorepo-builder init
This generates monorepo-builder.php in your project root.
First use case:
Merge all package composer.json files into the root:
vendor/bin/monorepo-builder merge
Verify the root composer.json now includes dependencies from all packages.
monorepo-builder.php (auto-generated by init).vendor/bin/monorepo-builder without arguments to list all available commands../packages/; customize in packageDirectories() if needed.autoload-dev, extra.laravel, and scripts-aliases sections during merges.Merge and Propagate:
# Merge all package dependencies into root composer.json
vendor/bin/monorepo-builder merge
# Propagate root dependencies back to packages (e.g., after updating a shared Laravel dependency)
vendor/bin/monorepo-builder propagate
Use case: Keep shared Laravel dependencies (e.g., laravel/framework) synchronized across packages.
Append/Remove Data:
$mbConfig->dataToAppend([
ComposerJsonSection::AUTOLOAD_DEV => [
'psr-4' => ['App\\Tests\\' => 'tests'],
],
]);
Use case: Add Laravel-specific autoloading rules or custom extra.laravel keys post-merge.
Shared Dependency Consistency:
vendor/bin/monorepo-builder validate
Use case: Ensure all packages use the same version of spatie/laravel-permission or laravel/sanctum.
Interdependency Bumps:
vendor/bin/monorepo-builder bump-interdependency "^2.0"
Use case: Update mutual dependencies between Laravel plugins (e.g., a laravel-plugin-auth and laravel-plugin-payment).
Semantic Versioning:
# Release a patch version (e.g., v1.2.3 → v1.2.4)
vendor/bin/monorepo-builder release patch
# Release a specific version (e.g., v2.0.0)
vendor/bin/monorepo-builder release v2.0.0 --dry-run
Use case: Automate version bumps, Git tags, and changelog updates for Laravel packages.
Branch-Aware Releases:
$services->set(BranchAwareTagResolver::class);
Use case: Support LTS branches (e.g., Laravel 10 vs. 11) without global tag conflicts.
Localize Composer Paths:
vendor/bin/monorepo-builder localize-composer-paths
Use case: Test a Laravel plugin against a local core framework version (e.g., require-dev a local laravel/framework).
Package Aliases:
vendor/bin/monorepo-builder package-alias
Use case: Update branch-alias in package composer.json files for branch-aware development.
Preserve Laravel Sections:
$mbConfig->composerSectionOrder([
ComposerJsonSection::AUTOLOAD,
ComposerJsonSection::AUTOLOAD_DEV,
ComposerJsonSection::EXTRA, // Laravel's `extra.laravel` lives here
// ... other sections
]);
Why: Ensures extra.laravel keys (e.g., package:discover) are not lost during merges.
Custom Scripts:
$mbConfig->dataToAppend([
ComposerJsonSection::SCRIPTS => [
'post-autoload-dump' => [
'php artisan optimize:clear',
],
],
]);
Why: Add Laravel-specific scripts (e.g., optimize:clear) to all packages post-merge.
GitHub Actions:
Combine with symplify/github-action-monorepo-split to split Laravel packages into independent repos for deployment.
# .github/workflows/split.yml
jobs:
split:
uses: symplify/github-action-monorepo-split/.github/workflows/split.yml
with:
package-directories: 'packages/*'
Post-Merge Hooks:
Use dataToAppend to inject Laravel-specific configurations:
$mbConfig->dataToAppend([
ComposerJsonSection::CONFIG => [
'allow-plugins' => [
'php-http/discovery' => true,
],
],
]);
Isolated Testing:
Use localize-composer-paths to test Laravel plugins against local core versions:
vendor/bin/monorepo-builder localize-composer-paths
composer install --prefer-source
vendor/bin/phpunit --testsuite PluginTests
Dependency Validation: Add a CI step to validate shared Laravel dependencies:
# .github/workflows/validate.yml
jobs:
validate:
run: vendor/bin/monorepo-builder validate
Section Order Preservation:
scripts-aliases) may be dropped during merges if not explicitly configured.composerSectionOrder() to enforce ordering:
$mbConfig->composerSectionOrder(JsonSchema::getProperties());
Require vs. Require-Dev Conflicts:
merge command prioritizes require over require-dev. If a package has phpunit/phpunit in require-dev but the root has it in require, the package’s version is ignored.dataToAppend or dataToRemove to handle conflicts:
$mbConfig->dataToAppend([
ComposerJsonSection::REQUIRE_DEV => [
'phpunit/phpunit' => '^9.5',
],
]);
Branch-Aware Releases:
BranchAwareTagResolver, releases may fail if tags exist in other branches (e.g., v1.0.0 in main vs. v1.0.0 in laravel-10).$services->set(BranchAwareTagResolver::class);
Custom Workers:
ReleaseWorker implementations may not execute in the expected order.workers():
$mbConfig->workers([
CustomLaravelTestWorker::class,
UpdateBranchAliasReleaseWorker::class,
]);
PHAR Builds:
composer-json-manipulator autoload entry that breaks PHAR builds (fixed in v12.5.2).^12.5.2) if using PHARs.Dry Runs:
Always use --dry-run for destructive commands:
vendor/bin/monorepo-builder release v2.0.0 --dry-run
vendor/bin/monorepo-builder propagate --dry-run
Verbose Output: Enable debug mode for detailed logs:
vendor/bin/monorepo-builder merge -v
Validate Config: Test configuration changes incrementally:
# Test package discovery
vendor/bin/monorepo-builder --list-packages
# Test merge without committing
vendor/bin/monorepo-builder merge --dry-run
Git Diffs:
Use git diff to inspect changes before committing:
vendor/bin/monorepo-builder merge
git diff composer.json
How can I help you explore Laravel packages today?