Skip to content

Semantic Versioning

John Bodley edited this page Nov 16, 2023 · 4 revisions

The principles of Semantic Versioning are outlined in this document by Tom Preston-Werner co-founder of GitHub. The proposal is to follow these guidelines with regard to public releases of Superset. The definitions for what is a major/minor and patch release are described in the document, but in this document, we should clearly define what a breaking change on Superset is and then how to communicate it.

We also want to set up guidelines for deprecating features and announcing those deprecations in the changelog and release notes, and then fully removing the feature in a breaking change at some later date with a major version release. The goal is to have fewer breaking changes and to aim for changes to be backward compatible and then grouped together in a major release.

What is a breaking change?

  • CLI
    • Removal of a command
    • Addition of required argument flag
    • Removal of an argument flag in a way that removes functionality and could break any integrations
  • API
    • Removing/changing the url of a route
    • Adding/renaming required parameters
    • Addition of a required header
  • Feature or Config Flags
    • Removing a flag or switching the default in the config
    • Removing a callable method that is defined in the configs or updating it in a way that would break its integration, such as adding or removing required arguments
  • Database migrations
    • Migrations that take a lot of time and downtime or alternative methods of deployment needs to be accounted for or planned.
    • Destructive changes in data types, structure or nullable, i.e., reducing varchar amount, going from bigint to int, or changing the schema of a json blob, making a column not null when it was previously nullable.
  • UI
    • Changes that removes an existing functionality, such as a chart type or ability to select favorites. Inconsequential visual changes or small functional changes such as removing a tooltip or the removing the ability to color a label aren't considered breaking changes.
    • Changes that break an existing workflow without providing a clear alternative or require user intervention for the alternative to be applied.
  • Superset UI
    • Any updates to the ChartPlugin class and its constructor arguments that break an existing visual plugin
  • User roles/permissions
    • Changes that would remove current functionality for a user
    • With discretion, any changes that give users a significant amount of permissions where they didn’t have permissions before could also be considered a breaking change and users should be given sufficient notification.
  • Python version upgrades
    • Any changes that are version bumps in Python that would require users to upgrade their systems. We currently support the last three minor versions of Python.
  • SQLAlchemy version upgrades
    • Any changes that are major version bumps in SQLAlchemy that would require users to upgrade their databases
  • Database connectors
    • Any changes that would remove functionality for a particular database that is currently supported.

Best practices to make changes backward compatible

  • CLI
    • Add a new command and keep the existing command. Prompt users of the old command that it is deprecated and encourage them to use the new one.
  • API
    • Add new routes and leave the old routes intact. Message users in the changelog that the old API endpoints are deprecated and will be removed in the x.0 release.
    • Alternatively for larger systemic changes, create a new API version.
  • Feature or Config Flags
    • Before removing a flag that would create a breaking change, notate in the changelog and release notes that the flag/feature is deprecated and will be removed in the x.0 release.
    • When adding a new flag, the existing functionality should remain the default. Even though the new flag is in the base config file, it’s best to set the default to the “false” value of the flag.
    • Switching the default to “on” is a breaking change if the flag removes some functionality or breaks the UI (see other breaking change guidelines). Setting a flag to default to “on” should only be done in major release versions if the resulting change is a breaking change.
  • Database Migrations
    • If a migration has a script that updates data to conform to new database schema, most deployment strategies will run the migration live with the existing code and then deploy the new code, causing downtime between when the migration is run and the new code is deployed. Therefore, be very cautious about changing database schemas. Below are some suggestions to avoid downtime:
    • Optimize migrations and scripts to run without creating too much load on the database. Split them up and run separately when possible.
    • Columns should not be renamed, and instead a new column with a new name should be added. An additional migration can remove the now unused column once all references to it are removed from code in a major release.
    • Columns should not be deleted, unless all references to it are removed from code in a previous release. The migration to delete the column should occur in a major release.
    • Schema changes such as JSON blob structure, reducing varchar limits, changing bigint to an int or making a column not null should be treated like column changes. Instead of changing the data structure in the same column, create a new column with the new schema or structure, copy the data to the new structure, and then point the code to the new column. In a later major release, remove the old column.
    • In the case of a column, schema or table name change, if a destructive migration (removal of a column or table) is in a major release and there is a migration in a previous version that has created a related new table or column with a code update, a note should be added to the changelog to encourage admins to first upgrade Superset to the latest minor version, deploy the code and run the migrations, and then to upgrade to the major version. This way code is deployed with the updated migration that adds a table or column first and then the destructive migration is run afterward.
  • UI
    • Changing the look and adding features is considered backward compatible, but removing critical features is not. Put old functionality in a feature flag (default the flag with the old functionality to “false”) and remove the functionality with the “true” value of the flag. In the changelog, alert users of upcoming changes before removing the flag or changing the default to the new flag.
  • User roles/permissions
    • Instead of removing permissions, put the old functionality in a feature flag (default the old functionality to “false”) and remove the functionality with the “true” value of the flag.
  • Python version upgrades
    • Since we only support the last three minor versions, any minor Python version upgrades could require some users to upgrade their Python version. Therefore, minor Python version bumps should be considered breaking changes.
  • SQLAlchemy major version upgrades
    • SQLAlchemy major upgrades should be carefully tested for cases where the upgrade would break integration for users that may be on an older database version that is no longer supported or with any loss of functionality. When in doubt, add the upgrade to a Superset major version release.
  • Database Connectors
    • Instead of removing database functionality, put the old functionality in a feature flag (default the old functionality to “false”) and remove the functionality with the “true” value of the flag.

How to announce a breaking change in a PR

According to https://www.conventionalcommits.org/en/v1.0.0/#specification to announcing a breaking change in a commit message an ! is added to the prefix just before the colon, such as feat!: replace old charts with different ones. Reviewers should only allow this to be merged when the next release planned is a breaking change or if the author was able to make sufficient changes after feedback from reviewers to make the PR backward compatible. Also a risk:breaking-change tag should be added to the PR. This change should be notated in the changelog.

PR reviewers should also be diligent when looking at the code to identify if there are any breaking changes in the PR and make suggestions and recommendations to the author to label the PR as breaking if they feel it is warranted or even better, to make the code backward compatible.

A “TODO” should be added in the code with a greppable tag of “TODO: DEPRECATION” with any helpful instructions for what code needs to be changed or removed in order to remove the functionality at the next major version. Keep in mind that someone else other than the author may be removing the functionality at a later date, so clear instructions are helpful.

UPDATING.md should be updated with a “Deprecated” section for each release, and for major bumps, a “Breaking Change” section should be added. This document adds more context than what we can get from the PR commit message, and will be partially copied into the changelog. The full format of the changelog with deprecation and breaking change notifications is TBD.

How to announce deprecations to users

The changelog should contain information about features that are deprecated, and clearly notate when it is going to be permanently removed. I.e., “The feature flag “ANIMATED_WINDOWS” has been deprecated and will be removed in the 2.0 release.

We should be able to automatically pull this from UPDATING.MD into the changelog.

When possible, it is encouraged to log a message to users when they are using a feature that is deprecated, and let them know that the feature will be removed soon. CLI logs are a good example.

We should try to give users a sufficient amount of time between deprecating and removing functionality, to allow them to update their integrations.

How to announce breaking changes to contributors

The changelog for the major version bumps should contain information about any necessary changes that users will need to make to their codebase, integrations, databases, or charts before upgrading so that there are no interruptions in their usage of the platform. We can continue to point contributors to UPDATING.MD for more specific information on how to make the update. The release notes should also mention deprecations and breaking changes, but likely with less technical information, so it may be a subset of what is communicated in the changelog.

How to implement breaking changes upon a major version bump

Just before a major version branch/rc branch is cut, a commit (or multiple commits) should be merged into master that remove(s) any deprecated features/flags/backward incompatible changes. This sweep through the code and changelog for deprecated features ensures that we keep our code clean and are diligent about removing deprecated functionality on each major version bump. If the changelog is well documented with deprecation notes, we should be able to find what needs to be removed from that list.

What if something is inadvertently added to a minor or patch release that is a breaking change?

If a breaking change is released, a patch fix should be released as soon as possible correcting/reverting the breaking change and a note for the affected version in the changelog should highlight that a breaking change is in that release, and encourage users to take the next patched version.

What if a security issue requires a change that is a breaking change?

Security fixes with a breaking change should always go into the next release as a major version. If necessary, this can happen quickly if it is just cherry picked onto the last version, with a major version bump. Security fixes that are backward compatible should go with the next release or as a patch on the last release. If the fix is backward compatible and the next release is a major version (as if the security issue was detected as we were building the next major version), then we should also backport the security fix to the last release as well so that we can fix the issue for people who have Superset pinned to the last major (or minor) version, and don't notice that there is a security fix/issue.

What if a breaking change gets introduced into a release as a bug?

If a breaking change is introduced into a minor or patch release that is considered a bug, fix the bug as soon as possible in the next patch or minor release. You do not need to do anything to make that release a major version.

Clone this wiki locally