Skip to content

Changesets

Tyler Butler edited this page Sep 11, 2024 · 21 revisions

Changesets

Last updated September 11 2024

We use a modified version of the changesets workflow to track changes that we want to communicate to customers or partners.

A changeset is a separate concept from either a changelog or release notes, but they are related. The changeset carries with it two key bits of information:

  • the packages affected by the change
  • a Markdown-formatted description of the change

Storing this information directly in git metadata such as commits is problematic because once written, git metadata cannot be changed without disrupting other contributors. This means that when we do a release and generate the changelogs, any tweaks we want to make must be made and stored elsewhere. Changesets allow us to review and fix change announcements just like code. Changesets are stored on the file system in a .changeset folder in the root of the release group (or package, for independent packages).

A changeset is a Markdown file with YAML front matter. The contents of the Markdown is the change summary which will be written to the changelog and the YAML front matter describes what packages have changed and what semver bump types they should be (for the FluidFramework repo the bump types are determined by the target branch).

---
"@myproject/cli": minor
"@myproject/core": minor
---

Change all the things

This is useful because it breaks change tracking into two steps:

  1. Adding a changeset - can be done in a PR, by a contributor, while the change is fresh in their mind.
  2. Releasing/versioning - combines all changesets and writes changelogs, which can then be reviewed in aggregate.

Note

The default changesets workflow and tools, which we are using, include the "bump/release type" (major | minor | patch) for each package in the changeset. Within the FluidFramework repo, the bump type is determined by the branch the change is merged to. Practically speaking, this means most changesets are minor changes. If you use the tools we provide, this metadata will be filled out for you automatically.

Terminology

Package – A self-contained tarball of code and metadata that is published to an npm feed. The smallest component of a release. Also called a library.

Release group – A collection of packages that we version and release together.

Release – A version of a package or release group that has been published to public npm. Importantly, our releases can contain multiple packages in the case of release groups.

(Per-package) Changelog – A file that is typically included in a package that lists the changes per version of the package. Typically called CHANGELOG.md. Sometimes this is just a list of commits, but it’s more useful when organized around things customers care about: new features, major improvements, breaking changes, etc. Example changelog: https://github.com/microsoft/FluidFramework/blob/main/packages/runtime/container-runtime/CHANGELOG.md

Release notes – A curated collection of all the changes in a particular release, including new features, breaking changes, and deprecations. Because we release multiple packages (dozens at a time in the case of client), we can’t expect people to read the individual changes in each package. Release notes are critical because they aggregate the changes across packages into a readable, useful format. Example release notes: https://github.com/microsoft/FluidFramework/releases/tag/client_v2.2.0

Changesets and CI

Changesets are not fully automated yet. For now, PRs that need changesets are manually identified and labeled with the changeset-required label. If the PR is labeled changeset-required (only added manually at this point), then it will be checked for a changeset. If one is missing, then a comment will be added to the PR saying that a changeset is needed, including a link to this documentation.

Custom metadata

We support additional custom metadata in our changesets. This is not supported by any changeset-ecosystem tools, including @changesets/cli; it is a custom addition that we use in our own tools. The additional metadata is provided in a second front matter section under the first. For example:

---
"@myproject/cli": minor
"@myproject/core": minor
---
---
section: fix
includeInReleaseNotes: false
highlight: true
---

Change all the things

More exposition.

All of this metadata is optional, and only some of it will be automatically provided by the tools. This metadata is primarily intended to help with the generation of release notes.

Important

Our custom metadata is not supported by standard changeset tools, including @changesets/cli, which is the core changesets package. Because of this, some of our tools such as flub generate:changelog strip the changesets of this metadata before invoking commands like changeset version. If the custom metadata is not removed, then it ends up in the changelogs, which messes with the changelog formatting and is also confusing.

Release note sections

The release note sections are configured in fluidBuild.config.cjs in the root of the repo. The sections may change release-to-release as our needs change.

Changesets that apply to no packages

Sometimes we have information that needs to be in the release notes but doesn't apply to any packages. An example of this is when you delete a package. The package is deleted, so there's no package to associate the changeset with. However, such changes are likely relevant for the release notes so customers know the packages were deleted. To accomodate this, we support changesets with an empty metadata section:

---
---
---
section: other
---

This changeset will be included in the release notes...

...but not the per-package changelogs.

Tip

Standard changeset tools such as @changesets/cli, which is the core changesets package, silently ignore changesets that apply to no packages (as of version 2.27.8, possibly earlier). This is OK since such changesets are intended to be put into the release notes only, not the per-package changelogs.

Adding a changeset to a PR

Note: the following only applies to the client and server release groups. For independent packages or other release groups, contact @tylerbutler.

You can add a changeset to your PRs manually or by using the pnpm flub changeset add command.

Adding a changeset using pnpm flub changeset add --releaseGroup <releaseGroup>

To add a changeset, run pnpm flub changeset add --releaseGroup <releaseGroup> from the root of the release group. You will be prompted to select the affected packages. By default the CLI will show what packages have changed relative to main to make it easier to select affected packages, but you can compare with any branch by passing the --branch <BRANCH> flag (e.g. --branch next. The output is completely editable after the CLI is used so don't worry about "getting it right." You can always fix it up!

Manually adding a changeset

To manually add a changeset, add a randomly named markdown file to the .changeset folder in the root of the release group. Make sure to include the metadata about what packages are affected!

Adding an empty changeset

You can add an empty changeset using the command pnpm flub changeset add --empty. Remember to add details about the change, including the metadata about what packages are affected!

How do I know what packages to include in the changeset?

Each package in the changeset will have a changelog entry with the contents of the changeset. In other words, if you list a package in a changeset, you're saying that the contents of the changeset are relevant to that package. You do not need to include every package that was changed in a given PR. For example, if you deprecate a class in packageA and replace the use of the deprecated class in packageB, then packageB probably shouldn't be included in the changeset, while packageA should be.

Which PRs require changesets?

Any change that should be communicated to customers or partners should have a changeset. Stated differently, changes without a changeset are "invisible" to customers; changesets are how we track what needs to be communicated with partners and customers. We are discussing how to automate flagging some PRs, but for now it's manual.

Every upgrade of a server or common package in the client release group should have a changeset to ensure clarity about upgrades and prevent unexpected issues. Each changeset should detail any new functionalities, describe bugs fixed in the upgrade, and identify any potential breaking changes. It should also include a link to the release notes or changelog of the upgraded package for easy reference. For example, a changeset should exist when we do major updates to server or common packages.

Do I need to add a changeset with the change, or can I add it later?

You should add a changeset with every change that should be communicated, even if it is empty. The contents of the changeset can be updated at any time before release, but adding the changeset with the relevant change makes it easier to link commits to changelog entries. The presence of the changeset signals "This change contains something that should be communicated to customers. I may not know exactly what should be written yet, but I know it needs to be communicated." You can always add an empty changeset if you really don't know what to communicate to customers yet.

More questions?

Our changesets FAQ may answer them. If not, contact @tylerbutler.

Clone this wiki locally