zigpy / open-coordinator-backup

Open Zigbee coordinator backup format
MIT License
56 stars 7 forks source link

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

Open Hedda opened 3 years ago

Hedda commented 3 years ago

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 commented 3 years ago

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: ...

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

castorw commented 3 years ago

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?

MattWestb commented 3 years ago

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.

Hedda commented 3 years ago

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)?

MattWestb commented 3 years ago

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.

castorw commented 3 years ago

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.
MattWestb commented 3 years ago

@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.

Hedda commented 3 years ago

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.

puddly commented 3 years ago

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.

castorw commented 3 years ago

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.:

Like for agreement 🙃

Hedda commented 3 years ago

We could also do:

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

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

Adminiuga commented 3 years ago

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.