Composer tools to maintain a monorepo
Do you maintain a monorepo with more packages?
This package has few useful tools, that will make that easier.
composer require symplify/monorepo-builder --dev
The best to lean-in fast is to read basic intro at blog post All You Always Wanted to Know About Monorepo.
We also made a simple command to make that easy for you:
vendor/bin/monorepo-builder init
And the basic setup is done!
composer.json
to the Root OneMerges configured sections to the root composer.json
, so you can only edit composer.json
of particular packages and let script to synchronize it.
Sections that are needed for monorepo to work will be merged:
To merge run:
vendor/bin/monorepo-builder merge
Typical location for packages is /packages
. But what if you have different naming or extra /projects
directory?
use Symplify\MonorepoBuilder\ComposerJsonManipulator\ValueObject\ComposerJsonSection;
use Symplify\MonorepoBuilder\Config\MBConfig;
use Symplify\MonorepoBuilder\ValueObject\Option;
return static function (MBConfig $mbConfig): void {
// where are the packages located?
$mbConfig->packageDirectories([
// default value
__DIR__ . '/packages',
// custom
__DIR__ . '/projects',
]);
// how to skip packages in loaded directories?
$mbConfig->packageDirectoriesExcludes([__DIR__ . '/packages/secret-package']);
// "merge" command related
// what extra parts to add after merge?
$mbConfig->dataToAppend([
ComposerJsonSection::AUTOLOAD_DEV => [
'psr-4' => [
'Symplify\Tests\\' => 'tests',
],
],
ComposerJsonSection::REQUIRE_DEV => [
'phpstan/phpstan' => '^0.12',
],
]);
$mbConfig->dataToRemove([
ComposerJsonSection::REQUIRE => [
// the line is removed by key, so version is irrelevant, thus *
'phpunit/phpunit' => '*',
],
ComposerJsonSection::REPOSITORIES => [
// this will remove all repositories
Option::REMOVE_COMPLETELY,
],
]);
};
Let’s say you release symplify/symplify
4.0 and you need package to depend on version ^4.0
for each other:
vendor/bin/monorepo-builder bump-interdependency "^4.0"
In synchronized monorepo, it’s common to use same package version to prevent bugs and WTFs. So if one of your package uses symfony/console
3.4 and the other symfony/console
4.1, this will tell you:
vendor/bin/monorepo-builder validate
You can see this even if there is already version 3.0 out:
{
"extra": {
"branch-alias": {
"dev-master": "2.0-dev"
}
}
}
Not good. Get rid of this manual work and add this command to your release workflow:
vendor/bin/monorepo-builder package-alias
This will add alias 3.1-dev
to composer.json
in each package.
If you prefer 3.1.x-dev
over default 3.1-dev
, you can configure it:
use Symplify\MonorepoBuilder\Config\MBConfig;
return static function (MBConfig $mbConfig): void {
// default: "<major>.<minor>-dev"
$mbConfig->packageAliasFormat('<major>.<minor>.x-dev');
};
Thanks to GitHub Actions, this was never simpler to set up. Use symplify/github-action-monorepo-split.
How to configure it? See our local setup at .github/workflows/split_monorepo.yaml
When a new version of your package is released, you have to do many manual steps:
git push
with tag,CHANGELOG.md
title Unreleased to v<version> - Y-m-d
formatBut what if you forget one or do it in wrong order? Everything will crash!
The release
command will make you safe:
vendor/bin/monorepo-builder release v7.0
And add the following release workers to your monorepo-builder.php
:
use Symplify\MonorepoBuilder\Config\MBConfig;
use Symplify\MonorepoBuilder\Release\ReleaseWorker\AddTagToChangelogReleaseWorker;
use Symplify\MonorepoBuilder\Release\ReleaseWorker\PushNextDevReleaseWorker;
use Symplify\MonorepoBuilder\Release\ReleaseWorker\PushTagReleaseWorker;
use Symplify\MonorepoBuilder\Release\ReleaseWorker\SetCurrentMutualDependenciesReleaseWorker;
use Symplify\MonorepoBuilder\Release\ReleaseWorker\SetNextMutualDependenciesReleaseWorker;
use Symplify\MonorepoBuilder\Release\ReleaseWorker\TagVersionReleaseWorker;
use Symplify\MonorepoBuilder\Release\ReleaseWorker\UpdateBranchAliasReleaseWorker;
use Symplify\MonorepoBuilder\Release\ReleaseWorker\UpdateReplaceReleaseWorker;
return static function (MBConfig $mbConfig): void {
// release workers - in order to execute
$mbConfig->workers([
UpdateReplaceReleaseWorker::class,
SetCurrentMutualDependenciesReleaseWorker::class,
AddTagToChangelogReleaseWorker::class,
TagVersionReleaseWorker::class,
PushTagReleaseWorker::class,
SetNextMutualDependenciesReleaseWorker::class,
UpdateBranchAliasReleaseWorker::class,
PushNextDevReleaseWorker::class,
]);
};
These TagVersionReleaseWorker
and PushTagReleaseWorker
are enabled by default.
If you want to disable these default workers, you can use the following code.
return static function (MBConfig $mbConfig): void {
$mbConfig->disableDefaultWorkers();
};
You can also include your own workers. Just add services that implements ReleaseWorkerInterface
.
Are you afraid to tag and push? Use --dry-run
to see only descriptions:
vendor/bin/monorepo-builder release 7.0 --dry-run
Do you want to release next patch version, e.g. current v0.7.1
→ next v0.7.2
?
vendor/bin/monorepo-builder release patch
You can use minor
and major
too.