Fix and update version checks (#3792)
Currently our version update checks aren't actually working; the script doesn't work correctly if no explicit --base-sha is passed, but that's always how CI is calling it.
Fixes https://github.com/flutter/flutter/issues/79823 (and version checks in general)
This makes a number of changes:
- Fixes it to work without --base-sha
- Adds tests that it works in that mode
- And tightens existing tests to require ToolExit, not just any error, to reduce false-positive test success
- Adds verbose logging of the checks being done, to make it easier to debug this kind of issue in the future
- Tightens the exception handling for missing previous versions to just the line that's expected to fail in that case
- Only allows missing versions when "publish_to: none" is set
- Adds that everywhere it's missing
- Standardize the format in the repo to "none" (instead of also having "'none'").
- Allows the use of NEXT in CHANGELOG as a way of gathering changes that are worth noting, but not
doing a publish cycle for. (Replaces the plan of using -dev versions, since that's actually harder to implement,
and more confusing.)
- Ensures that we don't forget to clean up NEXT entries when bumping versions
diff --git a/packages/android_alarm_manager/example/pubspec.yaml b/packages/android_alarm_manager/example/pubspec.yaml
index 7852534..e948ac2 100644
--- a/packages/android_alarm_manager/example/pubspec.yaml
+++ b/packages/android_alarm_manager/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: android_alarm_manager_example
description: Demonstrates how to use the android_alarm_manager plugin.
+publish_to: none
dependencies:
flutter:
diff --git a/packages/android_intent/example/pubspec.yaml b/packages/android_intent/example/pubspec.yaml
index fc15451..0104749 100644
--- a/packages/android_intent/example/pubspec.yaml
+++ b/packages/android_intent/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: android_intent_example
description: Demonstrates how to use the android_intent plugin.
+publish_to: none
dependencies:
flutter:
diff --git a/packages/battery/battery/example/pubspec.yaml b/packages/battery/battery/example/pubspec.yaml
index 648e9f5..a2a6527 100644
--- a/packages/battery/battery/example/pubspec.yaml
+++ b/packages/battery/battery/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: battery_example
description: Demonstrates how to use the battery plugin.
+publish_to: none
dependencies:
flutter:
diff --git a/packages/camera/camera/example/pubspec.yaml b/packages/camera/camera/example/pubspec.yaml
index 5fdaf58..0c06de9 100644
--- a/packages/camera/camera/example/pubspec.yaml
+++ b/packages/camera/camera/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: camera_example
description: Demonstrates how to use the camera plugin.
+publish_to: none
dependencies:
camera:
diff --git a/packages/connectivity/connectivity/example/pubspec.yaml b/packages/connectivity/connectivity/example/pubspec.yaml
index 58d6f0d..2eb6953 100644
--- a/packages/connectivity/connectivity/example/pubspec.yaml
+++ b/packages/connectivity/connectivity/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: connectivity_example
description: Demonstrates how to use the connectivity plugin.
+publish_to: none
dependencies:
flutter:
diff --git a/packages/connectivity/connectivity_macos/example/pubspec.yaml b/packages/connectivity/connectivity_macos/example/pubspec.yaml
index d130158..27baef7 100644
--- a/packages/connectivity/connectivity_macos/example/pubspec.yaml
+++ b/packages/connectivity/connectivity_macos/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: connectivity_example
description: Demonstrates how to use the connectivity plugin.
+publish_to: none
dependencies:
flutter:
diff --git a/packages/device_info/device_info/example/pubspec.yaml b/packages/device_info/device_info/example/pubspec.yaml
index 36b6d6e..5c158a3 100644
--- a/packages/device_info/device_info/example/pubspec.yaml
+++ b/packages/device_info/device_info/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: device_info_example
description: Demonstrates how to use the device_info plugin.
+publish_to: none
dependencies:
flutter:
diff --git a/packages/device_info/device_info_platform_interface/lib/model/android_device_info.dart b/packages/device_info/device_info_platform_interface/lib/model/android_device_info.dart
index 961d373..b61dc14 100644
--- a/packages/device_info/device_info_platform_interface/lib/model/android_device_info.dart
+++ b/packages/device_info/device_info_platform_interface/lib/model/android_device_info.dart
@@ -29,7 +29,7 @@
required this.isPhysicalDevice,
required this.androidId,
required List<String> systemFeatures,
- }) : supported32BitAbis = List<String>.unmodifiable(supported32BitAbis),
+ }) : supported32BitAbis = List<String>.unmodifiable(supported32BitAbis),
supported64BitAbis = List<String>.unmodifiable(supported64BitAbis),
supportedAbis = List<String>.unmodifiable(supportedAbis),
systemFeatures = List<String>.unmodifiable(systemFeatures);
diff --git a/packages/espresso/example/pubspec.yaml b/packages/espresso/example/pubspec.yaml
index 6e824ac..fe40421 100644
--- a/packages/espresso/example/pubspec.yaml
+++ b/packages/espresso/example/pubspec.yaml
@@ -1,6 +1,6 @@
name: espresso_example
description: Demonstrates how to use the espresso plugin.
-publish_to: 'none'
+publish_to: none
environment:
sdk: ">=2.12.0-259.9.beta <3.0.0"
diff --git a/packages/file_selector/file_selector/example/pubspec.yaml b/packages/file_selector/file_selector/example/pubspec.yaml
index 580237c..b2bbbb0 100644
--- a/packages/file_selector/file_selector/example/pubspec.yaml
+++ b/packages/file_selector/file_selector/example/pubspec.yaml
@@ -1,7 +1,6 @@
name: example
description: A new Flutter project.
-
-publish_to: 'none' # Remove this line if you wish to publish to pub.dev
+publish_to: none
version: 1.0.0+1
diff --git a/packages/flutter_plugin_android_lifecycle/example/pubspec.yaml b/packages/flutter_plugin_android_lifecycle/example/pubspec.yaml
index 4506437..e0d225c 100644
--- a/packages/flutter_plugin_android_lifecycle/example/pubspec.yaml
+++ b/packages/flutter_plugin_android_lifecycle/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: flutter_plugin_android_lifecycle_example
description: Demonstrates how to use the flutter_plugin_android_lifecycle plugin.
+publish_to: none
dependencies:
flutter:
diff --git a/packages/google_maps_flutter/google_maps_flutter/example/pubspec.yaml b/packages/google_maps_flutter/google_maps_flutter/example/pubspec.yaml
index eb06e09..0035c96 100644
--- a/packages/google_maps_flutter/google_maps_flutter/example/pubspec.yaml
+++ b/packages/google_maps_flutter/google_maps_flutter/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: google_maps_flutter_example
description: Demonstrates how to use the google_maps_flutter plugin.
+publish_to: none
environment:
sdk: '>=2.12.0-259.9.beta <3.0.0'
diff --git a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/circles.dart b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/circles.dart
index 2a19d87..ae8faa0 100644
--- a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/circles.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/circles.dart
@@ -15,7 +15,7 @@
/// Initialize the cache. The [StreamController] comes from the [GoogleMapController], and is shared with other controllers.
CirclesController({
required StreamController<MapEvent> stream,
- }) : _streamController = stream,
+ }) : _streamController = stream,
_circleIdToController = Map<CircleId, CircleController>();
/// Returns the cache of [CircleController]s. Test only.
diff --git a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/markers.dart b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/markers.dart
index 704577b..b650b9b 100644
--- a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/markers.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/markers.dart
@@ -15,7 +15,7 @@
/// Initialize the cache. The [StreamController] comes from the [GoogleMapController], and is shared with other controllers.
MarkersController({
required StreamController<MapEvent> stream,
- }) : _streamController = stream,
+ }) : _streamController = stream,
_markerIdToController = Map<MarkerId, MarkerController>();
/// Returns the cache of [MarkerController]s. Test only.
diff --git a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/polygons.dart b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/polygons.dart
index ef51bd6..8a964315 100644
--- a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/polygons.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/polygons.dart
@@ -15,7 +15,7 @@
/// Initializes the cache. The [StreamController] comes from the [GoogleMapController], and is shared with other controllers.
PolygonsController({
required StreamController<MapEvent> stream,
- }) : _streamController = stream,
+ }) : _streamController = stream,
_polygonIdToController = Map<PolygonId, PolygonController>();
/// Returns the cache of [PolygonController]s. Test only.
diff --git a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/polylines.dart b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/polylines.dart
index 184c0d9..695b295 100644
--- a/packages/google_maps_flutter/google_maps_flutter_web/lib/src/polylines.dart
+++ b/packages/google_maps_flutter/google_maps_flutter_web/lib/src/polylines.dart
@@ -15,7 +15,7 @@
/// Initializes the cache. The [StreamController] comes from the [GoogleMapController], and is shared with other controllers.
PolylinesController({
required StreamController<MapEvent> stream,
- }) : _streamController = stream,
+ }) : _streamController = stream,
_polylineIdToController = Map<PolylineId, PolylineController>();
/// Returns the cache of [PolylineContrller]s. Test only.
diff --git a/packages/google_sign_in/google_sign_in/example/pubspec.yaml b/packages/google_sign_in/google_sign_in/example/pubspec.yaml
index f08a131..721e77e 100755
--- a/packages/google_sign_in/google_sign_in/example/pubspec.yaml
+++ b/packages/google_sign_in/google_sign_in/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: google_sign_in_example
description: Example of Google Sign-In plugin.
+publish_to: none
dependencies:
flutter:
diff --git a/packages/image_picker/image_picker/example/pubspec.yaml b/packages/image_picker/image_picker/example/pubspec.yaml
index b2e5b63..a52b0f5 100755
--- a/packages/image_picker/image_picker/example/pubspec.yaml
+++ b/packages/image_picker/image_picker/example/pubspec.yaml
@@ -1,6 +1,6 @@
name: image_picker_example
description: Demonstrates how to use the image_picker plugin.
-author: Flutter Team <flutter-dev@googlegroups.com>
+publish_to: none
dependencies:
video_player: ^2.0.0-nullsafety.7
diff --git a/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml b/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml
index 8d193de..6625cb9 100644
--- a/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml
+++ b/packages/in_app_purchase/in_app_purchase/example/pubspec.yaml
@@ -1,6 +1,6 @@
name: in_app_purchase_example
description: Demonstrates how to use the in_app_purchase plugin.
-author: Flutter Team <flutter-dev@googlegroups.com>
+publish_to: none
dependencies:
flutter:
diff --git a/packages/integration_test/example/pubspec.yaml b/packages/integration_test/example/pubspec.yaml
index 558d5f7..e39f115 100644
--- a/packages/integration_test/example/pubspec.yaml
+++ b/packages/integration_test/example/pubspec.yaml
@@ -1,6 +1,6 @@
name: integration_test_example
description: Demonstrates how to use the integration_test plugin.
-publish_to: 'none'
+publish_to: none
environment:
sdk: ">=2.1.0 <3.0.0"
diff --git a/packages/ios_platform_images/example/pubspec.yaml b/packages/ios_platform_images/example/pubspec.yaml
index 552790e..e87dd59 100644
--- a/packages/ios_platform_images/example/pubspec.yaml
+++ b/packages/ios_platform_images/example/pubspec.yaml
@@ -1,6 +1,6 @@
name: ios_platform_images_example
description: Demonstrates how to use the ios_platform_images plugin.
-publish_to: 'none'
+publish_to: none
homepage: https://github.com/flutter/plugins/tree/master/packages/ios_platform_images/ios_platform_images
environment:
diff --git a/packages/local_auth/example/pubspec.yaml b/packages/local_auth/example/pubspec.yaml
index aad68c5..7cc6b39 100644
--- a/packages/local_auth/example/pubspec.yaml
+++ b/packages/local_auth/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: local_auth_example
description: Demonstrates how to use the local_auth plugin.
+publish_to: none
dependencies:
flutter:
diff --git a/packages/package_info/example/pubspec.yaml b/packages/package_info/example/pubspec.yaml
index 0e47ad2..139b9e2 100644
--- a/packages/package_info/example/pubspec.yaml
+++ b/packages/package_info/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: package_info_example
description: Demonstrates how to use the package_info plugin.
+publish_to: none
dependencies:
flutter:
diff --git a/packages/path_provider/path_provider/example/pubspec.yaml b/packages/path_provider/path_provider/example/pubspec.yaml
index 326c68e..6ebde43 100644
--- a/packages/path_provider/path_provider/example/pubspec.yaml
+++ b/packages/path_provider/path_provider/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: path_provider_example
description: Demonstrates how to use the path_provider plugin.
+publish_to: none
dependencies:
flutter:
diff --git a/packages/path_provider/path_provider_macos/example/pubspec.yaml b/packages/path_provider/path_provider_macos/example/pubspec.yaml
index 1451dea..f91678c 100644
--- a/packages/path_provider/path_provider_macos/example/pubspec.yaml
+++ b/packages/path_provider/path_provider_macos/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: path_provider_example
description: Demonstrates how to use the path_provider plugin.
+publish_to: none
dependencies:
flutter:
diff --git a/packages/path_provider/path_provider_windows/example/pubspec.yaml b/packages/path_provider/path_provider_windows/example/pubspec.yaml
index 29e228d..8843e2d 100644
--- a/packages/path_provider/path_provider_windows/example/pubspec.yaml
+++ b/packages/path_provider/path_provider_windows/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: path_provider_example
description: Demonstrates how to use the path_provider plugin.
+publish_to: none
dependencies:
flutter:
diff --git a/packages/quick_actions/quick_actions/example/pubspec.yaml b/packages/quick_actions/quick_actions/example/pubspec.yaml
index b26f843..391b4c3 100644
--- a/packages/quick_actions/quick_actions/example/pubspec.yaml
+++ b/packages/quick_actions/quick_actions/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: quick_actions_example
description: Demonstrates how to use the quick_actions plugin.
+publish_to: none
dependencies:
flutter:
diff --git a/packages/sensors/example/lib/snake.dart b/packages/sensors/example/lib/snake.dart
index 4717768..afa12e3 100644
--- a/packages/sensors/example/lib/snake.dart
+++ b/packages/sensors/example/lib/snake.dart
@@ -99,10 +99,10 @@
final math.Point<int>? newDirection = currentAcceleration == null
? null
: currentAcceleration.x.abs() < 1.0 && currentAcceleration.y.abs() < 1.0
- ? null
- : (currentAcceleration.x.abs() < currentAcceleration.y.abs())
- ? math.Point<int>(0, currentAcceleration.y.sign.toInt())
- : math.Point<int>(-currentAcceleration.x.sign.toInt(), 0);
+ ? null
+ : (currentAcceleration.x.abs() < currentAcceleration.y.abs())
+ ? math.Point<int>(0, currentAcceleration.y.sign.toInt())
+ : math.Point<int>(-currentAcceleration.x.sign.toInt(), 0);
state.step(newDirection);
}
}
diff --git a/packages/sensors/example/pubspec.yaml b/packages/sensors/example/pubspec.yaml
index 7d8effb..884ebbb 100644
--- a/packages/sensors/example/pubspec.yaml
+++ b/packages/sensors/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: sensors_example
description: Demonstrates how to use the sensors plugin.
+publish_to: none
dependencies:
flutter:
diff --git a/packages/share/example/pubspec.yaml b/packages/share/example/pubspec.yaml
index 378e25b..31deb1f 100644
--- a/packages/share/example/pubspec.yaml
+++ b/packages/share/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: share_example
description: Demonstrates how to use the share plugin.
+publish_to: none
dependencies:
flutter:
diff --git a/packages/shared_preferences/shared_preferences/example/pubspec.yaml b/packages/shared_preferences/shared_preferences/example/pubspec.yaml
index 7a7b1ac..c3454a5 100644
--- a/packages/shared_preferences/shared_preferences/example/pubspec.yaml
+++ b/packages/shared_preferences/shared_preferences/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: shared_preferences_example
description: Demonstrates how to use the shared_preferences plugin.
+publish_to: none
dependencies:
flutter:
diff --git a/packages/shared_preferences/shared_preferences_linux/example/pubspec.yaml b/packages/shared_preferences/shared_preferences_linux/example/pubspec.yaml
index a3a3cbc..8b2c393 100644
--- a/packages/shared_preferences/shared_preferences_linux/example/pubspec.yaml
+++ b/packages/shared_preferences/shared_preferences_linux/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: shared_preferences_linux_example
description: Demonstrates how to use the shared_preferences_linux plugin.
+publish_to: none
dependencies:
flutter:
diff --git a/packages/shared_preferences/shared_preferences_macos/example/pubspec.yaml b/packages/shared_preferences/shared_preferences_macos/example/pubspec.yaml
index 8ad710c..c64fda7 100644
--- a/packages/shared_preferences/shared_preferences_macos/example/pubspec.yaml
+++ b/packages/shared_preferences/shared_preferences_macos/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: shared_preferences_example
description: Demonstrates how to use the shared_preferences plugin.
+publish_to: none
dependencies:
flutter:
diff --git a/packages/shared_preferences/shared_preferences_windows/example/pubspec.yaml b/packages/shared_preferences/shared_preferences_windows/example/pubspec.yaml
index e835987..db6401c 100644
--- a/packages/shared_preferences/shared_preferences_windows/example/pubspec.yaml
+++ b/packages/shared_preferences/shared_preferences_windows/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: shared_preferences_windows_example
description: Demonstrates how to use the shared_preferences_windows plugin.
+publish_to: none
environment:
sdk: ">=2.12.0-259.9.beta <3.0.0"
diff --git a/packages/url_launcher/url_launcher/example/pubspec.yaml b/packages/url_launcher/url_launcher/example/pubspec.yaml
index 4ab2353..e56f76f 100644
--- a/packages/url_launcher/url_launcher/example/pubspec.yaml
+++ b/packages/url_launcher/url_launcher/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: url_launcher_example
description: Demonstrates how to use the url_launcher plugin.
+publish_to: none
dependencies:
flutter:
diff --git a/packages/url_launcher/url_launcher_linux/example/pubspec.yaml b/packages/url_launcher/url_launcher_linux/example/pubspec.yaml
index e0c59fb..389f3fd 100644
--- a/packages/url_launcher/url_launcher_linux/example/pubspec.yaml
+++ b/packages/url_launcher/url_launcher_linux/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: url_launcher_example
description: Demonstrates how to use the url_launcher plugin.
+publish_to: none
dependencies:
flutter:
diff --git a/packages/url_launcher/url_launcher_macos/example/pubspec.yaml b/packages/url_launcher/url_launcher_macos/example/pubspec.yaml
index 595d1bc..2e221dc 100644
--- a/packages/url_launcher/url_launcher_macos/example/pubspec.yaml
+++ b/packages/url_launcher/url_launcher_macos/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: url_launcher_example
description: Demonstrates how to use the url_launcher plugin.
+publish_to: none
dependencies:
flutter:
diff --git a/packages/url_launcher/url_launcher_windows/example/pubspec.yaml b/packages/url_launcher/url_launcher_windows/example/pubspec.yaml
index 86ceeec..a0fecd5 100644
--- a/packages/url_launcher/url_launcher_windows/example/pubspec.yaml
+++ b/packages/url_launcher/url_launcher_windows/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: url_launcher_example
description: Demonstrates the Windows implementation of the url_launcher plugin.
+publish_to: none
dependencies:
flutter:
diff --git a/packages/video_player/video_player/example/pubspec.yaml b/packages/video_player/video_player/example/pubspec.yaml
index 354f3d1..6386a2b 100644
--- a/packages/video_player/video_player/example/pubspec.yaml
+++ b/packages/video_player/video_player/example/pubspec.yaml
@@ -1,6 +1,5 @@
name: video_player_example
description: Demonstrates how to use the video_player plugin.
-version: 0.0.1
publish_to: none
dependencies:
diff --git a/packages/webview_flutter/example/pubspec.yaml b/packages/webview_flutter/example/pubspec.yaml
index b706741..84e9163 100644
--- a/packages/webview_flutter/example/pubspec.yaml
+++ b/packages/webview_flutter/example/pubspec.yaml
@@ -1,5 +1,6 @@
name: webview_flutter_example
description: Demonstrates how to use the webview_flutter plugin.
+publish_to: none
environment:
sdk: ">=2.12.0-259.9.beta <3.0.0"
diff --git a/packages/webview_flutter/lib/webview_flutter.dart b/packages/webview_flutter/lib/webview_flutter.dart
index 92ff8e0..74d8af8 100644
--- a/packages/webview_flutter/lib/webview_flutter.dart
+++ b/packages/webview_flutter/lib/webview_flutter.dart
@@ -180,7 +180,7 @@
JavascriptChannel({
required this.name,
required this.onMessageReceived,
- }) : assert(name != null),
+ }) : assert(name != null),
assert(onMessageReceived != null),
assert(_validChannelNames.hasMatch(name));
diff --git a/packages/wifi_info_flutter/wifi_info_flutter/example/pubspec.yaml b/packages/wifi_info_flutter/wifi_info_flutter/example/pubspec.yaml
index 57edbe8..108bd39 100644
--- a/packages/wifi_info_flutter/wifi_info_flutter/example/pubspec.yaml
+++ b/packages/wifi_info_flutter/wifi_info_flutter/example/pubspec.yaml
@@ -1,6 +1,6 @@
name: wifi_info_flutter_example
description: Demonstrates how to use the wifi_info_flutter plugin.
-publish_to: 'none'
+publish_to: none
environment:
sdk: ">=2.12.0-259.9.beta <3.0.0"
diff --git a/script/tool/lib/src/common.dart b/script/tool/lib/src/common.dart
index fc1fdca..d8826c7 100644
--- a/script/tool/lib/src/common.dart
+++ b/script/tool/lib/src/common.dart
@@ -596,10 +596,18 @@
return changedFiles.toList();
}
- /// Get the package version specified in the pubspec file in `pubspecPath` and at the revision of `gitRef`.
- Future<Version> getPackageVersion(String pubspecPath, String gitRef) async {
- final io.ProcessResult gitShow =
- await baseGitDir.runCommand(<String>['show', '$gitRef:$pubspecPath']);
+ /// Get the package version specified in the pubspec file in `pubspecPath` and
+ /// at the revision of `gitRef` (defaulting to the base if not provided).
+ Future<Version> getPackageVersion(String pubspecPath, {String gitRef}) async {
+ final String ref = gitRef ?? (await _getBaseSha());
+
+ io.ProcessResult gitShow;
+ try {
+ gitShow =
+ await baseGitDir.runCommand(<String>['show', '$ref:$pubspecPath']);
+ } on io.ProcessException {
+ return null;
+ }
final String fileContent = gitShow.stdout as String;
final String versionString = loadYaml(fileContent)['version'] as String;
return versionString == null ? null : Version.parse(versionString);
diff --git a/script/tool/lib/src/version_check_command.dart b/script/tool/lib/src/version_check_command.dart
index 086fa54..14dc8fb 100644
--- a/script/tool/lib/src/version_check_command.dart
+++ b/script/tool/lib/src/version_check_command.dart
@@ -13,8 +13,6 @@
import 'common.dart';
-const String _kBaseSha = 'base-sha';
-
/// Categories of version change types.
enum NextVersionType {
/// A breaking change.
@@ -96,48 +94,59 @@
final List<String> changedPubspecs =
await gitVersionFinder.getChangedPubSpecs();
- final String baseSha = argResults[_kBaseSha] as String;
+ const String indentation = ' ';
for (final String pubspecPath in changedPubspecs) {
- try {
- final File pubspecFile = fileSystem.file(pubspecPath);
- if (!pubspecFile.existsSync()) {
- continue;
- }
- final Pubspec pubspec = Pubspec.parse(pubspecFile.readAsStringSync());
- if (pubspec.publishTo == 'none') {
- continue;
- }
+ print('Checking versions for $pubspecPath...');
+ final File pubspecFile = fileSystem.file(pubspecPath);
+ if (!pubspecFile.existsSync()) {
+ print('${indentation}Deleted; skipping.');
+ continue;
+ }
+ final Pubspec pubspec = Pubspec.parse(pubspecFile.readAsStringSync());
+ if (pubspec.publishTo == 'none') {
+ print('${indentation}Found "publish_to: none"; skipping.');
+ continue;
+ }
- final Version masterVersion =
- await gitVersionFinder.getPackageVersion(pubspecPath, baseSha);
- final Version headVersion =
- await gitVersionFinder.getPackageVersion(pubspecPath, 'HEAD');
- if (headVersion == null) {
- continue; // Example apps don't have versions
- }
+ final Version headVersion =
+ await gitVersionFinder.getPackageVersion(pubspecPath, gitRef: 'HEAD');
+ if (headVersion == null) {
+ printErrorAndExit(
+ errorMessage: '${indentation}No version found. A package that '
+ 'intentionally has no version should be marked '
+ '"publish_to: none".');
+ }
+ final Version masterVersion =
+ await gitVersionFinder.getPackageVersion(pubspecPath);
+ if (masterVersion == null) {
+ print('${indentation}Unable to find pubspec in master. '
+ 'Safe to ignore if the project is new.');
+ }
- final Map<Version, NextVersionType> allowedNextVersions =
- getAllowedNextVersions(masterVersion, headVersion);
+ if (masterVersion == headVersion) {
+ print('${indentation}No version change.');
+ continue;
+ }
- if (!allowedNextVersions.containsKey(headVersion)) {
- final String error = '$pubspecPath incorrectly updated version.\n'
- 'HEAD: $headVersion, master: $masterVersion.\n'
- 'Allowed versions: $allowedNextVersions';
- printErrorAndExit(errorMessage: error);
- }
+ final Map<Version, NextVersionType> allowedNextVersions =
+ getAllowedNextVersions(masterVersion, headVersion);
- final bool isPlatformInterface =
- pubspec.name.endsWith('_platform_interface');
- if (isPlatformInterface &&
- allowedNextVersions[headVersion] ==
- NextVersionType.BREAKING_MAJOR) {
- final String error = '$pubspecPath breaking change detected.\n'
- 'Breaking changes to platform interfaces are strongly discouraged.\n';
- printErrorAndExit(errorMessage: error);
- }
- } on io.ProcessException {
- print('Unable to find pubspec in master for $pubspecPath.'
- ' Safe to ignore if the project is new.');
+ if (!allowedNextVersions.containsKey(headVersion)) {
+ final String error = '${indentation}Incorrectly updated version.\n'
+ '${indentation}HEAD: $headVersion, master: $masterVersion.\n'
+ '${indentation}Allowed versions: $allowedNextVersions';
+ printErrorAndExit(errorMessage: error);
+ } else {
+ print('$indentation$headVersion -> $masterVersion');
+ }
+
+ final bool isPlatformInterface =
+ pubspec.name.endsWith('_platform_interface');
+ if (isPlatformInterface &&
+ allowedNextVersions[headVersion] == NextVersionType.BREAKING_MAJOR) {
+ final String error = '$pubspecPath breaking change detected.\n'
+ 'Breaking changes to platform interfaces are strongly discouraged.\n';
+ printErrorAndExit(errorMessage: error);
}
}
@@ -153,7 +162,7 @@
final String packageName = plugin.basename;
print('-----------------------------------------');
print(
- 'Checking the first version listed in CHANGELOG.MD matches the version in pubspec.yaml for $packageName.');
+ 'Checking the first version listed in CHANGELOG.md matches the version in pubspec.yaml for $packageName.');
final Pubspec pubspec = _tryParsePubspec(plugin);
if (pubspec == null) {
@@ -169,12 +178,29 @@
final Iterator<String> iterator = lines.iterator;
while (iterator.moveNext()) {
if (iterator.current.trim().isNotEmpty) {
- firstLineWithText = iterator.current;
+ firstLineWithText = iterator.current.trim();
break;
}
}
// Remove all leading mark down syntax from the version line.
- final String versionString = firstLineWithText.split(' ').last;
+ String versionString = firstLineWithText.split(' ').last;
+
+ // Skip validation for the special NEXT version that's used to accumulate
+ // changes that don't warrant publishing on their own.
+ bool hasNextSection = versionString == 'NEXT';
+ if (hasNextSection) {
+ print('Found NEXT; validating next version in the CHANGELOG.');
+ // Ensure that the version in pubspec hasn't changed without updating
+ // CHANGELOG. That means the next version entry in the CHANGELOG pass the
+ // normal validation.
+ while (iterator.moveNext()) {
+ if (iterator.current.trim().startsWith('## ')) {
+ versionString = iterator.current.trim().split(' ').last;
+ break;
+ }
+ }
+ }
+
final Version fromChangeLog = Version.parse(versionString);
if (fromChangeLog == null) {
final String error =
@@ -190,6 +216,18 @@
''';
printErrorAndExit(errorMessage: error);
}
+
+ // If NEXT wasn't the first section, it should not exist at all.
+ if (!hasNextSection) {
+ final RegExp nextRegex = RegExp(r'^#+\s*NEXT\s*$');
+ if (lines.any((String line) => nextRegex.hasMatch(line))) {
+ printErrorAndExit(errorMessage: '''
+When bumping the version for release, the NEXT section should be incorporated
+into the new version's release notes.
+ ''');
+ }
+ }
+
print('$packageName passed version check');
}
diff --git a/script/tool/pubspec.yaml b/script/tool/pubspec.yaml
index e471239..9260e8f 100644
--- a/script/tool/pubspec.yaml
+++ b/script/tool/pubspec.yaml
@@ -1,6 +1,6 @@
name: flutter_plugin_tools
description: Productivity utils for hosting multiple plugins within one repository.
-publish_to: 'none'
+publish_to: none
dependencies:
args: "^1.4.3"
diff --git a/script/tool/test/version_check_test.dart b/script/tool/test/version_check_test.dart
index 96a460d..ed953e0 100644
--- a/script/tool/test/version_check_test.dart
+++ b/script/tool/test/version_check_test.dart
@@ -62,6 +62,8 @@
final String response =
gitShowResponses[invocation.positionalArguments[0][1]];
when<String>(mockProcessResult.stdout as String).thenReturn(response);
+ } else if (invocation.positionalArguments[0][0] == 'merge-base') {
+ when<String>(mockProcessResult.stdout as String).thenReturn('abc123');
}
return Future<io.ProcessResult>.value(mockProcessResult);
});
@@ -98,11 +100,12 @@
);
expect(gitDirCommands.length, equals(3));
expect(
- gitDirCommands[0].join(' '), equals('diff --name-only master HEAD'));
- expect(gitDirCommands[1].join(' '),
- equals('show master:packages/plugin/pubspec.yaml'));
- expect(gitDirCommands[2].join(' '),
- equals('show HEAD:packages/plugin/pubspec.yaml'));
+ gitDirCommands,
+ containsAll(<Matcher>[
+ equals(<String>['diff', '--name-only', 'master', 'HEAD']),
+ equals(<String>['show', 'master:packages/plugin/pubspec.yaml']),
+ equals(<String>['show', 'HEAD:packages/plugin/pubspec.yaml']),
+ ]));
});
test('denies invalid version', () async {
@@ -117,15 +120,50 @@
await expectLater(
result,
- throwsA(const TypeMatcher<Error>()),
+ throwsA(const TypeMatcher<ToolExit>()),
);
expect(gitDirCommands.length, equals(3));
expect(
- gitDirCommands[0].join(' '), equals('diff --name-only master HEAD'));
- expect(gitDirCommands[1].join(' '),
- equals('show master:packages/plugin/pubspec.yaml'));
- expect(gitDirCommands[2].join(' '),
- equals('show HEAD:packages/plugin/pubspec.yaml'));
+ gitDirCommands,
+ containsAll(<Matcher>[
+ equals(<String>['diff', '--name-only', 'master', 'HEAD']),
+ equals(<String>['show', 'master:packages/plugin/pubspec.yaml']),
+ equals(<String>['show', 'HEAD:packages/plugin/pubspec.yaml']),
+ ]));
+ });
+
+ test('allows valid version without explicit base-sha', () async {
+ createFakePlugin('plugin', includeChangeLog: true, includeVersion: true);
+ gitDiffResponse = 'packages/plugin/pubspec.yaml';
+ gitShowResponses = <String, String>{
+ 'abc123:packages/plugin/pubspec.yaml': 'version: 1.0.0',
+ 'HEAD:packages/plugin/pubspec.yaml': 'version: 2.0.0',
+ };
+ final List<String> output =
+ await runCapturingPrint(runner, <String>['version-check']);
+
+ expect(
+ output,
+ containsAllInOrder(<String>[
+ 'No version check errors found!',
+ ]),
+ );
+ });
+
+ test('denies invalid version without explicit base-sha', () async {
+ createFakePlugin('plugin', includeChangeLog: true, includeVersion: true);
+ gitDiffResponse = 'packages/plugin/pubspec.yaml';
+ gitShowResponses = <String, String>{
+ 'abc123:packages/plugin/pubspec.yaml': 'version: 0.0.1',
+ 'HEAD:packages/plugin/pubspec.yaml': 'version: 0.2.0',
+ };
+ final Future<List<String>> result =
+ runCapturingPrint(runner, <String>['version-check']);
+
+ await expectLater(
+ result,
+ throwsA(const TypeMatcher<ToolExit>()),
+ );
});
test('gracefully handles missing pubspec.yaml', () async {
@@ -143,6 +181,8 @@
output,
orderedEquals(<String>[
'Determine diff with base sha: master',
+ 'Checking versions for packages/plugin/pubspec.yaml...',
+ ' Deleted; skipping.',
'No version check errors found!',
]),
);
@@ -171,13 +211,18 @@
);
expect(gitDirCommands.length, equals(3));
expect(
- gitDirCommands[0].join(' '), equals('diff --name-only master HEAD'));
- expect(
- gitDirCommands[1].join(' '),
- equals(
- 'show master:packages/plugin_platform_interface/pubspec.yaml'));
- expect(gitDirCommands[2].join(' '),
- equals('show HEAD:packages/plugin_platform_interface/pubspec.yaml'));
+ gitDirCommands,
+ containsAll(<Matcher>[
+ equals(<String>['diff', '--name-only', 'master', 'HEAD']),
+ equals(<String>[
+ 'show',
+ 'master:packages/plugin_platform_interface/pubspec.yaml'
+ ]),
+ equals(<String>[
+ 'show',
+ 'HEAD:packages/plugin_platform_interface/pubspec.yaml'
+ ]),
+ ]));
});
test('disallows breaking changes to platform interfaces', () async {
@@ -194,17 +239,22 @@
runner, <String>['version-check', '--base-sha=master']);
await expectLater(
output,
- throwsA(const TypeMatcher<Error>()),
+ throwsA(const TypeMatcher<ToolExit>()),
);
expect(gitDirCommands.length, equals(3));
expect(
- gitDirCommands[0].join(' '), equals('diff --name-only master HEAD'));
- expect(
- gitDirCommands[1].join(' '),
- equals(
- 'show master:packages/plugin_platform_interface/pubspec.yaml'));
- expect(gitDirCommands[2].join(' '),
- equals('show HEAD:packages/plugin_platform_interface/pubspec.yaml'));
+ gitDirCommands,
+ containsAll(<Matcher>[
+ equals(<String>['diff', '--name-only', 'master', 'HEAD']),
+ equals(<String>[
+ 'show',
+ 'master:packages/plugin_platform_interface/pubspec.yaml'
+ ]),
+ equals(<String>[
+ 'show',
+ 'HEAD:packages/plugin_platform_interface/pubspec.yaml'
+ ]),
+ ]));
});
test('Allow empty lines in front of the first version in CHANGELOG',
@@ -230,7 +280,7 @@
expect(
output,
containsAllInOrder(<String>[
- 'Checking the first version listed in CHANGELOG.MD matches the version in pubspec.yaml for plugin.',
+ 'Checking the first version listed in CHANGELOG.md matches the version in pubspec.yaml for plugin.',
'plugin passed version check',
'No version check errors found!'
]),
@@ -255,7 +305,7 @@
runner, <String>['version-check', '--base-sha=master']);
await expectLater(
output,
- throwsA(const TypeMatcher<Error>()),
+ throwsA(const TypeMatcher<ToolExit>()),
);
try {
final List<String> outputValue = await output;
@@ -291,7 +341,7 @@
expect(
output,
containsAllInOrder(<String>[
- 'Checking the first version listed in CHANGELOG.MD matches the version in pubspec.yaml for plugin.',
+ 'Checking the first version listed in CHANGELOG.md matches the version in pubspec.yaml for plugin.',
'plugin passed version check',
'No version check errors found!'
]),
@@ -322,7 +372,121 @@
runner, <String>['version-check', '--base-sha=master']);
await expectLater(
output,
- throwsA(const TypeMatcher<Error>()),
+ throwsA(const TypeMatcher<ToolExit>()),
+ );
+ try {
+ final List<String> outputValue = await output;
+ await expectLater(
+ outputValue,
+ containsAllInOrder(<String>[
+ '''
+ versions for plugin in CHANGELOG.md and pubspec.yaml do not match.
+ The version in pubspec.yaml is 1.0.0.
+ The first version listed in CHANGELOG.md is 1.0.1.
+ ''',
+ ]),
+ );
+ } on ToolExit catch (_) {}
+ });
+
+ test('Allow NEXT as a placeholder for gathering CHANGELOG entries',
+ () async {
+ createFakePlugin('plugin', includeChangeLog: true, includeVersion: true);
+
+ final Directory pluginDirectory =
+ mockPackagesDir.childDirectory('plugin');
+
+ createFakePubspec(pluginDirectory,
+ isFlutter: true, includeVersion: true, version: '1.0.0');
+ const String changelog = '''
+## NEXT
+
+* Some changes that won't be published until the next time there's a release.
+
+## 1.0.0
+
+* Some other changes.
+''';
+ createFakeCHANGELOG(pluginDirectory, changelog);
+ final List<String> output = await runCapturingPrint(
+ runner, <String>['version-check', '--base-sha=master']);
+ await expectLater(
+ output,
+ containsAllInOrder(<String>[
+ 'Found NEXT; validating next version in the CHANGELOG.',
+ 'plugin passed version check',
+ 'No version check errors found!',
+ ]),
+ );
+ });
+
+ test('Fail if NEXT is left in the CHANGELOG when adding a version bump',
+ () async {
+ createFakePlugin('plugin', includeChangeLog: true, includeVersion: true);
+
+ final Directory pluginDirectory =
+ mockPackagesDir.childDirectory('plugin');
+
+ createFakePubspec(pluginDirectory,
+ isFlutter: true, includeVersion: true, version: '1.0.1');
+ const String changelog = '''
+## 1.0.1
+
+* Some changes.
+
+## NEXT
+
+* Some changes that should have been folded in 1.0.1.
+
+## 1.0.0
+
+* Some other changes.
+''';
+ createFakeCHANGELOG(pluginDirectory, changelog);
+ final Future<List<String>> output = runCapturingPrint(
+ runner, <String>['version-check', '--base-sha=master']);
+ await expectLater(
+ output,
+ throwsA(const TypeMatcher<ToolExit>()),
+ );
+ try {
+ final List<String> outputValue = await output;
+ await expectLater(
+ outputValue,
+ containsAllInOrder(<String>[
+ '''
+ versions for plugin in CHANGELOG.md and pubspec.yaml do not match.
+ The version in pubspec.yaml is 1.0.0.
+ The first version listed in CHANGELOG.md is 1.0.1.
+ ''',
+ ]),
+ );
+ } on ToolExit catch (_) {}
+ });
+
+ test('Fail if the version changes without replacing NEXT', () async {
+ createFakePlugin('plugin', includeChangeLog: true, includeVersion: true);
+
+ final Directory pluginDirectory =
+ mockPackagesDir.childDirectory('plugin');
+
+ createFakePubspec(pluginDirectory,
+ isFlutter: true, includeVersion: true, version: '1.0.1');
+ const String changelog = '''
+## NEXT
+
+* Some changes that should be listed as part of 1.0.1.
+
+## 1.0.0
+
+* Some other changes.
+''';
+ createFakeCHANGELOG(pluginDirectory, changelog);
+ final Future<List<String>> output = runCapturingPrint(
+ runner, <String>['version-check', '--base-sha=master']);
+ await expectLater(
+ output,
+ throwsA(const TypeMatcher<ToolExit>()),
);
try {
final List<String> outputValue = await output;