chore(shorebird_cli): don't allow iOS releases to be created with Flutter < 3.19.5 (#1864)
This commit is contained in:
@@ -3,6 +3,7 @@ import 'dart:io' hide Platform;
|
||||
import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:platform/platform.dart';
|
||||
import 'package:pub_semver/pub_semver.dart';
|
||||
import 'package:scoped/scoped.dart';
|
||||
import 'package:shorebird_cli/src/archive_analysis/archive_analysis.dart';
|
||||
import 'package:shorebird_cli/src/code_push_client_wrapper.dart';
|
||||
@@ -20,7 +21,6 @@ import 'package:shorebird_cli/src/shorebird_build_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_env.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_flutter.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_cli/src/validators/validators.dart';
|
||||
import 'package:shorebird_cli/src/version.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
|
||||
@@ -59,7 +59,7 @@ class ReleaseIosCommand extends ShorebirdCommand
|
||||
)
|
||||
..addOption(
|
||||
'flutter-version',
|
||||
help: 'The Flutter version to use when building the app (e.g: 3.16.3).',
|
||||
help: 'The Flutter version to use when building the app (e.g: 3.19.5).',
|
||||
)
|
||||
..addFlag(
|
||||
'codesign',
|
||||
@@ -93,10 +93,7 @@ make smaller updates to your app.
|
||||
await shorebirdValidator.validatePreconditions(
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
validators: [
|
||||
...doctor.iosCommandValidators,
|
||||
ShorebirdFlutterVersionSupportsIOSValidator(),
|
||||
],
|
||||
validators: doctor.iosCommandValidators,
|
||||
supportedOperatingSystems: {Platform.macOS},
|
||||
);
|
||||
} on PreconditionFailedException catch (e) {
|
||||
@@ -154,6 +151,13 @@ make smaller updates to your app.
|
||||
|
||||
var flutterRevisionForRelease = shorebirdEnv.flutterRevision;
|
||||
if (flutterVersion != null) {
|
||||
if (Version.parse(flutterVersion) < minimumSupportedIosFlutterVersion) {
|
||||
logger.err(
|
||||
'''iOS releases are not supported with Flutter versions older than $minimumSupportedIosFlutterVersion.''',
|
||||
);
|
||||
return ExitCode.usage.code;
|
||||
}
|
||||
|
||||
final String? revision;
|
||||
try {
|
||||
revision = await shorebirdFlutter.getRevisionForVersion(
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:io/io.dart' show copyPath;
|
||||
import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:platform/platform.dart';
|
||||
import 'package:pub_semver/pub_semver.dart';
|
||||
import 'package:scoped/scoped.dart';
|
||||
import 'package:shorebird_cli/src/code_push_client_wrapper.dart';
|
||||
import 'package:shorebird_cli/src/command.dart';
|
||||
@@ -13,12 +14,12 @@ import 'package:shorebird_cli/src/doctor.dart';
|
||||
import 'package:shorebird_cli/src/executables/xcodebuild.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/platform.dart';
|
||||
import 'package:shorebird_cli/src/platform/ios.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_artifact_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_build_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_env.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_flutter.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_validator.dart';
|
||||
import 'package:shorebird_cli/src/validators/validators.dart';
|
||||
import 'package:shorebird_cli/src/version.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
|
||||
@@ -62,10 +63,7 @@ of the iOS app that is using this module.''',
|
||||
checkUserIsAuthenticated: true,
|
||||
checkShorebirdInitialized: true,
|
||||
supportedOperatingSystems: {Platform.macOS},
|
||||
validators: [
|
||||
...doctor.iosCommandValidators,
|
||||
ShorebirdFlutterVersionSupportsIOSValidator(),
|
||||
],
|
||||
validators: doctor.iosCommandValidators,
|
||||
);
|
||||
} on PreconditionFailedException catch (e) {
|
||||
return e.exitCode.code;
|
||||
@@ -99,6 +97,13 @@ of the iOS app that is using this module.''',
|
||||
|
||||
var flutterRevisionForRelease = shorebirdEnv.flutterRevision;
|
||||
if (flutterVersion != null) {
|
||||
if (Version.parse(flutterVersion) < minimumSupportedIosFlutterVersion) {
|
||||
logger.err(
|
||||
'''iOS releases are not supported with Flutter versions older than $minimumSupportedIosFlutterVersion.''',
|
||||
);
|
||||
return ExitCode.usage.code;
|
||||
}
|
||||
|
||||
final String? revision;
|
||||
try {
|
||||
revision = await shorebirdFlutter.getRevisionForVersion(
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'dart:io';
|
||||
|
||||
import 'package:args/args.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:pub_semver/pub_semver.dart';
|
||||
import 'package:scoped/scoped.dart';
|
||||
import 'package:shorebird_cli/src/archive_analysis/archive_analysis.dart';
|
||||
|
||||
@@ -48,6 +49,9 @@ class InvalidExportOptionsPlistException implements Exception {
|
||||
final String message;
|
||||
}
|
||||
|
||||
/// The minimum allowed Flutter version for creating iOS releases.
|
||||
final minimumSupportedIosFlutterVersion = Version(3, 19, 5);
|
||||
|
||||
/// A reference to a [Ios] instance.
|
||||
final iosRef = create(Ios.new);
|
||||
|
||||
|
||||
-67
@@ -1,67 +0,0 @@
|
||||
import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:pub_semver/pub_semver.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_flutter.dart';
|
||||
import 'package:shorebird_cli/src/validators/validators.dart';
|
||||
|
||||
class ShorebirdFlutterVersionSupportsIOSValidator extends Validator {
|
||||
ShorebirdFlutterVersionSupportsIOSValidator();
|
||||
|
||||
@override
|
||||
String get description => 'Shorebird Flutter version supports iOS';
|
||||
|
||||
@override
|
||||
Future<List<ValidationIssue>> validate() async {
|
||||
final issues = <ValidationIssue>[];
|
||||
|
||||
// TODO(eseidel): Share "parse version" logic with the
|
||||
// ShorebirdFlutterValidator.
|
||||
final flutterVersion = await shorebirdFlutter.getVersion();
|
||||
if (flutterVersion == null) {
|
||||
issues.add(
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.warning,
|
||||
message: 'Unable to determine Shorebird Flutter version',
|
||||
),
|
||||
);
|
||||
return issues;
|
||||
}
|
||||
|
||||
// Our new mixed-mode engine had crashes in our last release of 3.16.4
|
||||
// through several releases of 3.16.7. There are OK release of 3.16.7
|
||||
// but it's easier to just warn away from all of 3.16.7.
|
||||
// We did not release 3.16.8 so we're recommending 3.16.9.
|
||||
final firstBadFlutter = Version(3, 16, 4);
|
||||
final lastBadFlutter = Version(3, 16, 7);
|
||||
final recommendedFlutter = Version(3, 16, 9);
|
||||
final useFlutterVersionCommand = lightCyan.wrap(
|
||||
'shorebird flutter versions use $recommendedFlutter',
|
||||
);
|
||||
// This is a warning to encourage those patching older versions of Flutter
|
||||
// to upgrade.
|
||||
if (flutterVersion < firstBadFlutter) {
|
||||
issues.add(
|
||||
ValidationIssue(
|
||||
severity: ValidationIssueSeverity.warning,
|
||||
message: '''
|
||||
Shorebird iOS recommends Flutter $recommendedFlutter or later.
|
||||
Run $useFlutterVersionCommand to upgrade.
|
||||
''',
|
||||
),
|
||||
);
|
||||
}
|
||||
// This is an error to disallow known-bad versions of Flutter for iOS.
|
||||
if (flutterVersion >= firstBadFlutter && flutterVersion <= lastBadFlutter) {
|
||||
issues.add(
|
||||
ValidationIssue(
|
||||
severity: ValidationIssueSeverity.error,
|
||||
message: '''
|
||||
Shorebird iOS does not support Flutter $flutterVersion.
|
||||
Run $useFlutterVersionCommand to upgrade.
|
||||
''',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return issues;
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,6 @@ import 'package:shorebird_cli/src/shorebird_process.dart';
|
||||
|
||||
export 'android_internet_permission_validator.dart';
|
||||
export 'shorebird_flutter_validator.dart';
|
||||
export 'shorebird_flutter_version_supports_ios_validator.dart';
|
||||
export 'shorebird_version_validator.dart';
|
||||
export 'storage_access_validator.dart';
|
||||
|
||||
|
||||
@@ -583,7 +583,7 @@ flutter:
|
||||
});
|
||||
|
||||
group('when flutter-version is provided', () {
|
||||
const flutterVersion = '3.16.3';
|
||||
const flutterVersion = '3.19.5';
|
||||
setUp(() {
|
||||
when(() => argResults['flutter-version']).thenReturn(flutterVersion);
|
||||
});
|
||||
@@ -609,6 +609,22 @@ $exception''',
|
||||
});
|
||||
});
|
||||
|
||||
group('when flutter version is too old', () {
|
||||
setUp(() {
|
||||
when(() => argResults['flutter-version']).thenReturn('3.16.3');
|
||||
});
|
||||
|
||||
test('prints error log and exits with code 64 (usage)', () async {
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, equals(ExitCode.usage.code));
|
||||
verify(
|
||||
() => logger.err(
|
||||
'''iOS releases are not supported with Flutter versions older than 3.19.5.''',
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
});
|
||||
|
||||
group('when flutter version is not supported', () {
|
||||
setUp(() {
|
||||
when(
|
||||
|
||||
+17
-1
@@ -313,7 +313,7 @@ flutter:
|
||||
});
|
||||
|
||||
group('when flutter-version is provided', () {
|
||||
const flutterVersion = '3.16.3';
|
||||
const flutterVersion = '3.19.5';
|
||||
setUp(() {
|
||||
when(() => argResults['flutter-version']).thenReturn(flutterVersion);
|
||||
});
|
||||
@@ -339,6 +339,22 @@ $exception''',
|
||||
});
|
||||
});
|
||||
|
||||
group('when flutter version is too old', () {
|
||||
setUp(() {
|
||||
when(() => argResults['flutter-version']).thenReturn('3.16.3');
|
||||
});
|
||||
|
||||
test('prints error log and exits with code 64 (usage)', () async {
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, equals(ExitCode.usage.code));
|
||||
verify(
|
||||
() => logger.err(
|
||||
'''iOS releases are not supported with Flutter versions older than 3.19.5.''',
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
});
|
||||
|
||||
group('when flutter version is not supported', () {
|
||||
setUp(() {
|
||||
when(
|
||||
|
||||
-122
@@ -1,122 +0,0 @@
|
||||
import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
import 'package:pub_semver/pub_semver.dart';
|
||||
import 'package:scoped/scoped.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_flutter.dart';
|
||||
import 'package:shorebird_cli/src/validators/validators.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../mocks.dart';
|
||||
|
||||
void main() {
|
||||
group(ShorebirdFlutterVersionSupportsIOSValidator, () {
|
||||
late ShorebirdFlutter shorebirdFlutter;
|
||||
late ShorebirdFlutterVersionSupportsIOSValidator validator;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
return runScoped(
|
||||
() => body(),
|
||||
values: {
|
||||
shorebirdFlutterRef.overrideWith(() => shorebirdFlutter),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
setUp(() {
|
||||
shorebirdFlutter = MockShorebirdFlutter();
|
||||
validator = ShorebirdFlutterVersionSupportsIOSValidator();
|
||||
});
|
||||
|
||||
test('has a non-empty description', () {
|
||||
expect(validator.description, isNotEmpty);
|
||||
});
|
||||
|
||||
group('when flutter version lookup fails', () {
|
||||
setUp(() {
|
||||
when(() => shorebirdFlutter.getVersion()).thenAnswer((_) async => null);
|
||||
});
|
||||
|
||||
test('returns validation warning', () async {
|
||||
final results = await runWithOverrides(validator.validate);
|
||||
|
||||
expect(
|
||||
results,
|
||||
equals([
|
||||
const ValidationIssue(
|
||||
severity: ValidationIssueSeverity.warning,
|
||||
message: 'Unable to determine Shorebird Flutter version',
|
||||
),
|
||||
]),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('when flutter version is before the first bad version', () {
|
||||
setUp(() {
|
||||
when(
|
||||
() => shorebirdFlutter.getVersion(),
|
||||
).thenAnswer((_) async => Version(3, 16, 3));
|
||||
});
|
||||
|
||||
test('returns validation warning', () async {
|
||||
final results = await runWithOverrides(validator.validate);
|
||||
|
||||
expect(
|
||||
results,
|
||||
equals(
|
||||
[
|
||||
ValidationIssue(
|
||||
severity: ValidationIssueSeverity.warning,
|
||||
message: '''
|
||||
Shorebird iOS recommends Flutter 3.16.9 or later.
|
||||
Run ${lightCyan.wrap('shorebird flutter versions use 3.16.9')} to upgrade.
|
||||
''',
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
group('when flutter version is in known bad range', () {
|
||||
setUp(() {
|
||||
when(
|
||||
() => shorebirdFlutter.getVersion(),
|
||||
).thenAnswer((_) async => Version(3, 16, 7));
|
||||
});
|
||||
|
||||
test('returns validation warning', () async {
|
||||
final results = await runWithOverrides(validator.validate);
|
||||
|
||||
expect(
|
||||
results,
|
||||
equals(
|
||||
[
|
||||
ValidationIssue(
|
||||
severity: ValidationIssueSeverity.error,
|
||||
message: '''
|
||||
Shorebird iOS does not support Flutter 3.16.7.
|
||||
Run ${lightCyan.wrap('shorebird flutter versions use 3.16.9')} to upgrade.
|
||||
''',
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('when flutter version is above the last bad flutter version', () {
|
||||
setUp(() {
|
||||
when(
|
||||
() => shorebirdFlutter.getVersion(),
|
||||
).thenAnswer((_) async => Version(3, 16, 10));
|
||||
});
|
||||
|
||||
test('returns no validation issues', () async {
|
||||
final results = await runWithOverrides(validator.validate);
|
||||
|
||||
expect(results, isEmpty);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user