semantic_changelog

MIT License

Stars
34
Committers
2

Welcome to semantic_changelog!

This repository is a set of tools designed to do package versioning using changelogs.

It is primarily designed for maintaining my own packages, as it is the convention I use for Riverpod/Freezed/... But feel free to clone this and use it~

Motivation

When maintaining large open-source projects (often mono-repositories), dealing with version bump can be tedious. One common issue is dealing with dependencies. For example, a package a may depend on a package b. Then, when incrementing the version of b, we also need to update the dependency of b in the a package.

There are tools to help with this, such as conventional_commits. The problem is that they rely on commits.

There are a number of problems with this approach:

  • In a mono-repository, one PR may affect multiple packages at once in a different way. For example, this PR can both require a 0.0.x bump for one package, but require a x.0.0 bump for another package. Using conventional_commits, this would require using separate commits for these changes. This is tedious to do and doesn't quite match the typical developer workflow.

  • Having a clean commit history can be difficult. Asking contributors to an OSS package to rewrite the git history of their PR for the sake of package versioning can add a significant burden to contributors. This is also very error prone, and a mistake could easily slip by during reviews.

  • The semantic commit approach does not promote reviewing changelogs during PR reviews. Changelogs are core to users of a package. But by relying on commits to generate a changelog, the person who will write the changelog changes will be the person who will do the package release instead of the author of the PR changes. As such, mistakes tend to slip by.

How it works

The idea of semantic changelogs is that we do not rely anymore on commits for package versions. Instead, our changelog is the source of truth for versioning.

In short, when writing a PR, the PR must include a changelog entry matching the following:

## Unreleased <breaking/major/minor/patch>

/_ insert description about the changes one by this PR _/

## 1.2.3

/_ content of the changelog before this PR _/

The point is that the first line of the CHANGELOG.md of a package impacted by a PR should contain an indication on how to bump the package version.

Then, when it is time to make a release, the version number is bumped by relying on the major/minor/patch flag picked. The Unreleased <flag> text is then replaced by the new package version.

By doing so, the git history no-longer matters. It also become possible to make a breaking change for one package but only a bugfix for another package, all in one commit.

This is doable because each package should have its own changelog. In which case we could have:

// The changelog of "packages/foo"

## Unreleased major
// The changelog of "packages/bar"

## Unreleased patch

At the same time, this approach can be easily validated in the CI. A CI could check that a changelog is modified if a package is modified, and that the changelog starts with ## Unreleased <flag>

Installing the command lines (Dart only)

This convention comes with a Dart command line for applying it to Dart projects. You can install it with dart pub global activate -s git https://github.com/rrousselGit/semantic_changelog/.

Updating package versions

To update pubspec.yamls, you can run:

# Look-up for all projects in the current folder, and based on their changelog
# update the package versions
version bump

Example of output:

$ version bump
The following packages have been updated:
riverpod            : 2.3.0 -> 2.3.1
flutter_riverpod    : 2.3.0 -> 2.3.1
hooks_riverpod      : 2.3.0 -> 2.3.1

Asserting that a Pull Request contains the necessary CHANGELOG updates

Chances are you will want to automate checking in pull-requests that CHANGELOG files are correctly modified.

For this, you can run:

version check main

This will compare your current git branch with the "main" branch. And if a package is modified but does not contain a CHANGELOG entry, then this command will fail:

$ version check
Changes detected for package `riverpod_generator` at `packages/riverpod_generator`, but no CHANGELOG.md entry found.
Please add a CHANGELOG.md entry for this package.
To do so, start the CHANGELOG.md with `## Unreleased major/minor/patch` and explain the changes introduced.

Changed files (total 28):
  packages/riverpod_generator/integration/build_yaml/README.md
  packages/riverpod_generator/integration/build_yaml/pubspec.yaml
  packages/riverpod_generator/lib/src/parse_generator.dart
  ...

Publishing new versions to git/pub

Once your pubspecs have been updated, you can publish the changes with:

# After running "version bump", you can now run this command to both "git tag"
# and publish modified packages to pub.dev.
version publish

Example of output:

$ version publish
The following packages will be published:
riverpod            : (2.3.1)
flutter_riverpod    : (2.3.1)
hooks_riverpod      : (2.3.1)
✔ Continue? (y/N) ‥ y
✓ riverpod
✓ flutter_riverpod
✓ hooks_riverpod