Skip to content

Commit

Permalink
[ci] Run analysis with older versions of Flutter (flutter#5000)
Browse files Browse the repository at this point in the history
  • Loading branch information
stuartmorgan committed Mar 9, 2022
1 parent eb6ad34 commit 6852d0a
Show file tree
Hide file tree
Showing 18 changed files with 213 additions and 70 deletions.
24 changes: 20 additions & 4 deletions .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ flutter_upgrade_template: &FLUTTER_UPGRADE_TEMPLATE
- git fetch origin
# Switch to the requested channel.
- git checkout $TARGET_TREEISH
# When using a branch rather than a hash, reset to the upstream branch
# rather than using pull, since the base image can sometimes be in a state
# where it has diverged from upstream (!).
- if [[ "$TARGET_TREEISH" == "$CHANNEL" ]]; then
# When using a branch rather than a hash or version tag, reset to the
# upstream branch rather than using pull, since the base image can sometimes
# be in a state where it has diverged from upstream (!).
- if [[ "$TARGET_TREEISH" == "$CHANNEL" ]] && [[ "$CHANNEL" != *"."* ]]; then
- git reset --hard @{u}
- fi
# Run doctor to allow auditing of what version of Flutter the run is using.
Expand Down Expand Up @@ -138,6 +138,22 @@ task:
# Restore the tree to a clean state, to avoid accidental issues if
# other script steps are added to this task.
- git checkout .
# Does a sanity check that plugins at least pass analysis on the N-1 and N-2
# versions of Flutter stable if the plugin claims to support that version.
# This is to minimize accidentally making changes that break old versions
# (which we don't commit to supporting, but don't want to actively break)
# without updating the constraints.
# Note: The versions below should be manually updated after a new stable
# version comes out.
- name: legacy-version-analyze
depends_on: analyze
env:
matrix:
CHANNEL: "2.5.3"
CHANNEL: "2.8.1"
analyze_script:
- ./script/tool_runner.sh analyze --skip-if-not-supporting-flutter-version="$CHANNEL" --custom-analysis=script/configs/custom_analysis.yaml
- echo "If this test fails, the minumum Flutter version should be updated"
### Web tasks ###
- name: web-build_all_plugins
env:
Expand Down
4 changes: 4 additions & 0 deletions packages/camera/camera_web/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## NEXT

* Updates minimum Flutter version for changes in 0.2.1+3.

## 0.2.1+3

* Internal code cleanup for stricter analysis options.
Expand Down
2 changes: 1 addition & 1 deletion packages/camera/camera_web/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ version: 0.2.1+3

environment:
sdk: ">=2.12.0 <3.0.0"
flutter: ">=2.0.0"
flutter: ">=2.8.0"

flutter:
plugin:
Expand Down
4 changes: 4 additions & 0 deletions packages/google_sign_in/google_sign_in_web/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## NEXT

* Updates minimum Flutter version to 2.8.

## 0.10.0+5

* Internal code cleanup for stricter analysis options.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ publish_to: none

environment:
sdk: ">=2.12.0 <3.0.0"
flutter: ">=2.2.0"
flutter: ">=2.8.0"

dependencies:
flutter:
Expand Down
2 changes: 1 addition & 1 deletion packages/google_sign_in/google_sign_in_web/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ version: 0.10.0+5

environment:
sdk: ">=2.12.0 <3.0.0"
flutter: ">=2.0.0"
flutter: ">=2.8.0"

flutter:
plugin:
Expand Down
4 changes: 4 additions & 0 deletions packages/quick_actions/quick_actions/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## NEXT

* Updates minimum Flutter version to 2.8.

## 0.6.0+10

* Moves Android and iOS implementations to federated packages.
Expand Down
4 changes: 4 additions & 0 deletions packages/video_player/video_player/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## NEXT

* Updates minimum Flutter version to 2.10.

## 2.3.0

* Adds `allowBackgroundPlayback` to `VideoPlayerOptions`.
Expand Down
2 changes: 1 addition & 1 deletion packages/video_player/video_player/example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ publish_to: none

environment:
sdk: ">=2.12.0 <3.0.0"
flutter: ">=1.12.13+hotfix.5"
flutter: ">=2.10.0"

dependencies:
flutter:
Expand Down
2 changes: 1 addition & 1 deletion packages/video_player/video_player/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ version: 2.3.0

environment:
sdk: ">=2.14.0 <3.0.0"
flutter: ">=2.8.0"
flutter: ">=2.10.0"

flutter:
plugin:
Expand Down
3 changes: 3 additions & 0 deletions script/tool/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
`flutter` behavior.
- Validates `default_package` entries in plugins.
- Removes `allow-warnings` from the `podspecs` command.
- Adds `skip-if-not-supporting-flutter-version` to allow running tests using a
version of Flutter that not all packages support. (E.g., to allow for running
some tests against old versions of Flutter to help avoid accidental breakage.)

## 0.7.3

Expand Down
49 changes: 13 additions & 36 deletions script/tool/lib/src/analyze_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,9 @@ import 'package:yaml/yaml.dart';

import 'common/core.dart';
import 'common/package_looping_command.dart';
import 'common/plugin_command.dart';
import 'common/process_runner.dart';
import 'common/repository_package.dart';

const int _exitPackagesGetFailed = 3;

/// A command to run Dart analysis on packages.
class AnalyzeCommand extends PackageLoopingCommand {
/// Creates a analysis command instance.
Expand Down Expand Up @@ -84,41 +81,8 @@ class AnalyzeCommand extends PackageLoopingCommand {
return false;
}

/// Ensures that the dependent packages have been fetched for all packages
/// (including their sub-packages) that will be analyzed.
Future<bool> _runPackagesGetOnTargetPackages() async {
final List<Directory> packageDirectories =
await getTargetPackagesAndSubpackages()
.map((PackageEnumerationEntry entry) => entry.package.directory)
.toList();
final Set<String> packagePaths =
packageDirectories.map((Directory dir) => dir.path).toSet();
packageDirectories.removeWhere((Directory directory) {
// Remove the 'example' subdirectories; 'flutter packages get'
// automatically runs 'pub get' there as part of handling the parent
// directory.
return directory.basename == 'example' &&
packagePaths.contains(directory.parent.path);
});
for (final Directory package in packageDirectories) {
final int exitCode = await processRunner.runAndStream(
flutterCommand, <String>['packages', 'get'],
workingDir: package);
if (exitCode != 0) {
return false;
}
}
return true;
}

@override
Future<void> initializeRun() async {
print('Fetching dependencies...');
if (!await _runPackagesGetOnTargetPackages()) {
printError('Unable to get dependencies.');
throw ToolExit(_exitPackagesGetFailed);
}

_allowedCustomAnalysisDirectories =
getStringListArg(_customAnalysisFlag).expand<String>((String item) {
if (item.endsWith('.yaml')) {
Expand All @@ -138,6 +102,19 @@ class AnalyzeCommand extends PackageLoopingCommand {

@override
Future<PackageResult> runForPackage(RepositoryPackage package) async {
// For non-example packages, fetch dependencies. 'flutter packages get'
// automatically runs 'pub get' in examples as part of handling the parent
// directory, which is guaranteed to come first in the package enumeration.
if (package.directory.basename != 'example' ||
!RepositoryPackage(package.directory.parent).pubspecFile.existsSync()) {
final int exitCode = await processRunner.runAndStream(
flutterCommand, <String>['packages', 'get'],
workingDir: package.directory);
if (exitCode != 0) {
return PackageResult.fail(<String>['Unable to get dependencies']);
}
}

if (_hasUnexpecetdAnalysisOptions(package)) {
return PackageResult.fail(<String>['Unexpected local analysis options']);
}
Expand Down
41 changes: 39 additions & 2 deletions script/tool/lib/src/common/package_looping_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import 'package:file/file.dart';
import 'package:git/git.dart';
import 'package:path/path.dart' as p;
import 'package:platform/platform.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:pubspec_parse/pubspec_parse.dart';

import 'core.dart';
import 'plugin_command.dart';
Expand Down Expand Up @@ -75,7 +77,16 @@ abstract class PackageLoopingCommand extends PluginCommand {
Platform platform = const LocalPlatform(),
GitDir? gitDir,
}) : super(packagesDir,
processRunner: processRunner, platform: platform, gitDir: gitDir);
processRunner: processRunner, platform: platform, gitDir: gitDir) {
argParser.addOption(
_skipByFlutterVersionArg,
help: 'Skip any packages that require a Flutter version newer than '
'the provided version.',
);
}

static const String _skipByFlutterVersionArg =
'skip-if-not-supporting-flutter-version';

/// Packages that had at least one [logWarning] call.
final Set<PackageEnumerationEntry> _packagesWithWarnings =
Expand Down Expand Up @@ -219,6 +230,11 @@ abstract class PackageLoopingCommand extends PluginCommand {
_otherWarningCount = 0;
_currentPackageEntry = null;

final String minFlutterVersionArg = getStringArg(_skipByFlutterVersionArg);
final Version? minFlutterVersion = minFlutterVersionArg.isEmpty
? null
: Version.parse(minFlutterVersionArg);

final DateTime runStart = DateTime.now();

await initializeRun();
Expand All @@ -242,7 +258,8 @@ abstract class PackageLoopingCommand extends PluginCommand {

PackageResult result;
try {
result = await runForPackage(entry.package);
result = await _runForPackageIfSupported(entry.package,
minFlutterVersion: minFlutterVersion);
} catch (e, stack) {
printError(e.toString());
printError(stack.toString());
Expand Down Expand Up @@ -285,6 +302,26 @@ abstract class PackageLoopingCommand extends PluginCommand {
return true;
}

/// Returns the result of running [runForPackage] if the package is supported
/// by any run constraints, or a skip result if it is not.
Future<PackageResult> _runForPackageIfSupported(
RepositoryPackage package, {
Version? minFlutterVersion,
}) async {
if (minFlutterVersion != null) {
final Pubspec pubspec = package.parsePubspec();
final VersionConstraint? flutterConstraint =
pubspec.environment?['flutter'];
if (flutterConstraint != null &&
!flutterConstraint.allows(minFlutterVersion)) {
return PackageResult.skip(
'Does not support Flutter ${minFlutterVersion.toString()}');
}
}

return await runForPackage(package);
}

void _printSuccess(String message) {
captureOutput ? print(message) : printSuccess(message);
}
Expand Down
3 changes: 3 additions & 0 deletions script/tool/lib/src/common/plugin_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -409,6 +409,9 @@ abstract class PluginCommand extends Command<void> {
///
/// By default, packages excluded via --exclude will not be in the stream, but
/// they can be included by passing false for [filterExcluded].
///
/// Subpackages are guaranteed to be after the containing package in the
/// stream.
Stream<PackageEnumerationEntry> getTargetPackagesAndSubpackages(
{bool filterExcluded = true}) async* {
await for (final PackageEnumerationEntry plugin
Expand Down
8 changes: 4 additions & 4 deletions script/tool/test/analyze_command_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ void main() {
orderedEquals(<ProcessCall>[
ProcessCall(
'flutter', const <String>['packages', 'get'], plugin1Dir.path),
ProcessCall(
'flutter', const <String>['packages', 'get'], plugin2Dir.path),
ProcessCall('dart', const <String>['analyze', '--fatal-infos'],
plugin1Dir.path),
ProcessCall(
'flutter', const <String>['packages', 'get'], plugin2Dir.path),
ProcessCall('dart', const <String>['analyze', '--fatal-infos'],
plugin2Dir.path),
]));
Expand Down Expand Up @@ -82,10 +82,10 @@ void main() {
orderedEquals(<ProcessCall>[
ProcessCall(
'flutter', const <String>['packages', 'get'], plugin1Dir.path),
ProcessCall(
'flutter', const <String>['packages', 'get'], plugin2Dir.path),
ProcessCall('dart', const <String>['analyze', '--fatal-infos'],
plugin1Dir.path),
ProcessCall(
'flutter', const <String>['packages', 'get'], plugin2Dir.path),
ProcessCall('dart', const <String>['analyze', '--fatal-infos'],
plugin2Dir.path),
]));
Expand Down
28 changes: 28 additions & 0 deletions script/tool/test/common/package_looping_command_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,34 @@ void main() {
expect(command.checkedPackages,
isNot(contains(excluded.childDirectory('example2').path)));
});

test('skips unsupported versions when requested', () async {
final Directory excluded = createFakePlugin('a_plugin', packagesDir,
flutterConstraint: '>=2.10.0');
final Directory included = createFakePackage('a_package', packagesDir);

final TestPackageLoopingCommand command =
createTestCommand(includeSubpackages: true, hasLongOutput: false);
final List<String> output = await runCommand(command, arguments: <String>[
'--skip-if-not-supporting-flutter-version=2.5.0'
]);

expect(
command.checkedPackages,
unorderedEquals(<String>[
included.path,
included.childDirectory('example').path,
]));
expect(command.checkedPackages, isNot(contains(excluded.path)));

expect(
output,
containsAllInOrder(<String>[
'${_startHeadingColor}Running for a_package...$_endColor',
'${_startHeadingColor}Running for a_plugin...$_endColor',
'$_startSkipColor SKIPPING: Does not support Flutter 2.5.0$_endColor',
]));
});
});

group('output', () {
Expand Down
Loading

0 comments on commit 6852d0a

Please sign in to comment.