Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question: How to semver patch a patch? e.g. use a specific tag #8381

Closed
josephdpurcell opened this issue Oct 19, 2019 · 7 comments
Closed

Question: How to semver patch a patch? e.g. use a specific tag #8381

josephdpurcell opened this issue Oct 19, 2019 · 7 comments

Comments

@josephdpurcell
Copy link

josephdpurcell commented Oct 19, 2019

Problem / Motivation

This issues is to help everyone understand what to do when you need to "patch a patch," i.e. insert a tag between two PATCH versions.

Imagine you have a project that has the following versions as tags in the repository:

  • 1.0.59 - Includes Features A and B
  • 1.0.60 - Includes Features A, B, C, D, E, and F

The 1.0.59 version is deployed to production. The 1.0.60 version is not schedule to go to production for another 5 days and you need a hotfix deployed today. You can't release 1.0.60 because there are features that haven't been QA'd yet, some of them may have bugs. We need to move more quickly.

How do I tag a release in such a way that composer will accept it and it complies with semver?

Options to Consider

It sounds like there are a few paths that could be taken in theory, let's make the assumption they all require telling anyone using the 1.0.59 version to use a specific other version, i.e. no one can just do a composer update to pull in the hotfix in the scenario outlined above. Also, we'll assume you can't simply re-create the tags.

Option 1: Claim it's a release management issue.

You could argue that the issue is with the release management process or correct use of version numbers. If 1.0.59 and 1.0.60 are releases of features, why didn't the MINOR version increase? Why are you not tagging a release candidate or pre-release version instead of an actual patch since QA hasn't been completed? This is a long term solution, it doesn't solve the immediate problem of needing to patch a patch.

Option 2: Use a 4 digit version. [violates Semver]

Semver supports only 3 digits, X.y.z, but composer supports 4 digits. This is a viable option as long as you have nothing preventing you from creating a 4 digit version and you're OK with violating semver. For example, use 1.0.59.1 as the hotfix version.

Option 3: Use composer patches.

Release a patch file to the 1.0.59 version. Have everyone using the 1.0.59 version to add this patch to their composer.json file using composer patches.

Option 4: Composer to support specifying a tag name. [theoretical]

Composer supports pinning to a specific commit hash or a branch name. It does not support pinning to a tag name. This scenario would require composer changing to support specifying a specific tag name. Perhaps this could be achieved by composer mapping an arbitrary tag to a commit hash and pinning against that commit hash. In turn, this would allow support for semver build metadata, e.g. 1.0.59+hotfix.

Option 5: Use a branch instead of a tag.

Create a branch off 1.0.59 like so:

git checkout -b  hotfix/foo 1.0.59

Add changes to this branch. Have everyone using the 1.0.59 version to use the hotfix/foo branch with composer require vendor/package:dev-hotfix/foo. Never delete the branch.

Option 6: Use a pre-release tag. [violates Semver]

Use a tag like 1.0.59-patch1. While this does work with composer it violates Semver, which states that a tag with a hyphen - is a pre-release and has "a lower precedence than the associated normal version." So, 1.0.59-patch1 should come before 1.0.59 in your version history, which would not be the case here.

Option 7: Reference the commit of a build tag. [requires disclaimer]

While composer doesn't support referencing a tag name such as a build tag (i.e. a tag that has build information), you can reference the commit hash a tag points to. This solution would involve creating a branch from the tag:

git checkout -b  hotfix/foo 1.0.59

Add changes to this branch. Tag the branch with 1.0.59+patch1. Have everyone using the 1.0.59 version to use the 1.0.59+patch1 tag by referencing the commit the tag points to like so: composer require vendor/package:dev-master#d3f9f1b. You can now delete the hotfix/foo branch, but you must keep the master branch.

Please read the disclaimer if using this. The composer.json metadata will be read from the master branch, so for example if a additional dependency gets added to the master composer.json anyone using the 1.0.59+patch1 will also read that additional dependency.

Proposed Resolution

The long term resolution would be Option 1: Claim it's a release management issue.

In the short term, these options are all viable:

  • Option 2: Use a 4 digit version. [violates Semver]
  • Option 3: Use composer patches.
  • Option 5: Use a branch instead of a tag.
  • Option 6: Use a pre-release tag. [violates Semver]
  • Option 7: Reference the commit of a build tag. [requires disclaimer]

Composer has made it clear that Option 4: Composer to support specifying a tag name is not going to happen.

Commentary / Opinion

Option 1 is clearly the "right" answer, but given what I've seen in my research there is a need for a short term solution. Here's my opinion about those:

Option 3 requires too much effort and coordination compared to the alternatives. I would throw this out. Option 4 is a non starter. So, we are left with 2, 5, 6, and 7.

Options 2 and 6 are the best fit if you do not need to comply with Semver. Option 2 is logical: the 4th digit is a sequence of changes to the 3rd digit. Option 6 at least is formatted like Semver but those familiar with Semver might be confused why a pre-release happened after a release.

Options 5 and 7 are the best fit for complying with Semver and also have composer support. Option 5 has the downside of needing to keep a branch. Option 7 has the serious downside of the disclaimer that composer will read the metdata from the specified branch.

Which option is the best choice is contextual. If I had to pick one, I would go with Option 2: Use a 4 digit version. While it violates Semver it has the least risk, least effort, and least confusion.

Related Information

@josephdpurcell josephdpurcell changed the title Question: How to semver patch a patch? e.g. use a specific tag, Question: How to semver patch a patch? e.g. use a specific tag Oct 19, 2019
@phansys
Copy link
Contributor

phansys commented Oct 19, 2019

How introducing features C, D, E, and F in a PATCH version is intended to be compatible with the semantic versioning spec?

@josephdpurcell
Copy link
Author

I am interested in what the PHP/composer/semver community thinks about which option is most reasonable.

@phansys your comment sounds like a vote for "Option 1: Claim it's a release management issue." For the sake of argument though, what if these are all fixes instead of features? i.e. 1.0.59 is a PATCH and 1.0.60 is a PATCH, but there is a need for a patch to 1.0.59 that needs released before 1.0.60? Option 1 may still be valid, but doesn't offer a short term solution. Say we're in this situation, how would you solve it?

@josephdpurcell
Copy link
Author

Edited description to clarify Option 1 is long term with no short term solution. Added 2 more reference materials.

@Seldaek
Copy link
Member

Seldaek commented Oct 24, 2019

Strictly per semver you would have to release 1.0.60 and then your upcoming 1.0.60 would be pushed to 1.0.61.

With Composer though you may use 1.0.60.1 which is supported, or 1.0.59-patch1 which is also supported. Using build metadata (1.0.59+patch1) IMO is not a good idea as this should resolve to the same version as 1.0.59 and thus users won't necessarily update to it.

@Seldaek Seldaek closed this as completed Oct 24, 2019
@josephdpurcell
Copy link
Author

Thanks for the input, @Seldaek!

I apparently did not properly test using a pre-release. This does work! I'm updating the description to show this as Option 6: Use a pre-release tag. This violates Semver since anything X.y.z-* precedes X.y.z, but it does work.

I'll also clarify the assumption that it is not possible to re-tag; that certainly would be a fine option if its available.

@Seldaek
Copy link
Member

Seldaek commented Oct 24, 2019

It is possible to retag but it is generally speaking poor practice as people having updated before the retag can't easily be sure they are on the right tag, and it can cause other issues with git.

@josephdpurcell
Copy link
Author

I've added Option 7: Reference the commit of a build tag. [requires disclaimer].

Also, I updated the "Proposed Resolution" section with some opinions.

What I've concluded is: Which option is the best choice is contextual. If I had to pick one, I would go with Option 2: Use a 4 digit version. While it violates Semver it has the least risk, least effort, and least confusion.

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

No branches or pull requests

3 participants