Magento 2: How to Specify "Semantic Versioning" Dependencies in my Module's composer.json

Do I need to manually look at my module everytime I use a piece of core Magento code and add a require:... line to composer.json?

Yes, every time in your code you use anything from a core module you need to add it to your composer's require. As you likely want your load order to be after the core module I would also suggest adding it to your module.xml file in the sequence section.

Or is there an automated tool that can do that for me?

I haven't come across any yet. If there is please let me know. It would need to be a fairly sophisticated tool and would likely require substantial test coverage and then runs a matrix of different versions to produce a working set.

How do I specify a version to include in my composer.json? Should it be the specific module version I've developed against? Or should there me some sort of wildcard involved? Or do I need to make a decision based on tradeoffs? If so, what are the tradeoffs involved for each style of version specifying?

Options to define a version number

  1. 100.0.2
    Only work when this specific version

  2. 100.0.*
    * is a wildcard and can be replaced with any version number 100.0.0, 100.0.1, ... , 100.0.120

  3. ~100.0.2
    Makes 2 a wildcard that can only go up so 100.0.2, 100.0.3, ... , 100.0.120

  4. ^100.0.2
    Allows any release up until 101 so 100.0.2, 100.0.3, ..., 100.1.0, 100.2.5

For options 2-4 if your stability settings allow it it would also include versions like 100.0.1-beta

Practical use

Option 1.) is the most cautious one, you know which version you developed against and only accept working with this particular version - your module can only be installed alongside that particular module at that version. All other install/upgrade attempts will fail with a composer message highlighting that it can't find an installable set of components.

Option 2.) I think can be thought of as non-option as is covered by Option 3.) if you use it like ~100.0.0

Option 3.) Be compatible as long as no new features are introduced

Option 4.) Be compatible as long as no breaking changes are introduced

Trade Offs

1 Your extension only works for 1 version of a Magento module (technically if there aren't any changes in a module the version number should not increase and multiple Magento Project versions could theoretically include the same Magento core module with the same version. Practically I haven't seen this and looks like it requires some process changes on the Magento end see here). Since you are so closely tied against 1 version of the Magento core module you end up with lots of releases and versions of your own extension, if you want to stay compatible.

3-4 Your extension works with multiple versions of Magento and you do not need to release different versions of your extension every time Magento releases a new version. The downside here is that you claim compatibility even though a change could be introduced in Magento that is incompatible with your own code. This risk is real as Magento's definition of semantic versioning for their own module releases only extends to what is marked with an @api annotation (more on this in this GitHub issue) with its limited scope.

tl;dr;
100.0.2 Play it safe, lots of releases to maintain for you
^100.0.2 Semantic Versioning how it should work, less releases for you but with higher risk due to currently the limited scope of @api annotated classes and methods. If you had an extension which is 100% using sanctioned classes and methods this would be the obvious choice.


It can be like 0.1.0-alpha1 -> 0.1.0-alpha2, 0.1.0-alpha3, based on the stability of the module. As shared in the documentation the requirement will go something like:-

"require": {
    "myexamplestore/product-bundle": "2.0.0-RC1",
    "myexamplestore/acme-extension": "~1.0"
    }

Based on your update, this should be updated like :-

"require": {
    "myexamplestore/product-bundle": "2.4.0-RC1",
    "myexamplestore/acme-extension": "~2.0"
    }

I do not think there is any automated system to this yet, but as per documentation it is very important to follow this.

But you should use PATCH if there are minor bug fixes in your module.

Refer to

PATCH indicates backward-compatible bug fixes

You are right the answer is bit unclear, but you can see it was updated way back around 1 year. But this is how it is.