From 25de4759ac7358e1b17dc074b9925e10c18a947a Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 25 Jan 2023 14:19:48 -0500 Subject: [PATCH 1/4] Add support for SDK version validation --- script/tool/CHANGELOG.md | 5 + .../tool/lib/src/pubspec_check_command.dart | 76 +++++++- script/tool/pubspec.yaml | 2 +- .../tool/test/pubspec_check_command_test.dart | 173 +++++++++++++++++- 4 files changed, 248 insertions(+), 8 deletions(-) diff --git a/script/tool/CHANGELOG.md b/script/tool/CHANGELOG.md index 55b5aeb7222a..34def6ecf676 100644 --- a/script/tool/CHANGELOG.md +++ b/script/tool/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.13.4 + +* Adds the ability to validate minimum supported Dart/Flutter versions in + `pubspec-check`. + ## 0.13.3 * Renames `podspecs` to `podspec-check`. The old name will continue to work. diff --git a/script/tool/lib/src/pubspec_check_command.dart b/script/tool/lib/src/pubspec_check_command.dart index 5682ba057688..aefa316a41f6 100644 --- a/script/tool/lib/src/pubspec_check_command.dart +++ b/script/tool/lib/src/pubspec_check_command.dart @@ -5,6 +5,7 @@ import 'package:file/file.dart'; import 'package:git/git.dart'; import 'package:platform/platform.dart'; +import 'package:pub_semver/pub_semver.dart'; import 'package:yaml/yaml.dart'; import 'common/core.dart'; @@ -29,7 +30,23 @@ class PubspecCheckCommand extends PackageLoopingCommand { processRunner: processRunner, platform: platform, gitDir: gitDir, - ); + ) { + argParser.addOption( + _minMinDartVersionFlag, + help: + 'The minimum Dart version to allow as the minimum SDK constraint.\n\n' + 'This is only enforced for non-Flutter packages; Flutter packages ' + 'use --$_minMinFlutterVersionFlag', + ); + argParser.addOption( + _minMinFlutterVersionFlag, + help: + 'The minimum Flutter version to allow as the minimum SDK constraint.', + ); + } + + static const String _minMinDartVersionFlag = 'min-min-dart-version'; + static const String _minMinFlutterVersionFlag = 'min-min-flutter-version'; // Section order for plugins. Because the 'flutter' section is critical // information for plugins, and usually small, it goes near the top unlike in @@ -100,6 +117,24 @@ class PubspecCheckCommand extends PackageLoopingCommand { printError('$listIndentation${sectionOrder.join('\n$listIndentation')}'); } + final String minMinDartVersionString = getStringArg(_minMinDartVersionFlag); + final String minMinFlutterVersionString = + getStringArg(_minMinFlutterVersionFlag); + final String? minVersionError = _checkForMinimumVersionError( + pubspec, + package, + minMinDartVersion: minMinDartVersionString.isEmpty + ? null + : Version.parse(minMinDartVersionString), + minMinFlutterVersion: minMinFlutterVersionString.isEmpty + ? null + : Version.parse(minMinFlutterVersionString), + ); + if (minVersionError != null) { + printError('$indentation$minVersionError'); + passing = false; + } + if (isPlugin) { final String? implementsError = _checkForImplementsError(pubspec, package: package); @@ -320,4 +355,43 @@ class PubspecCheckCommand extends PackageLoopingCommand { final String suffix = packageName.substring(parentName.length); return !nonImplementationSuffixes.contains(suffix); } + + /// Validates that a Flutter package has a minimum SDK version constraint of + /// at least [minMinFlutterVersion] (if provided), or that a non-Flutter + /// package has a minimum SDK version constraint of [minMinDartVersion] + /// (if provided). + /// + /// Returns an error string if validation fails. + String? _checkForMinimumVersionError( + Pubspec pubspec, + RepositoryPackage package, { + Version? minMinDartVersion, + Version? minMinFlutterVersion, + }) { + final VersionConstraint? dartConstraint = pubspec.environment?['sdk']; + final VersionConstraint? flutterConstraint = + pubspec.environment?['flutter']; + + if (flutterConstraint != null) { + // Validate Flutter packages against the Flutter requirement. + if (minMinFlutterVersion != null) { + final Version? constraintMin = + flutterConstraint is VersionRange ? flutterConstraint.min : null; + if ((constraintMin ?? Version(0, 0, 0)) < minMinFlutterVersion) { + return 'Minimum allowed Flutter version $constraintMin is less than $minMinFlutterVersion'; + } + } + } else { + // Validate non-Flutter packages against the Dart requirement. + if (minMinDartVersion != null) { + final Version? constraintMin = + dartConstraint is VersionRange ? dartConstraint.min : null; + if ((constraintMin ?? Version(0, 0, 0)) < minMinDartVersion) { + return 'Minimum allowed Dart version $constraintMin is less than $minMinDartVersion'; + } + } + } + + return null; + } } diff --git a/script/tool/pubspec.yaml b/script/tool/pubspec.yaml index abf2a61f4cf0..a8df2a9cd23a 100644 --- a/script/tool/pubspec.yaml +++ b/script/tool/pubspec.yaml @@ -1,7 +1,7 @@ name: flutter_plugin_tools description: Productivity utils for flutter/plugins and flutter/packages repository: https://github.com/flutter/plugins/tree/main/script/tool -version: 0.13.3 +version: 0.13.4 dependencies: args: ^2.1.0 diff --git a/script/tool/test/pubspec_check_command_test.dart b/script/tool/test/pubspec_check_command_test.dart index 2c254ca94984..7a9c0cec7cbc 100644 --- a/script/tool/test/pubspec_check_command_test.dart +++ b/script/tool/test/pubspec_check_command_test.dart @@ -60,12 +60,16 @@ ${publishable ? '' : "publish_to: 'none'"} '''; } -String _environmentSection() { - return ''' -environment: - sdk: ">=2.12.0 <3.0.0" - flutter: ">=2.0.0" -'''; +String _environmentSection({ + String dartConstraint = '>=2.12.0 <3.0.0', + String? flutterConstraint = '>=2.0.0', +}) { + return [ + 'environment:', + ' sdk: "$dartConstraint"', + if (flutterConstraint != null) ' flutter: "$flutterConstraint"', + '', + ].join('\n'); } String _flutterSection({ @@ -931,6 +935,163 @@ ${_devDependenciesSection()} ]), ); }); + + test('fails when a Flutter package has a too-low minimum Flutter version', + () async { + final RepositoryPackage package = createFakePackage( + 'a_package', packagesDir, + isFlutter: true, examples: []); + + package.pubspecFile.writeAsStringSync(''' +${_headerSection('a_package')} +${_environmentSection(flutterConstraint: '>=2.10.0')} +${_dependenciesSection()} +'''); + + Error? commandError; + final List output = await runCapturingPrint(runner, [ + 'pubspec-check', + '--min-min-flutter-version', + '3.0.0' + ], errorHandler: (Error e) { + commandError = e; + }); + + expect(commandError, isA()); + expect( + output, + containsAllInOrder([ + contains('Minimum allowed Flutter version 2.10.0 is less than 3.0.0'), + ]), + ); + }); + + test( + 'passes when a Flutter package requires exactly the minimum Flutter version', + () async { + final RepositoryPackage package = createFakePackage( + 'a_package', packagesDir, + isFlutter: true, examples: []); + + package.pubspecFile.writeAsStringSync(''' +${_headerSection('a_package')} +${_environmentSection(flutterConstraint: '>=3.0.0')} +${_dependenciesSection()} +'''); + + final List output = await runCapturingPrint(runner, + ['pubspec-check', '--min-min-flutter-version', '3.0.0']); + + expect( + output, + containsAllInOrder([ + contains('Running for a_package...'), + contains('No issues found!'), + ]), + ); + }); + + test( + 'passes when a Flutter package requires a higher minimum Flutter version', + () async { + final RepositoryPackage package = createFakePackage( + 'a_package', packagesDir, + isFlutter: true, examples: []); + + package.pubspecFile.writeAsStringSync(''' +${_headerSection('a_package')} +${_environmentSection(flutterConstraint: '>=3.3.0')} +${_dependenciesSection()} +'''); + + final List output = await runCapturingPrint(runner, + ['pubspec-check', '--min-min-flutter-version', '3.0.0']); + + expect( + output, + containsAllInOrder([ + contains('Running for a_package...'), + contains('No issues found!'), + ]), + ); + }); + + test('fails when a non-Flutter package has a too-low minimum Dart version', + () async { + final RepositoryPackage package = + createFakePackage('a_package', packagesDir, examples: []); + + package.pubspecFile.writeAsStringSync(''' +${_headerSection('a_package')} +${_environmentSection(dartConstraint: '>=2.14.0 <3.0.0', flutterConstraint: null)} +${_dependenciesSection()} +'''); + + Error? commandError; + final List output = await runCapturingPrint( + runner, ['pubspec-check', '--min-min-dart-version', '2.17.0'], + errorHandler: (Error e) { + commandError = e; + }); + + expect(commandError, isA()); + expect( + output, + containsAllInOrder([ + contains('Minimum allowed Dart version 2.14.0 is less than 2.17.0'), + ]), + ); + }); + + test( + 'passes when a non-Flutter package requires exactly the minimum Dart version', + () async { + final RepositoryPackage package = createFakePackage( + 'a_package', packagesDir, + isFlutter: true, examples: []); + + package.pubspecFile.writeAsStringSync(''' +${_headerSection('a_package')} +${_environmentSection(dartConstraint: '>=2.17.0 <3.0.0', flutterConstraint: null)} +${_dependenciesSection()} +'''); + + final List output = await runCapturingPrint(runner, + ['pubspec-check', '--min-min-dart-version', '2.17.0']); + + expect( + output, + containsAllInOrder([ + contains('Running for a_package...'), + contains('No issues found!'), + ]), + ); + }); + + test( + 'passes when a non-Flutter package requires a higher minimum Dart version', + () async { + final RepositoryPackage package = createFakePackage( + 'a_package', packagesDir, + isFlutter: true, examples: []); + + package.pubspecFile.writeAsStringSync(''' +${_headerSection('a_package')} +${_environmentSection(dartConstraint: '>=2.18.0 <3.0.0', flutterConstraint: null)} +${_dependenciesSection()} +'''); + + final List output = await runCapturingPrint(runner, + ['pubspec-check', '--min-min-dart-version', '2.17.0']); + + expect( + output, + containsAllInOrder([ + contains('Running for a_package...'), + contains('No issues found!'), + ]), + ); + }); }); group('test pubspec_check_command on Windows', () { From 93bd02dd4595d8dec310c311328690c98990efb0 Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 25 Jan 2023 14:23:13 -0500 Subject: [PATCH 2/4] Add the check to CI --- .cirrus.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.cirrus.yml b/.cirrus.yml index 85f8a2a115dd..4a5d604a081f 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -101,7 +101,9 @@ task: always: format_script: ./script/tool_runner.sh format --fail-on-change license_script: $PLUGIN_TOOL_COMMAND license-check - pubspec_script: ./script/tool_runner.sh pubspec-check + # The major and minor versions here should match the lowest version + # analyzed in legacy_version_analyze. + pubspec_script: ./script/tool_runner.sh pubspec-check --min-min-flutter-version=3.0.0 --min-min-dart-version=2.17.0 readme_script: - ./script/tool_runner.sh readme-check # Re-run with --require-excerpts, skipping packages that still need @@ -171,6 +173,7 @@ task: - name: legacy_version_analyze depends_on: analyze matrix: + # Change the arguments to pubspec-check when changing these values. env: CHANNEL: "3.0.5" DART_VERSION: "2.17.6" From ce5da08072a6294891ebc1a49dcc95cf7a4ebe6f Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 25 Jan 2023 14:28:33 -0500 Subject: [PATCH 3/4] Fix violations --- packages/file_selector/file_selector/example/pubspec.yaml | 1 + packages/file_selector/file_selector_ios/example/pubspec.yaml | 3 ++- .../file_selector/file_selector_linux/example/pubspec.yaml | 1 + packages/flutter_plugin_android_lifecycle/example/pubspec.yaml | 1 + packages/path_provider/path_provider_foundation/pubspec.yaml | 2 +- packages/plugin_platform_interface/pubspec.yaml | 2 +- .../webview_flutter_android/example/pubspec.yaml | 1 + .../webview_flutter/webview_flutter_web/example/pubspec.yaml | 1 + .../webview_flutter_wkwebview/example/pubspec.yaml | 1 + 9 files changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/file_selector/file_selector/example/pubspec.yaml b/packages/file_selector/file_selector/example/pubspec.yaml index 011d95874ae4..ff9d6d0d2e17 100644 --- a/packages/file_selector/file_selector/example/pubspec.yaml +++ b/packages/file_selector/file_selector/example/pubspec.yaml @@ -6,6 +6,7 @@ version: 1.0.0+1 environment: sdk: ">=2.12.0 <3.0.0" + flutter: ">=3.0.0" dependencies: file_selector: diff --git a/packages/file_selector/file_selector_ios/example/pubspec.yaml b/packages/file_selector/file_selector_ios/example/pubspec.yaml index 5a2eaa6f7dcd..175ec6c6e7d0 100644 --- a/packages/file_selector/file_selector_ios/example/pubspec.yaml +++ b/packages/file_selector/file_selector_ios/example/pubspec.yaml @@ -5,6 +5,7 @@ version: 1.0.0 environment: sdk: ">=2.14.4 <3.0.0" + flutter: ">=3.0.0" dependencies: # The following adds the Cupertino Icons font to your application. @@ -28,4 +29,4 @@ dev_dependencies: sdk: flutter flutter: - uses-material-design: true \ No newline at end of file + uses-material-design: true diff --git a/packages/file_selector/file_selector_linux/example/pubspec.yaml b/packages/file_selector/file_selector_linux/example/pubspec.yaml index 912a082bd602..f90d1c88ef97 100644 --- a/packages/file_selector/file_selector_linux/example/pubspec.yaml +++ b/packages/file_selector/file_selector_linux/example/pubspec.yaml @@ -5,6 +5,7 @@ version: 1.0.0+1 environment: sdk: ">=2.12.0 <3.0.0" + flutter: ">=3.0.0" dependencies: file_selector_linux: diff --git a/packages/flutter_plugin_android_lifecycle/example/pubspec.yaml b/packages/flutter_plugin_android_lifecycle/example/pubspec.yaml index e732497eee95..4c97e6c44cd1 100644 --- a/packages/flutter_plugin_android_lifecycle/example/pubspec.yaml +++ b/packages/flutter_plugin_android_lifecycle/example/pubspec.yaml @@ -4,6 +4,7 @@ publish_to: none environment: sdk: ">=2.12.0 <3.0.0" + flutter: ">=3.0.0" dependencies: flutter: diff --git a/packages/path_provider/path_provider_foundation/pubspec.yaml b/packages/path_provider/path_provider_foundation/pubspec.yaml index 9ceb115ccfe1..30dd655acc00 100644 --- a/packages/path_provider/path_provider_foundation/pubspec.yaml +++ b/packages/path_provider/path_provider_foundation/pubspec.yaml @@ -6,7 +6,7 @@ version: 2.1.1 environment: sdk: ">=2.12.0 <3.0.0" - flutter: ">=2.10.0" + flutter: ">=3.0.0" flutter: plugin: diff --git a/packages/plugin_platform_interface/pubspec.yaml b/packages/plugin_platform_interface/pubspec.yaml index 6a4bc488693b..25189d942f84 100644 --- a/packages/plugin_platform_interface/pubspec.yaml +++ b/packages/plugin_platform_interface/pubspec.yaml @@ -18,7 +18,7 @@ issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+ version: 2.1.3 environment: - sdk: ">=2.12.0 <3.0.0" + sdk: ">=2.17.0 <3.0.0" dependencies: meta: ^1.3.0 diff --git a/packages/webview_flutter/webview_flutter_android/example/pubspec.yaml b/packages/webview_flutter/webview_flutter_android/example/pubspec.yaml index 0daacb07b13f..0fc0daf84118 100644 --- a/packages/webview_flutter/webview_flutter_android/example/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_android/example/pubspec.yaml @@ -4,6 +4,7 @@ publish_to: none environment: sdk: ">=2.14.0 <3.0.0" + flutter: ">=3.0.0" dependencies: flutter: diff --git a/packages/webview_flutter/webview_flutter_web/example/pubspec.yaml b/packages/webview_flutter/webview_flutter_web/example/pubspec.yaml index 782817eb7100..4685135acdf1 100644 --- a/packages/webview_flutter/webview_flutter_web/example/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_web/example/pubspec.yaml @@ -4,6 +4,7 @@ publish_to: none environment: sdk: ">=2.14.0 <3.0.0" + flutter: ">=3.0.0" dependencies: flutter: diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml b/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml index 7ccb302a843b..718eb282018b 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml @@ -4,6 +4,7 @@ publish_to: none environment: sdk: ">=2.12.0 <3.0.0" + flutter: ">=3.0.0" dependencies: flutter: From 1b5c101c668d640e5902413ef8a0158b1955183f Mon Sep 17 00:00:00 2001 From: Stuart Morgan Date: Wed, 25 Jan 2023 14:31:52 -0500 Subject: [PATCH 4/4] Update CHANGELOGs --- packages/path_provider/path_provider_foundation/CHANGELOG.md | 4 ++++ packages/plugin_platform_interface/CHANGELOG.md | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/packages/path_provider/path_provider_foundation/CHANGELOG.md b/packages/path_provider/path_provider_foundation/CHANGELOG.md index 17e45d37a2ba..7adb04f4c984 100644 --- a/packages/path_provider/path_provider_foundation/CHANGELOG.md +++ b/packages/path_provider/path_provider_foundation/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported Flutter version to 3.0. + ## 2.1.1 * Fixes a regression in the path retured by `getApplicationSupportDirectory` on iOS. diff --git a/packages/plugin_platform_interface/CHANGELOG.md b/packages/plugin_platform_interface/CHANGELOG.md index 0b5a6b63a52f..93e45c814668 100644 --- a/packages/plugin_platform_interface/CHANGELOG.md +++ b/packages/plugin_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## NEXT + +* Updates minimum supported Dart version. + ## 2.1.3 * Minor fixes for new analysis options.