feryardiant/learn-monorepo-common
Shared common library for the feryardiant/learn-monorepo project, providing reusable utilities and code for packages in a PHP monorepo. A learning-focused example of monorepo organization, package sharing, and Composer dependency management for developers exploring shared logic.
learn-monorepo-common is normally consumed by sibling packages with a "repositories": [{ "type": "path", "url": "../common" }] entry and a "require": { "feryardiant/learn-monorepo-common": "*" } constraint. Composer symlinks the package, so edits in common/src are immediately visible to consumers without re-publishing.composer.json (namespace, autoload, extra.laravel provider registration), src/ for the shared classes/traits, config/ for anything publishable, tests/Pest.php (new in v0.0.6) for the test bootstrap contract, and .github/workflows/ for the per-sub-package release automation added in this release../vendor/bin/pest in the package root to confirm the Pest bootstrap works, then add a single test that uses the common test helpers (uses(TestCase::class)->in('Feature') style) before wiring the package into a real sub-package. Because v0.0.6 is infrastructure-only (Pest init + release automation), there is no runtime API change to learn — validate the workflow first, then start pulling shared helpers into your own packages.common and require it from each sub-package. When you are tempted to paste a helper into a second package, that is the signal to promote it here.tests/Pest.php at the common base test case and expectation set rather than duplicating uses(...) blocks. The typical shape is one uses(CommonTestCase::class)->in('Feature', 'Unit') plus package-specific in() overrides where behavior differs.extra.laravel.providers, consumers get it for free. For anything optional (config, migrations, commands), expose it via publishes() / mergeConfigFrom() and let the consumer opt in with vendor:publish --tag=....feat(common): ..., fix(http-client): ...) so the automation attributes changes correctly.* constraints are fine while everything is symlinked, but as soon as you tag a release, switch consumers to ^0.x so an accidental breaking change in common fails loudly at composer update instead of silently at runtime.common re-runs every consumer's suite — that is the main safety net the symlinked path repository gives you.common, composer update feryardiant/learn-monorepo-common (or delete vendor/ in the consumer) if classes appear stale. Autoload classmaps are the usual culprit; composer dump-autoload fixes most "class not found" surprises.uses() and in() are directory- and namespace-scoped. If a shared bootstrap lives in common/tests, the consumer's Pest.php must explicitly require or uses() it — Pest will not discover a sibling package's test bootstrap automatically. Symptom: helper functions undefined only when running from the consumer root.common can produce ambiguous or duplicate releases. Split such commits, or accept that the automation will tag the first matching package — check the workflow file to see whether it keys off paths, tags, or commit scopes before trusting it.common. Anything with package-specific config (routes, policies, model bindings) belongs in the consuming package; common should stay dependency-light or you create a diamond where every package inherits every other package's requirements.mergeConfigFrom() are fine, but code reading config() at boot time will freeze values under config:cache. Read config inside handlers/resolvers, not in the provider constructor.expect()->extend(...)) registered in the shared bootstrap, and macros/traits on the common base test case. Both give consumers leverage without forking common. Keep them additive and documented in the package README — the release automation only logs commit subjects, so undocumented helpers effectively don't exist for new team members.How can I help you explore Laravel packages today?