open-coordinator-backup icon indicating copy to clipboard operation
open-coordinator-backup copied to clipboard

Use “Semantic Versioning" scheme for the format's metadata versions?

Open Hedda opened this issue 4 years ago • 12 comments

metadata

The top-level metadata object contains basic information about the backup itself: ...

  • version: number - specifier that will be incremented upon major specification changes that will require migration or introduce new keys. The current value is 1,

Suggest format use the latest “Semantic Versioning" scheme for versions from the very beginning, and if so maybe start with 0.0.1?

Please consider https://semver.org version format of X.Y.Z (Major.Minor.Patch) for metadata versions, or for application compatibity:

X = X indicate a change in the public API that introduce backward incompatibility. Y = Y indicate an addition of some features or functions Z = X indicate a fix (either fixing bug or build, either changing internal structure without impacting functionnality)

Summary

Given a version number MAJOR.MINOR.PATCH, increment the:

  1. MAJOR version when you make incompatible API changes,
  2. MINOR version when you add functionality in a backwards compatible manner, and
  3. PATCH version when you make backwards compatible bug fixes.

Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.

Hedda avatar Feb 10 '21 09:02 Hedda

If acceptable then suggest change current value for version from 1 to 0.0.1 and continue from there.

metadata

The top-level metadata object contains basic information about the backup itself: ...

  • version: number - specifier that will be incremented upon major specification changes that will require migration or introduce new keys. The current value is 0.0.1,

PS: Also need to remember to change the version in any samples like z2m-sample-1.json

https://github.com/zigpy/open-coordinator-backup/blob/main/samples/z2m-sample-1.json

Hedda avatar Feb 10 '21 09:02 Hedda

Well this is something we have discussed a few times with @puddly. While it would be nice to use semantic versioning (my idea previously as well) keeping the version number a single integer makes it easier to track and perform format migrations. In my opinion it's easier to track changes for low-level formats using simple numeric versioning.

This way when there is a change/removal or addition to the format structure we can easily write one-by-one incremental version migrations which can be easily applied together. Eg 1 -> 2, 2 -> 3, 3 -> 4. We may write the migrations in multiple languages so they will be easy to use by any standard integrator. Without the struggle of maintaining 3 versioning levels.

Let's keep this open for a discussion. @puddly your thoughts?

castorw avatar Feb 10 '21 10:02 castorw

Then one DB or file format is not very likely being changes so frequently its more then OK have single numbers as version. In applications its one other story with large and smale changes is being made of API and applications functions.

MattWestb avatar Feb 10 '21 10:02 MattWestb

Well this is something we have discussed a few times with @puddly. While it would be nice to use semantic versioning (my idea previously as well) keeping the version number a single integer makes it easier to track and perform format migrations. In my opinion it's easier to track changes for low-level formats using simple numeric versioning.

My thought was only that Semantic Versioning scheme like X.Y.Z (Major.Minor.Patch) would make it more future proof for later use.

I guess you could use a Semantic Versioning scheme like X.Y.Z (Major.Minor.Patch) and choose to only ever change the "Z" (Patch)?

Hedda avatar Feb 10 '21 10:02 Hedda

Then its the opposite then its not "patches" for one DB or file formats so only major is being used so back to point one. On the application level its very big difference but its not part of this scope.

MattWestb avatar Feb 10 '21 10:02 MattWestb

I guess you could use a Semantic Versioning scheme like X.Y.Z (Major.Minor.Patch) and choose to only ever change the "Z" (Patch)?

But that is exactly against semantic versioning. We would have to increase major and minor as well to keep it semantic as per the spec:

MAJOR version when you make incompatible API changes,
MINOR version when you add functionality in a backwards compatible manner, and
PATCH version when you make backwards compatible bug fixes.

castorw avatar Feb 10 '21 10:02 castorw

@Hedda Its like the EZSP version 8 is not backward compatible with EZSP version 7 and earlier. The protocol is not having one 7.3.1 that can "talking" version 7 and little more.

MattWestb avatar Feb 10 '21 10:02 MattWestb

All semantics in the end, as long as it does not break the applications from working without updates the devs could say it is a patch.

Apploguise for bikeshedding this. It is not really important to implement any other version scheme until multiple applications use it.

Hedda avatar Feb 10 '21 10:02 Hedda

Even the Semver spec itself never set a minor or patch number, it just jumped from 1.0.0 to 2.0.0 😄

I believe the main purpose of Semver is to simplify package manager constraints (e.g. 1.1.* will in theory allow bugfix releases, 1.*.* if you want the absolute latest version that will likely work with your code). Therefore, a file format like this can't really have a "patch" number. From the perspective of an application trying to read a backup or for that matter write one (do they just increment the patch without changing any code? why?), either the file is fully compatible, the file contains additional keys while retaining backwards compatibility, or it's incompatible. This would sort of leave us with just a major version (indicating compatibility) and a minor version (indicating the addition of new keys).

This was my original idea, to simplify parsing by the application:

"version": [0, 1]

We could also do:

"version": {
    "major": 0,
    "minor": 1
}

The addition of new keys can also be handled implicitly by just asking an application to ignore unknown keys and rely only on the major version, as we have it now.

puddly avatar Feb 10 '21 15:02 puddly

Okay, so maybe we should go for the middle ground. I suggest major and minor versioning using @puddly's original format:

{
   "version": [1, 0]
}

But we need to declare strict rules on how and when the version changes, eg.:

  • minor version is incremented when fields are added in backward-compatible manner,
  • major version is incremented and minor version reset to 0 when an backward-incompatible format change is introduced, eg.:
    • key is renamed,
    • value data format is changed,
    • field is removed,
    • field is moved or in any way re-structured.

Like for agreement 🙃

castorw avatar Feb 10 '21 17:02 castorw

We could also do:

"version": {
    "major": 0,
    "minor": 1
}

IMHO like that later idea as a more human-readable format

Hedda avatar Feb 11 '21 11:02 Hedda

or we could keep it simple, just as a version number and having a policy for the app to support current_version - 2 backward compatibility. After all it is not an app to warrant a sem. versioning.

Adminiuga avatar Feb 11 '21 15:02 Adminiuga