[ci] Run analysis with older versions of Flutter (#5000)

This commit is contained in:
stuartmorgan
2022-03-09 11:35:23 -05:00
committed by GitHub
parent 199afd96f1
commit 159f6d87b7
8 changed files with 172 additions and 61 deletions

View File

@ -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.
@ -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')) {
@ -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']);
}

View File

@ -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';
@ -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 =
@ -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();
@ -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());
@ -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);
}

View File

@ -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