Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

[tools] Add update-release-info #5643

Merged
merged 7 commits into from
May 18, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions script/tool/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.8.6

- Adds `update-release-info` to apply changelog and optional version changes
across multiple packages.

## 0.8.5

- Updates `test` to inculde the Dart unit tests of examples, if any.
Expand Down
26 changes: 26 additions & 0 deletions script/tool/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,32 @@ cd <repository root>
dart run ./script/tool/bin/flutter_plugin_tools.dart update-excerpts --packages plugin_name
```

### Update CHANGELOG and Version

`update-release-info` will automatically update the version and `CHANGELOG.md`
following standard repository style and practice. It can be used for
single-package updates to handled the details of getting the `CHANGELOG.md`
format correct, but is especially useful for bulk updates.

For instance, if you've added a new analysis option that required production
code changes across many packages:

```sh
cd <repository root>
dart run ./script/tool/bin/flutter_plugin_tools.dart update-release-info \
--version=minimal \
--changelog="Fixes violations of new analysis option some_new_option."
--run-on-changed-packages
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can --run-on-changed-packages be the default behavior for this tool, so people don't have to "remember" to pass it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would require some re-plumbing to allow a command to change the default package selection behavior, and it would make it inconsistent with all the other commands. But then, it's a different kind of command than most of the others.

I'll play around with that tomorrow.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I came up with a different solution when I woke up this morning :) Instead of making this command have non-standard package targeting, I just made minimal skip any package that has no changes at all. That makes it even easier to use, since you don't have to worry about the base treeish that run-on-changed-packages is using.

You'll still need to explicitly target for the other modes, but I don't expect the other modes to actually be useful in a bulk-update setting.

```

The `minimal` option for `--version` will treat each package as either `bugfix`
or `next` depending on the files that have changed in that package, so is
often the best choice for a bulk change.

For cases where you know the change time, `minor` or `bugfix` will make the
corresponding version bump, or `next` will update only `CHANGELOG.md` without
changing the version.

### Publish a Release

**Releases are automated for `flutter/plugins` and `flutter/packages`.**
Expand Down
93 changes: 93 additions & 0 deletions script/tool/lib/src/common/package_state_utils.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:meta/meta.dart';
import 'package:path/path.dart' as p;

import 'repository_package.dart';

/// The state of a package on disk relative to git state.
@immutable
class PackageChangeState {
/// Creates a new immutable state instance.
const PackageChangeState({
required this.hasChanges,
required this.hasChangelogChange,
required this.needsVersionChange,
});

/// True if there are any changes to files in the package.
final bool hasChanges;

/// True if the package's CHANGELOG.md has been changed.
final bool hasChangelogChange;

/// True if any changes in the package require a version change according
/// to repository policy.
final bool needsVersionChange;
}

/// Checks [package] against [changedPaths] to determine what changes it has
/// and how those changes relate to repository policy about CHANGELOG and
/// version updates.
///
/// [changedPaths] should be a list of POSIX-style paths from a common root,
/// and [relativePackagePath] should be the path to [package] from that same
/// root. Commonly these will come from `gitVersionFinder.getChangedFiles()`
/// and `getRelativePoixPath(package.directory, gitDir.path)` respectively;
/// they are arguments mainly to allow for caching the changed paths for an
/// entire command run.
PackageChangeState checkPackageChangeState(
RepositoryPackage package, {
required List<String> changedPaths,
required String relativePackagePath,
}) {
final String packagePrefix = relativePackagePath.endsWith('/')
? relativePackagePath
: '$relativePackagePath/';

bool hasChanges = false;
bool hasChangelogChange = false;
bool needsVersionChange = false;
for (final String path in changedPaths) {
// Only consider files within the package.
if (!path.startsWith(packagePrefix)) {
continue;
}
final String packageRelativePath = path.substring(packagePrefix.length);
hasChanges = true;

final List<String> components = p.posix.split(packageRelativePath);
if (components.isEmpty) {
continue;
}
final bool isChangelog = components.first == 'CHANGELOG.md';
if (isChangelog) {
hasChangelogChange = true;
}

if (!needsVersionChange &&
!isChangelog &&
// The example's main.dart is shown on pub.dev, but for anything else
// in the example publishing has no purpose.
!(components.contains('example') && components.last != 'main.dart') &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't you place a markdown file in example alternatively?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True; added support for README.md and example.md.

(The heuristic here isn't perfect; there are some even more obscure files that could be shown but we never use, and this could also have false positives if, e.g., you change one of the potentially special files in a package that also has one of the other, higher-priority files, but in practice that's going to be extremely rare, and there's always a way to override the heuristic.)

// Changes to tests don't need to be published.
!components.contains('test') &&
!components.contains('androidTest') &&
!components.contains('RunnerTests') &&
!components.contains('RunnerUITests') &&
// The top-level "tool" directory is for non-client-facing utility code,
// so doesn't need to be published.
components.first != 'tool' &&
// Ignoring lints doesn't affect clients.
!components.contains('lint-baseline.xml')) {
needsVersionChange = true;
}
}

return PackageChangeState(
hasChanges: hasChanges,
hasChangelogChange: hasChangelogChange,
needsVersionChange: needsVersionChange);
}
2 changes: 2 additions & 0 deletions script/tool/lib/src/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import 'pubspec_check_command.dart';
import 'readme_check_command.dart';
import 'test_command.dart';
import 'update_excerpts_command.dart';
import 'update_release_info_command.dart';
import 'version_check_command.dart';
import 'xcode_analyze_command.dart';

Expand Down Expand Up @@ -70,6 +71,7 @@ void main(List<String> args) {
..addCommand(ReadmeCheckCommand(packagesDir))
..addCommand(TestCommand(packagesDir))
..addCommand(UpdateExcerptsCommand(packagesDir))
..addCommand(UpdateReleaseInfoCommand(packagesDir))
..addCommand(VersionCheckCommand(packagesDir))
..addCommand(XcodeAnalyzeCommand(packagesDir));

Expand Down
Loading