fix: ensure first composer install symlinks local packages#663
Merged
Conversation
Replace wikimedia/composer-merge-plugin indirection with a top-level path repository in each composer.json. The merge plugin could only intercept Composer events after it was already installed, so the first composer install in a sub-package fetched siblings from Packagist instead of symlinking from local paths — requiring a second install for the plugin to kick in. A top-level repositories field is read by Composer immediately, so sibling packages resolve to local symlinks on the first install with no plugin needed. End-user installs are unaffected because Composer ignores repositories defined in dependency packages.
# Conflicts: # packages/Amqp/composer.json # packages/DataProtection/composer.json # packages/Dbal/composer.json # packages/Enqueue/composer.json # packages/Kafka/composer.json # packages/PdoEventSourcing/composer.json # packages/Redis/composer.json
The new top-level repositories wildcard works inside the monorepo, but points to nonexistent paths once the directory is split into a standalone repo. For package splits (../*) it falls through silently, but the quickstart-examples split (../../packages/*) refers to a parent directory that does not exist next to a clone of the split repo, which made composer install fail hard with "the url supplied for the path repository does not exist". Add a release-time helper that strips type=path entries from every composer.json under the package directory and run it in the split job before invoking the split action. Monorepo composer.jsons are unaffected — the strip only runs on the in-memory checkout used by the split job.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why is this change proposed?
Cloning the repo,
cd-ing into a package (e.g.packages/Amqp), and runningcomposer installdid not symlink sibling Ecotone packages — it pulled them from Packagist instead. A secondcomposer installwas required forwikimedia/composer-merge-pluginto kick in and apply the path repositories fromlocal_packages.json. New contributors (and CI) hit this chicken-and-egg every time, and the workaround leaked into both the GitHub Actions workflows (composer global require wikimedia/composer-merge-plugin) and the docker-compose env (APP_MERGE_PLUGIN: yes). This PR makes the firstcomposer installwork correctly with no extra steps.Description of Changes
extra.merge-pluginindirection in everypackages/*/composer.json,_PackageTemplate/composer.json, andquickstart-examples/**/composer.jsonwith a top-levelrepositoriesfield using a wildcard path (../*,packages/*, etc. depending on depth).wikimedia/composer-merge-pluginfromrequire/require-devand fromconfig.allow-plugins(no longer needed).local-packages.jsonandpackages/local_packages.json..github/workflows/split-testing.ymland.github/workflows/quickstart-examples.yml.APP_MERGE_PLUGINenv var fromdocker-compose.yml.Why it's safe for end users
Composer ignores
repositoriesdefined in dependency packages — only the root project's repositories are honored. So when a user runscomposer require ecotone/amqpin their own project, the wildcardrepositoriesblock insideecotone/amqp'scomposer.jsonis read, then discarded. Sibling deps continue to resolve from Packagist as before.Verification
I tested both halves of the contract inside the project's docker container.
End-user safety — set up a consumer project that pulled
ecotone/amqpvia path repo, planted a poison-pillecotone/enqueue@1.309.999next to it that would only get installed if Composer honored the dep'srepositories. Result: realecotone/enqueue@1.309.3was downloaded from Packagist, poison-pill was ignored.Local dev fix — fresh
composer install(no priorvendor/lock) inside multiple packages and quickstart-examples, all symlink siblings on the first try:Full phpunit suite (1239 tests) passes in
packages/Ecotoneafter the refactor.Use case scenarios
cd packages/Dbal,composer install, run tests. No second install, no docs about merge-plugin needed.packages/with acomposer.json. The wildcard picks it up automatically; no central list to update.cd quickstart-examples/Schedule,composer install, run the example. Sibling packages come from local source, so changes inpackages/Ecotoneare reflected immediately.Resolution flow
flowchart LR A[composer install in packages/Amqp] --> B{repositories field} B -->|top-level<br/>read immediately| C[Discover ../* siblings] C --> D[Symlink ecotone/enqueue from ../Enqueue] style B fill:#cfc E[composer install in packages/Amqp<br/>old behavior] --> F{merge-plugin installed?} F -->|no, first run| G[Resolve ecotone/enqueue from Packagist] F -->|yes, second run| H[Symlink from ../Enqueue] style F fill:#fccPull Request Contribution Terms