Versioning in Signal K specification
Our versioning is based on http://snowplowanalytics.com/blog/2014/05/13/introducing-schemaver-for-semantic-versioning-of-schemas/
Most of this document is reproduced from there.
When versioning a data schema, we are concerned with the backwards-compatibility between the new schema and existing data represented in earlier versions of the schema. This is the fundamental building block of SchemaVer, and explains the divergence from Semantic Versioning.
Heres a simple formula for our SchemaVer:
Given a version number MODEL.REVISION.ADDITION-SUFFIX, increment the:
- MODEL - when you make a breaking schema change which will prevent interaction with any historical data
- REVISION - when you make a schema change which may prevent interaction with some historical data
- ADDITION - when you make a schema change that is compatible with all historical data
SUFFIX - optional - denotes special versions or active development eg
alpha-1
,SNAPSHOT
The first released version of Signal K will be
1.0.0
.- The current development version will then move to be
1.0.1-SNAPSHOT
- The next release candidate might then be
1.0.1-alpha-1
- The current development version will then move to be
1.0.2-SNAPSHOT
SNAPSHOT
denotes a version under active change. If you depend on the SNAPSHOT
version then every time you build your project it will have changed with what-ever was committed since last time you checked.
Let’s make SchemaVer more concrete with some examples using some (truncated and contrived) Signal K Schemas, in reverse order:
Addition
We have an existing JSON Schema, let’s call this 1.0.0
:
{
"type": "object",
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "https://signalk.org/demospecification/1.0.0/schemas/groups/communication.json#",
"description": "Schema describing the communication child-object of a Vessel.",
"title": "communication",
"properties": {
"dscAddress": {
"type": "string",
"description": "MMSI Callsign for VHF communication"
}
},
"required": ["dscAddress"],
"additionalProperties": false
}
Now we want to add an additional field to our schema:
{
"type": "object",
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "https://signalk.org/demospecification/1.0.1/schemas/groups/communication.json#",
"description": "Schema describing the communication child-object of a Vessel.",
"title": "communication",
"properties": {
"dscAddress": {
"type": "string",
"description": "MMSI Callsign for VHF communication"
},
"phoneNumber": {
"type": "string",
"description": "Phone number of skipper",
"example": "+64xxxxxx"
}
},
"required": ["dscAddress"],
"additionalProperties": false
}
Because our new phoneNumber
field is not a required field, and because version 1.0.0
had additionalProperties
set to false
, we know that all historical data will work with this new schema, ie. any json which validates against 1.0.0 will also be valid against 1.0.1.
Therefore we are looking at an ADDITION
, and so we bump the schema version to 1.0.1
.
Revision
Let’s now make our JSON Schema support additionalProperties - this constitutes another ADDITION
, so we are now on 1.0.2
:
{
"type": "object",
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "https://signalk.org/demospecification/1.0.2/schemas/groups/communication.json#",
"description": "Schema describing the communication child-object of a Vessel.",
"title": "communication",
"properties": {
"dscAddress": {
"type": "string",
"description": "MMSI Callsign for VHF communication"
},
"phoneNumber": {
"type": "string",
"description": "Phone number of skipper",
"example": "+64xxxxxx"
}
},
"required": ["dscAddress"],
"additionalProperties": true
}
After a while, we add a new field, callsignHf
:
{
"type": "object",
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "https://signalk.org/demospecification/1.1.0/schemas/groups/communication.json#",
"description": "Schema describing the communication child-object of a Vessel.",
"title": "communication",
"properties": {
"dscAddress": {
"type": "string",
"description": "MMSI Callsign for VHF communication"
},
"phoneNumber": {
"type": "string",
"description": "Phone number of skipper",
"example": "+64xxxxxx"
},
"callsignHf": {
"type": "string",
"description": "Callsign for HF communication",
"example": "ZL3RTH"
}
},
"required": ["dscAddress"],
"additionalProperties": true
}
Will this new schema validate all historical data? Unfortunately we can’t be certain, because there could be historical JSONs where the analyst added their own callsignHf
field which was not a string.
So we are effectively making a REVISION
to the data schema - so we bump the version to 1.1.0
(resetting ADDITION
to 0
).
Model
Oh dear - we have just realized that not every-one has DSC! It should have been a VHF callsign. Here is our new JSON Schema:
{
"type": "object",
"$schema": "http://json-schema.org/draft-04/schema#",
"id": "https://signalk.org/demospecification/2.0.0/schemas/groups/communication.json#",
"description": "Schema describing the communication child-object of a Vessel.",
"title": "communication",
"properties": {
"callsignVhf": {
"type": "string",
"description": "Callsign for VHF communication",
"example": "ZL1234"
},
"phoneNumber": {
"type": "string",
"description": "Phone number of skipper",
"example": "+64xxxxxx"
},
"callsignHf": {
"type": "string",
"description": "Callsign for HF communication",
"example": "ZL3RTH"
}
},
"required": ["callsignVhf"],
"additionalProperties": false
}
We have changed our MODEL
- because we can have no reasonable expectation that any of the historical data can interact with this schema. That means our new version is 2.0.0
Note that we also decided to use this “reboot” of the MODEL
to change additionalProperties
back to false
, because (as we have learnt) it will help us to avoid unnecessary REVISIONs in the future.
Note: https://signalk.org/demospecification/... is not real, it is just used here for illustration. The real schemas are located at: https://signalk.org/specification/...
Supplementary rules
In Signal K we have a few variations from SchemaVer:
- We use dots (.) to separate the version parts, not hyphens (-s) as in SchemaVer
- We use a suffix to denote in-progress or special releases, as commonly seen in Maven