Skip to content

[FEATURE] Determine the version to publish from the extension - #104

Open
bmack wants to merge 1 commit into
mainfrom
feature/resolve-version-for-publish
Open

[FEATURE] Determine the version to publish from the extension#104
bmack wants to merge 1 commit into
mainfrom
feature/resolve-version-for-publish

Conversation

@bmack

@bmack bmack commented Aug 12, 2026

Copy link
Copy Markdown
Member

The version argument of ter:publish is optional now. If it is not given, the version is taken from the extension itself, in this order:

  1. The tag of the checked out commit, with an optional v prefix. Tags which are no version, e.g. latest, are ignored.
  2. The version in ext_emconf.php.
  3. The version in composer.json, either on root level or at [extra][typo3/cms][version].

The last two are the ones maintained by the set-version command, so a release does not have to repeat its version on the command line:

tailor set-version 1.5.0
git commit -am "[RELEASE] A new version was published"
git tag -a 1.5.0
tailor ter:publish

Tailor states which version it uses and where it comes from:

$ tailor ter:publish
Using version 1.5.0 from the tag of the checked out commit.

Publishing version 1.5.0 of extension my_ext

Notes:

  • If the checked out commit is tagged with more than one version, the version has to be given as argument.
  • Since an extension key never looks like a version, ter:publish my_extension still works - the sole argument is moved to the extension key.
  • The composer.json version can never rescue a publish, since packaging validates that ext_emconf.php carries the same version. It does improve the error message though.
  • The extension key is now read from the composer.json of the given --path as well, instead of always from the current working directory.

The git repository is queried with git -C <path> tag --points-at HEAD. A missing git binary, a disabled exec() or a path which is no repository simply means there is no tag to work with.

The version argument of `ter:publish` is optional now. If it is not
given, the version is taken from the extension itself, in this order:

1. The tag of the checked out commit, with an optional `v` prefix.
   Tags which are no version, e.g. `latest`, are ignored.
2. The version in `ext_emconf.php`.
3. The version in `composer.json`, either on root level or at
   `[extra][typo3/cms][version]`.

The last two are the ones maintained by the `set-version` command,
so a release does not have to repeat its version on the command line.
Tailor states which version it uses and where it comes from.

If the checked out commit is tagged with more than one version, the
version has to be given as argument. Since an extension key never
looks like a version, `ter:publish my_extension` still works.

The extension key is now read from the `composer.json` of the given
`--path` as well, instead of always from the current working
directory.
@bmack
bmack requested a review from eliashaeussler August 12, 2026 13:52
Comment on lines +72 to +80
if (count($versions) > 1) {
throw new VersionMissingException(
sprintf(
'The checked out commit is tagged with more than one version (%s). Please state the version to use as argument.',
implode(', ', $versions)
),
1786492801
);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unsure if we should really fail here if more than one version tag points to HEAD (which is actually a quite uncommon circumstance), since we probably still read it from composer.json or ext_emconf.php.

Comment on lines +89 to +97
$version = (new EmConfReader($path))->getVersion();
if ($versionValidator->isValid($version)) {
return new ResolvedVersion($version, ResolvedVersion::SOURCE_EMCONF);
}

$version = (new ComposerReader($path))->getVersion();
if ($versionValidator->isValid($version)) {
return new ResolvedVersion($version, ResolvedVersion::SOURCE_COMPOSER);
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd give composer.json a higher priority than ext_emconf.php, since this reflects the new source of truth.

$versions = [];

foreach ($this->getTagsOfHead($path) as $tag) {
$version = (string)preg_replace('/^v/i', '', $tag);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$version = (string)preg_replace('/^v/i', '', $tag);
$version = ltrim($tag, 'v');

@CybotTM

CybotTM commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

tailor set-version 1.5.0
git commit -am "[RELEASE] A new version was published"
git tag -a 1.5.0
tailor ter:publish

not sure about this, regarding best practices.

IIRR it is not adviced to pin the version in composer.json in a repo - it will always drift.

Best practice is to leave version info in composer.json empty inside the repo, isn't it?

IMO the correct process for uploading packages, where needed:

  1. set version tag in git -> release
  2. checkout, set version (in composer.json) and package release assets -> tailor set version (for the package)
  3. upload to package registry like TER -> tailor upload

IMO we need to better distinguish between composer/packagist/git deployment/release and the "old" TER way of publishing packages

But i must admit I am not that deep in all this release processes, especially with TER

@CybotTM

CybotTM commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

I would go even further, running tailor in a repo should hard fail on invalid/missing version tagging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants