chore(shorebird_cli): Update ShorebirdCommand to accept a list of validators instead of a single ShorebirdFlutterValidator (#264)
This commit is contained in:
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user