A completely rewritten monorepo management package for Laravel, designed with clean architecture principles, better separation of concerns, and improved testability.
- Clean Interface Design: All services implement clear contracts
- Separation of Concerns: Actions, services, and commands are properly separated
- Dependency Injection: Full DI container usage for better testability
- Data Transfer Objects: Clean data handling with immutable DTOs
- Action-Based Logic: Complex operations broken into focused action classes
- Caching Layer: Built-in caching for GitHub API requests
- Optimized Requests: Reduced API calls through intelligent caching
- Batch Processing: Efficient handling of multiple packages
- Memory Efficiency: Better resource management
- Focused Commands: Simple, single-responsibility commands
- Better Error Handling: Comprehensive error reporting and logging
- Dry Run Support: Test releases without making changes
- Rich CLI Output: Beautiful, informative command output
- Comprehensive Tests: Full test coverage with Pest
composer require moox/monorepoPublish the configuration:
php artisan vendor:publish --tag="monorepo-config"Configure your environment variables:
MONOREPO_GITHUB_ORG=mooxphp
MONOREPO_PUBLIC_REPO=moox
MONOREPO_PRIVATE_REPO=pro
MONOREPO_PACKAGES_PATH=packages
MONOREPO_DEVLOG_PATH=packages/monorepo/DEVLOG.md
MONOREPO_CACHE_ENABLED=true
MONOREPO_CACHE_TTL=300
# Repository creation settings (defaults based on mooxphp/jobs)
MONOREPO_DEFAULT_LICENSE=null
MONOREPO_REPO_AUTO_INIT=false
MONOREPO_REPO_GITIGNORE=null
MONOREPO_REPO_HAS_ISSUES=true
MONOREPO_REPO_HAS_PROJECTS=false
MONOREPO_REPO_HAS_WIKI=false
MONOREPO_REPO_HAS_DISCUSSIONS=false
MONOREPO_REPO_ALLOW_FORKING=true
MONOREPO_REPO_WEB_COMMIT_SIGNOFF=false
# Merge preferences
MONOREPO_REPO_ALLOW_SQUASH=true
MONOREPO_REPO_ALLOW_MERGE=false
MONOREPO_REPO_ALLOW_REBASE=false
MONOREPO_REPO_ALLOW_AUTO_MERGE=false
MONOREPO_REPO_DELETE_BRANCH_ON_MERGE=trueGet an overview of all packages:
php artisan monorepo:listShow only public packages:
php artisan monorepo:list --publicShow only private packages:
php artisan monorepo:list --privateShow packages with changes:
php artisan monorepo:list --changesShow packages missing from GitHub:
php artisan monorepo:list --missingAutomatically create empty GitHub repositories for packages that don't have them:
php artisan monorepo:create-missingCreate only public repositories:
php artisan monorepo:create-missing --publicCreate only private repositories:
php artisan monorepo:create-missing --privateShow what would be created without making changes:
php artisan monorepo:create-missing --dry-runSkip confirmation prompts:
php artisan monorepo:create-missing --forceInteractive mode - ask for each repository individually:
php artisan monorepo:create-missing --interactiveSkip updating devlink configuration:
php artisan monorepo:create-missing --skip-devlinkCreate a new release:
php artisan monorepo:releaseSpecify version directly:
php artisan monorepo:release --version=1.2.3Dry run (show what would happen):
php artisan monorepo:release --dry-runRelease only public packages:
php artisan monorepo:release --public-onlyRelease only private packages:
php artisan monorepo:release --private-onlyThe package supports intelligent release control based on package stability settings in composer.json:
Add stability configuration to your package's composer.json:
{
"extra": {
"moox-stability": "stable"
}
}"stable": Package will receive GitHub releases when included in monorepo releases"dev"(or missing): Package will be split to its repository but won't get releases- Any other value: Treated as
"dev"
When you run php artisan monorepo:release --version=1.2.3:
- Monorepo Release: Creates
v1.2.3release on main monorepo - Package Splitting: All packages are split to their individual repositories
- Individual Releases: Only packages with
"moox-stability": "stable"get GitHub releases - Dev Packages: Split but no release (keeps repos up-to-date without versioned releases)
This allows you to:
- Keep experimental packages in development without confusing users with releases
- Gradually promote packages from dev to stable as they mature
- Maintain consistent repository content while controlling public releases
All commands provide clear progress feedback:
π Starting Monorepo Release Process v2.0
π Authenticating with GitHub...
β
Authenticated as: Moox-Bot
π‘ Getting current version from GitHub...
π Discovering packages from monorepo...
π Scanning public packages...
π‘ Fetching packages from mooxphp/moox...
π Processing 42 packages...
π Comparing with organization repositories...
π Processing changelog entries...- Repository Creation: Shows progress bar during batch repository creation
- Interactive Mode: Step-by-step confirmation with package details
- Rate Limiting: Built-in delays with feedback to avoid API limits
GitHubClientInterface- GitHub API interactionsVersionManagerInterface- Version handling and validationPackageDiscoveryInterface- Package discovery and comparisonChangelogProcessorInterface- Changelog/DEVLOG processing
GitHubClient- GitHub API client with cachingVersionManager- Semantic version management
DiscoverPackagesAction- Package discovery logicProcessChangelogAction- Changelog processing logicCreateReleaseAction- Release creation logic
PackageInfo- Package information containerReleaseInfo- Release information containerPackageChange- Package change information
ReleaseCommand- Main release orchestrationListPackagesCommand- Package listing and overviewCreateMissingRepositoriesCommand- Create missing GitHub repositories
- Discovery: Package discovery scans GitHub monorepo repositories and compares with organization repositories
- Changelog Processing: DEVLOG.md is parsed for package-specific changes
- Stability Filtering: Package stability settings determine release eligibility
- Version Management: Current version is retrieved and new version is validated
- Release Creation: GitHub releases are created and workflows are triggered
- Workflow Dispatch: Package splitting workflows are triggered with stability and package data
The package expects a DEVLOG.md file with the following format:
## PackageName1
- Feature: Added new functionality
- Fix: Fixed bug in component
- Breaking: Removed deprecated method
## PackageName2
- Feature: New feature addedPackages without explicit changelog entries get a "Compatibility release" message.
The package includes comprehensive tests:
./vendor/bin/pestTest structure:
tests/Unit/- Unit tests for services and actionstests/Feature/- Integration tests for commands
Example test for VersionManager:
it('validates semantic version format correctly', function () {
expect($this->versionManager->validateVersionFormat('1.0.0'))->toBeTrue();
expect($this->versionManager->validateVersionFormat('1.0.0-alpha.1'))->toBeTrue();
expect($this->versionManager->validateVersionFormat('invalid'))->toBeFalse();
});The monorepo package can automatically create empty GitHub repositories for packages that exist in your monorepo but don't have their own individual repositories. These empty repositories are then ready to be populated by your split workflow.
- Discovery: The command scans your GitHub monorepo(s) to find all packages
- Comparison: It compares found packages with existing repositories in your organization
- Repository Creation: For missing repositories, it creates empty GitHub repositories with proper settings
- Workflow Ready: The repositories are ready to receive content from your split workflow
When creating repositories, the package automatically updates your devlink configuration:
- Automatic Updates: New packages are added to
config/devlink.phpin alphabetical order - Proper Configuration: Packages are configured with correct paths and visibility settings
- Skip Option: Use
--skip-devlinkto skip devlink configuration updates - Error Handling: Devlink failures don't stop repository creation
This creates empty repositories that work perfectly with your existing split.yml workflow:
- Empty repositories are created with optimal settings for package splitting
- Configurable settings - defaults based on mooxphp/jobs repository:
- Issues: Enabled (configurable via
MONOREPO_REPO_HAS_ISSUES) - Projects: Disabled (configurable via
MONOREPO_REPO_HAS_PROJECTS) - Wiki: Disabled (configurable via
MONOREPO_REPO_HAS_WIKI) - Discussions: Disabled (configurable via
MONOREPO_REPO_HAS_DISCUSSIONS) - Forking: Allowed (configurable via
MONOREPO_REPO_ALLOW_FORKING) - Commit signoff: Not required (configurable via
MONOREPO_REPO_WEB_COMMIT_SIGNOFF)
- Issues: Enabled (configurable via
- Merge preferences configured (squash merge enabled, others disabled by default)
- Repository settings optimized for package workflows and fully customizable
- Ready for content - your workflow can immediately split package content into them
- Selective creation: Create only public or private repositories
- Dry-run mode: Preview what would be created without making changes
- Force mode: Skip interactive confirmations
- Configurable settings: Repository features and merge settings are configurable
- Dry-run mode: Preview repositories that would be created
- Interactive prompts: Confirmation required before creating repositories
- Progress tracking: Visual progress bar for batch operations
- Error handling: Detailed error reporting for failed creations
- Rate limiting: Built-in delays to avoid GitHub API limits
The v2.0 package is a complete rewrite with breaking changes:
moox:releasingβmonorepo:releasemoox:releasing --versionsβmonorepo:listmoox:releasing --compare-packagesβmonorepo:list --missing
- Old:
config('monorepo.github_org')β New:config('monorepo.github.organization') - Improved configuration structure with nested arrays
- All services now implement interfaces
- Dependency injection used throughout
- Better error handling and logging
- GitHub API responses are cached for 5 minutes by default
- Cache can be disabled via configuration
- Intelligent cache invalidation on writes
- Multiple packages processed efficiently
- Reduced API calls through pagination
- Memory-efficient collection handling
- Payload size limits prevent workflow failures
- Message sanitization prevents bash injection
- Intelligent truncation when needed
Create custom actions by implementing the relevant interfaces:
class CustomPackageAction implements PackageDiscoveryInterface
{
public function discoverPackages(string $path, string $visibility = 'public'): Collection
{
// Custom discovery logic
}
}Extend services by binding new implementations:
$this->app->bind(GitHubClientInterface::class, CustomGitHubClient::class);The package provides comprehensive logging:
- GitHub API request/response logging
- Error handling with context
- Performance metrics
- Cache hit/miss statistics
Logs are written to the Laravel log channel and include:
- Request URLs and methods
- Response status codes
- Error messages with context
- Performance timings
- GitHub tokens are securely handled
- Message sanitization prevents injection attacks
- Payload size limits prevent DoS
- Input validation on all user inputs
- Web UI for release management
- Webhook support for automated releases
- Multi-repository batch operations
- Release templates and automation
- Integration with package registries
- Advanced analytics and reporting
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
MIT License - see LICENSE file for details.
Monorepo v2.0 - Built with β€οΈ for better developer experience