Skip to content

Commit and release process

Bob Nystrom edited this page Nov 27, 2023 · 1 revision

This page describes how changes to dart_style are committed to the repo and how new versions are released and rolled out. If you don't contribute to the formatter, it's probably not useful to you.

Landing changes

The dart_style repo mostly follows a typical GitHub workflow. Changes are uploaded to branches and the author sends a pull request. Code review happens on the pull request and, once approved, the author squashes and merges the PR onto the main branch.

The main branch should always be in a shippable state. Any change that requires multiple commits before the formatter is back into a usable state should be done either on a branch or behind some sort of flag so that users aren't impacted until the work is completely done.

We also need to keep track of what changes have landed and whether a given change has been shipped. To do that:

Update the CHANGELOG

Every PR that affects something user-visible should also add a line to the CHANGELOG file describing the change.

Update the package version

When a PR lands a change, it should update the dart_style version number in the pubspec.yaml file to indicate that there are unpublished changes. If the dart_style version does not end in -wip, then the repo should be exactly equal to the published dart_style package at that version.

Otherwise, the version ends in -wip, and the number preceding that is what the next published version number will be. If we see that the version ends in -wip, we know there are unpublished changes. The way that number is bumped from the previously published version depends on what kinds of changes have landed. For example, let's say the last published version was 1.2.3:

  • If main has some unpublished minor non-breaking changes, then the pubspec's version would be 1.2.4-wip.

  • If main has significant new features but no breaking changes, then the pubspec's version would be 1.3.0-wip.

  • If main has a breaking change, then the version would be 2.0.0-wip.

We don't consider style changes to be "breaking" (otherwise, almost every change would be a breaking change), so most revisions to dart_style are patch releases. Breaking changes usually mean a breaking change to the library API or CLI options. More impactful style changes may necessitate a minor or major version increment.

When you land a change on main, make sure that you update the pubspec's version number as needed to reflect your change. Note that you'll only need to bump the -wip version the first time a change of a certain kind is landed. So if, for example, there are already minor changes and the pubspec's version is 1.2.4-wip, then you can land more minor changes without touching the version. You may need to change the number of an already--wip version if you are landing a change of greater caliber than previous ones. So if the version is 1.2.4-wip and you land the first significant new feature, you'd bump it to 1.3.0-wip.

Releasing a new version of dart_style

The formatter reaches users in two main ways:

  • From the Dart SDK, by running dart format. This uses a version of dart_style that is copied into the Dart SDK.

  • As a library, by depending on the dart_style package and using the public API it exposes. (The package also exposes a command line tool you can invoke using dart run or dart pub global activate, but that's rarely used).

Shipping a new version of the formatter thus means both rolling it into the Dart SDK and publishing a new version of the package onto pub.dev, in that order.

Rolling dart_style into the Dart SDK

Once a package is published to pub, it's very hard to unpublish it. So we want to make sure it doesn't have any regressions or unanticipated style changes. We validate that by testing inside Google before publishing on pub. The Dart SDK is automatically rolled into Google's monorepo on a frequent basis, so by rolling a commit of dart_style into the SDK, we get internal testing on a very large corpus of Dart code.

When we have a commit of the formatter that we are ready to ship, the first step is rolling it into the Dart SDK:

  1. In the Dart SDK repo, update the "dart_style_rev" line in the DEPS file to point to the new commit hash.

TODO: If there are style changes that necessitate updating the pre-built SDK, describe how to do that.

  1. If there are user-visible changes, then update the SDK's CHANGELOG with those changes. You can mostly just copy the relevant entries from dart_style's CHANGELOG over.

  2. Upload that change and send it out for review (rnystrom@, kallentu@, athom@, or anyone on Dart eng-prod can review it).

    If the formatter change includes support for some new language feature, this may cause CFE golden file tests to fail on the trybots. That's because those tests run the formatter if it succeeds or fall back to using the unformatted output if it fails. CFE folks often commit tests for new language features before the formatter supports them, so those golden files will be unformatted. When rolling a new formatter in, those tests can now be successfully formatted, so the (now formatted) expected output doesn't match the (unformatted) golden file.

    If you see test failures like this, the output will have a command to run to update the golden files. Run that, verify that it's just formatting changes, and upload those fixes with the change.

  3. Once you get approval and the bots are green, land the change.

Wait a few days for the SDK to get rolled into Google's monorepo and see if there are any problems. If so, fix them. Otherwise, this commit is now ready to be published...

Publishing a new version of dart_style

Whenever a version of the formatter is rolled into the Dart SDK, we should also publish it. That way, there is always a version of the dart_style library available for tools like code generators that matches the formatting behavior of dart format.

  1. From a local clone of dart_style on the main branch, run:

    $ dart run grinder bump

    That runs the tests and some other sanity checks to make sure the release looks good. It then updates the version number in the pubspec to remove the -wip part. Importantly, it also updates the version number string inside the dart_style library itself. That's the string that's printed when you run dart format -v.

  2. Assuming everything passed and looks good, create and upload a new branch with the changes and send out a PR for review (@munificent, @kallentu, or @natebosch). At this point, the changes should literally just be tweaking the version number in two places. You may also want to clean up the CHANGELOG a bit.

  3. Once the PR is approved, squash and merge it to main. A GitHub action will leave a comment on the PR telling you how to publish a version. That comment will contain the new version number. Click that number to open a page to create a new GitHub release for the version.

  4. Copy the relevant entries from the CHANGELOG into the release notes and then click "Publish release". That creates a new GitHub release for the version which in turn kicks off another Github action that automatically publishes that version to pub.dev.

  5. Go to pub.dev, search for "dart_style" and bask in the glory of having shipped a new version to the world.