Motivations

For users of the design system who are contributing to Kolibri product ecosystem development, two needs are in conflict:

  1. Rapid iteration allows the design system to rapidly respond to needs with new and improved components, new and improved design patterns, and rapid fixes
  2. Long-term stability allows the design system to form a stable and predictable foundation on which contributors can confidently build, with the expectation that the resulting work will not need to be revisited or break in the future

Our release process is designed to support both of these needs by being precise about what kinds of changes can happen in which types of releases, and also and facilitating an upgrade process to help all Kolibri products (specifically the Learning Platform, Studio, and Data Portal) stay up-to-date.

Semantic versioning

We use semantic versioning to help define what kinds of changes go in different kinds of releases.

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

  • MAJOR version for incompatible or breaking changes. For example:
    • A previously optional prop becomes required
    • New design guidance is added that contradicts previous guidance or creates a new fixed rule
    • Layout updates are made to a component, e.g. a CSS display prop changes from block to inline or the default width changes
    • Clarifying question: an update would potentially require someone updating their code, e.g. renaming a component
  • MINOR version for new or backwards-compatible functionality. For example:
    • A new component is added
    • Documentation or design guidance conventions (as opposed to rules) are added
    • Purely stylistic updates are made to a component or a new prop is added
  • PATCH version for backwards compatible bug fixes. For example:
    • A minor bug is fixed
    • Documentation and design guidance fixes or clarifications are made

Design patterns and APIs

The design system provides two kinds of "contracts" which may change from release to release:

  • The set of design patterns and guidance describe the current UX/UI conventions and best practices
  • The set of library components and their configuration options describe the current API

Significant changes to design patterns can be as important as API changes. For example, if we were to introduce strict new guidance that says "No text should ever be smaller than 11px", this would be considered a MAJOR version change because it requires us to go through the Learning Platform, Studio, and Data Portal to ensure that this new guidance is actually being followed.

Technical details

Git branches and tags

The design system is currently developed and released from a single main branch. Updates are made in transient feature branches, tested, and merged into main. Specific releases (such as v1.2.3) are represented as Github releases and Git tags.

The single-branch model does not support maintaining multiple releases in parallel – for example, releasing a new v1.2.3 after v1.3.0 has already happened. If this becomes necessary at some point we would make a dedicated release branch called v1.2.x for the purpose, similar to Kolibri's branching model.

Update policies

  • All user-facing changes for each release should be documented in the changelog.
  • The unstable or develop branches of product repos should track the HEAD of the design system main branch. It is the responsibility of the Design System Circle to make sure this happens.
  • The stable or release branches of product repos should be pinned to a stable, tagged version of the design system.

'Next' and 'Deprecated' components

To help smooth upgrades, the design system has a process for making both pre-release and deprecated versions of individual components available from a single monorepo:

Within a major design system release, components always have a current stable version. Components may also optionally have a next and/or deprecated version available, allowing access to newer or older major versions respectively.

For illustration, assume that the current stable version of the design system is 2.3.4. All importable modules are by default the 'current' version. For example:


      // imports KButton version 2.3.4 (current stable) import KModal from
      'kolibri-design-system/lib/KButton';
    

If (and only if) we plan on introducing breaking changes to a component, we would add a sub-directory called next to house this work and allow people to test or even use the alpha version while they are still mostly using 2.x.y stable:


      // imports KButton version 3.0.0-alpha (next unstable) import KModal from
      'kolibri-design-system/lib/KButton/next';
    

An update to next code might count as a patch release bump for the current stable semantic version. For example, we might release 2.3.5 with a changelog entry like:

Version 2.3.5: Renamed the text prop in lib/KButton/next to label

Once we release KDS version 3.0.0 stable, code in next becomes stable, and stable becomes deprecated:

Version 3.0.0: Added a new version of KButton addressing API inconsistency


      // imports KButton version 2.3.5 (deprecated) import KModal from
      'kolibri-design-system/lib/KButton/deprecated'; // imports KButton version 3.0.0 (current
      stable) import KModal from 'kolibri-design-system/lib/KButton';
    

It's unlikely that at this point a new next version of KButton would also be introduced, because we want to minimize churn and and unnecessary breaking changes. However, in rare cases we might need to do this, and there be three versions all available simultaneously:

Version 3.0.1: Added a new alpha version of KButton to address unexpected issue


      // imports KButton version 2.3.5 (deprecated)
      import KModal from 'kolibri-design-system/lib/KButton/deprecated';

      // imports KButton version 3.0.1 (current stable)
      import KModal from 'kolibri-design-system/lib/KButton';

      // imports KButton version 4.0.0-alpha (next unstable)
      import KModal from 'kolibri-design-system/lib/KButton/next';