For users of the design system who are contributing to Kolibri product ecosystem development, two needs are in conflict:
- Rapid iteration allows the design system to rapidly respond to needs with new and improved components, new and improved design patterns, and rapid fixes
- 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.
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:
MAJORversion 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
displayprop changes from
inlineor the default width changes
- Clarifying question: an update would potentially require someone updating their code, e.g. renaming a component
MINORversion 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
PATCHversion 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.
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.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.
- All user-facing changes for each release should be documented in the changelog.
- The unstable or develop branches of product repos should track the
HEADof the design system
mainbranch. 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
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
// 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
Once we release KDS version
3.0.0 stable, code in
next becomes stable, and stable becomes
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';