chore(shorebird_cli): Update ShorebirdCommand to accept a list of validators instead of a single ShorebirdFlutterValidator (#264)

This commit is contained in:
Bryan Oltman
2023-04-07 13:03:07 -04:00
committed by GitHub
parent c7eff381dc
commit a2c4b0bd73
15 changed files with 87 additions and 48 deletions
+6 -4
View File
@@ -33,14 +33,14 @@ abstract class ShorebirdCommand extends Command<int> {
CodePushClientBuilder? buildCodePushClient,
RunProcess? runProcess,
StartProcess? startProcess,
ShorebirdFlutterValidator? flutterValidator,
List<Validator>? validators,
}) : auth = auth ?? Auth(),
cache = cache ?? Cache(),
buildCodePushClient = buildCodePushClient ?? CodePushClient.new,
runProcess = runProcess ?? ShorebirdProcess.run,
startProcess = startProcess ?? ShorebirdProcess.start {
this.flutterValidator = flutterValidator ??
ShorebirdFlutterValidator(runProcess: this.runProcess);
this.validators =
validators ?? [ShorebirdFlutterValidator(runProcess: this.runProcess)];
}
final Auth auth;
@@ -49,7 +49,9 @@ abstract class ShorebirdCommand extends Command<int> {
final Logger logger;
final RunProcess runProcess;
final StartProcess startProcess;
late final ShorebirdFlutterValidator flutterValidator;
/// Checks that the Shorebird install and project are in a good state.
late List<Validator> validators;
/// [ArgResults] used for testing purposes only.
@visibleForTesting
@@ -19,7 +19,7 @@ class BuildCommand extends ShorebirdCommand
super.auth,
super.buildCodePushClient,
super.runProcess,
super.flutterValidator,
super.validators,
});
@override
@@ -37,7 +37,7 @@ class BuildCommand extends ShorebirdCommand
return ExitCode.noUser.code;
}
await logFlutterValidationIssues();
await logValidationIssues();
final buildProgress = logger.progress('Building release ');
try {
@@ -1,3 +1,4 @@
import 'package:collection/collection.dart';
import 'package:mason_logger/mason_logger.dart';
import 'package:shorebird_cli/src/command.dart';
import 'package:shorebird_cli/src/shorebird_version_mixin.dart';
@@ -14,20 +15,19 @@ class DoctorCommand extends ShorebirdCommand with ShorebirdVersionMixin {
/// {@macro doctor_command}
DoctorCommand({
required super.logger,
List<Validator>? validators,
super.validators,
super.runProcess,
}) {
this.validators = validators ??
<Validator>[
ShorebirdVersionValidator(
isShorebirdVersionCurrent: isShorebirdVersionCurrent,
),
ShorebirdFlutterValidator(runProcess: runProcess),
AndroidInternetPermissionValidator(),
];
validators = _allValidators(baseValidators: validators);
}
late final List<Validator> validators;
late final List<Validator> _doctorValidators = [
ShorebirdVersionValidator(
isShorebirdVersionCurrent: isShorebirdVersionCurrent,
),
ShorebirdFlutterValidator(runProcess: runProcess),
AndroidInternetPermissionValidator(),
];
@override
String get name => 'doctor';
@@ -68,4 +68,20 @@ Shorebird v$packageVersion
return ExitCode.success.code;
}
/// Creates a list that is the union of [baseValidators] and
/// [_doctorValidators].
List<Validator> _allValidators({
required List<Validator> baseValidators,
}) {
final missingValidators = _doctorValidators
.where(
(doctorValidator) => baseValidators.none(
(baseValidator) => baseValidator.id == doctorValidator.id,
),
)
.toList();
return baseValidators + missingValidators;
}
}
@@ -29,7 +29,7 @@ class PatchCommand extends ShorebirdCommand
super.buildCodePushClient,
super.cache,
super.runProcess,
super.flutterValidator,
super.validators,
HashFunction? hashFn,
http.Client? httpClient,
}) : _hashFn = hashFn ?? ((m) => sha256.convert(m).toString()),
@@ -108,7 +108,7 @@ class PatchCommand extends ShorebirdCommand
return ExitCode.usage.code;
}
await logFlutterValidationIssues();
await logValidationIssues();
await cache.updateAll();
@@ -27,7 +27,7 @@ class ReleaseCommand extends ShorebirdCommand
super.auth,
super.buildCodePushClient,
super.runProcess,
super.flutterValidator,
super.validators,
HashFunction? hashFn,
}) : _hashFn = hashFn ?? ((m) => sha256.convert(m).toString()) {
argParser
@@ -70,7 +70,7 @@ make smaller updates to your app.
return ExitCode.noUser.code;
}
await logFlutterValidationIssues();
await logValidationIssues();
final buildProgress = logger.progress('Building release');
try {
@@ -17,7 +17,7 @@ class RunCommand extends ShorebirdCommand
super.auth,
super.buildCodePushClient,
super.startProcess,
super.flutterValidator,
super.validators,
});
@override
@@ -35,7 +35,7 @@ class RunCommand extends ShorebirdCommand
return ExitCode.noUser.code;
}
await logFlutterValidationIssues();
await logValidationIssues();
logger.info('Running app...');
final process = await startProcess(
@@ -1,13 +1,17 @@
import 'package:collection/collection.dart';
import 'package:shorebird_cli/src/command.dart';
import 'package:shorebird_cli/src/validators/shorebird_flutter_validator.dart';
mixin FlutterValidationMixin on ShorebirdCommand {
/// Runs [ShorebirdFlutterValidator.validate] and writes validation issues to
/// stdout.
Future<void> logFlutterValidationIssues() async {
final flutterValidationIssues = await flutterValidator.validate();
if (flutterValidationIssues.isNotEmpty) {
for (final issue in flutterValidationIssues) {
Future<void> logValidationIssues() async {
final validationIssues = (await Future.wait(
validators.map((v) => v.validate()),
))
.flattened;
if (validationIssues.isNotEmpty) {
for (final issue in validationIssues) {
logger.info(issue.displayMessage);
}
}
@@ -57,7 +57,7 @@ class ShorebirdFlutterValidator extends Validator {
final message = """
Shorebird Flutter and the Flutter on your path are different versions.
\tShorebird Flutter: $shorebirdFlutterVersion
\tSystem Flutter: $pathFlutterVersion'''
\tSystem Flutter: $pathFlutterVersion
This can cause unexpected behavior if the version gap is wide. If you're seeing this unexpectedly, please let us know on Shorebird discord!""";
issues.add(
@@ -27,9 +27,7 @@ class ShorebirdVersionValidator extends Validator {
const ValidationIssue(
severity: ValidationIssueSeverity.warning,
message: '''
A new version of shorebird is available!
Run `shorebird upgrade` to upgrade.
''',
A new version of shorebird is available! Run `shorebird upgrade` to upgrade.''',
)
];
}
@@ -65,6 +65,9 @@ class ValidationIssue {
/// Checks for a specific issue with either the Shorebird installation or the
/// current Shorebird project.
abstract class Validator {
/// A unique identifer for this class.
String get id => '$runtimeType';
/// A one-sentence explanation of what this validator is checking.
String get description;
@@ -68,7 +68,7 @@ void main() {
}) async {
return processResult;
},
flutterValidator: flutterValidator,
validators: [flutterValidator],
)..testArgResults = argResults;
testApplicationConfigHome = (_) => applicationConfigHome.path;
@@ -10,6 +10,9 @@ class _MockShorebirdVersionValidator extends Mock
class _MockAndroidInternetPermissionValidator extends Mock
implements AndroidInternetPermissionValidator {}
class _MockShorebirdFlutterValidator extends Mock
implements ShorebirdFlutterValidator {}
class _MockLogger extends Mock implements Logger {}
class _MockProgress extends Mock implements Progress {}
@@ -21,36 +24,49 @@ void main() {
late DoctorCommand command;
late AndroidInternetPermissionValidator androidInternetPermissionValidator;
late ShorebirdVersionValidator shorebirdVersionValidator;
late ShorebirdFlutterValidator shorebirdFlutterValidator;
setUp(() {
logger = _MockLogger();
progress = _MockProgress();
when(() => logger.progress(any())).thenReturn(progress);
when(() => logger.info(any())).thenReturn(null);
androidInternetPermissionValidator =
_MockAndroidInternetPermissionValidator();
shorebirdVersionValidator = _MockShorebirdVersionValidator();
shorebirdFlutterValidator = _MockShorebirdFlutterValidator();
when(() => androidInternetPermissionValidator.id)
.thenReturn('$AndroidInternetPermissionValidator');
when(() => androidInternetPermissionValidator.description)
.thenReturn('Android');
when(() => androidInternetPermissionValidator.validate())
.thenAnswer((_) async => []);
when(() => shorebirdVersionValidator.id)
.thenReturn('$ShorebirdVersionValidator');
when(() => shorebirdVersionValidator.description)
.thenReturn('Shorebird Version');
when(() => shorebirdVersionValidator.validate())
.thenAnswer((_) async => []);
when(() => shorebirdFlutterValidator.id)
.thenReturn('$ShorebirdFlutterValidator');
when(() => shorebirdFlutterValidator.description)
.thenReturn('Shorebird Flutter');
when(() => shorebirdFlutterValidator.validate())
.thenAnswer((_) async => []);
command = DoctorCommand(
logger: logger,
validators: [
androidInternetPermissionValidator,
shorebirdVersionValidator,
shorebirdFlutterValidator,
],
);
when(() => logger.progress(any())).thenReturn(progress);
when(() => logger.info(any())).thenReturn(null);
when(() => androidInternetPermissionValidator.description)
.thenReturn('Android');
when(() => androidInternetPermissionValidator.validate())
.thenAnswer((_) async => []);
when(() => shorebirdVersionValidator.description)
.thenReturn('Shorebird Version');
when(() => shorebirdVersionValidator.validate())
.thenAnswer((_) async => []);
});
test('prints "no issues" when everything is OK', () async {
@@ -144,7 +144,7 @@ flutter:
},
logger: logger,
httpClient: httpClient,
flutterValidator: flutterValidator,
validators: [flutterValidator],
)..testArgResults = argResults;
testApplicationConfigHome = (_) => applicationConfigHome.path;
@@ -135,7 +135,7 @@ flutter:
return processResult;
},
logger: logger,
flutterValidator: flutterValidator,
validators: [flutterValidator],
)..testArgResults = argResults;
testApplicationConfigHome = (_) => applicationConfigHome.path;
@@ -63,7 +63,7 @@ void main() {
startProcess: (executable, arguments, {bool runInShell = false}) async {
return process;
},
flutterValidator: flutterValidator,
validators: [flutterValidator],
)..testArgResults = argResults;
testApplicationConfigHome = (_) => applicationConfigHome.path;