From 1085170d601bf9723e9a49f73c0effef7089cc8f Mon Sep 17 00:00:00 2001 From: Bryan Oltman Date: Wed, 28 Aug 2024 10:51:41 -0400 Subject: [PATCH] fix: delete shorebird build commands (#2453) --- .../lib/src/commands/build/build.dart | 5 - .../src/commands/build/build_aar_command.dart | 87 ------ .../src/commands/build/build_apk_command.dart | 75 ------ .../build/build_app_bundle_command.dart | 74 ----- .../lib/src/commands/build/build_command.dart | 25 -- .../src/commands/build/build_ipa_command.dart | 99 ------- .../lib/src/commands/commands.dart | 1 - .../lib/src/shorebird_cli_command_runner.dart | 1 - .../build/build_aar_command_test.dart | 190 ------------- .../build/build_apk_command_test.dart | 191 ------------- .../build/build_app_bundle_command_test.dart | 237 ---------------- .../commands/build/build_command_test.dart | 16 -- .../build/build_ipa_command_test.dart | 253 ------------------ 13 files changed, 1254 deletions(-) delete mode 100644 packages/shorebird_cli/lib/src/commands/build/build.dart delete mode 100644 packages/shorebird_cli/lib/src/commands/build/build_aar_command.dart delete mode 100644 packages/shorebird_cli/lib/src/commands/build/build_apk_command.dart delete mode 100644 packages/shorebird_cli/lib/src/commands/build/build_app_bundle_command.dart delete mode 100644 packages/shorebird_cli/lib/src/commands/build/build_command.dart delete mode 100644 packages/shorebird_cli/lib/src/commands/build/build_ipa_command.dart delete mode 100644 packages/shorebird_cli/test/src/commands/build/build_aar_command_test.dart delete mode 100644 packages/shorebird_cli/test/src/commands/build/build_apk_command_test.dart delete mode 100644 packages/shorebird_cli/test/src/commands/build/build_app_bundle_command_test.dart delete mode 100644 packages/shorebird_cli/test/src/commands/build/build_command_test.dart delete mode 100644 packages/shorebird_cli/test/src/commands/build/build_ipa_command_test.dart diff --git a/packages/shorebird_cli/lib/src/commands/build/build.dart b/packages/shorebird_cli/lib/src/commands/build/build.dart deleted file mode 100644 index db5a810f..00000000 --- a/packages/shorebird_cli/lib/src/commands/build/build.dart +++ /dev/null @@ -1,5 +0,0 @@ -export 'build_aar_command.dart'; -export 'build_apk_command.dart'; -export 'build_app_bundle_command.dart'; -export 'build_command.dart'; -export 'build_ipa_command.dart'; diff --git a/packages/shorebird_cli/lib/src/commands/build/build_aar_command.dart b/packages/shorebird_cli/lib/src/commands/build/build_aar_command.dart deleted file mode 100644 index 0af6d2db..00000000 --- a/packages/shorebird_cli/lib/src/commands/build/build_aar_command.dart +++ /dev/null @@ -1,87 +0,0 @@ -// ignore_for_file: public_member_api_docs - -import 'dart:async'; - -import 'package:mason_logger/mason_logger.dart'; -import 'package:path/path.dart' as p; -import 'package:shorebird_cli/src/artifact_builder.dart'; -import 'package:shorebird_cli/src/extensions/arg_results.dart'; -import 'package:shorebird_cli/src/logger.dart'; -import 'package:shorebird_cli/src/shorebird_command.dart'; -import 'package:shorebird_cli/src/shorebird_env.dart'; -import 'package:shorebird_cli/src/shorebird_validator.dart'; - -/// {@template build_aar_command} -/// -/// `shorebird build aar` -/// Build an Android aar file from your app. -/// {@endtemplate} -class BuildAarCommand extends ShorebirdCommand { - BuildAarCommand() { - // We would have a "target" option here, similar to what [BuildApkCommand] - // and [BuildAabCommand] have, but target cannot currently be configured in - // `flutter build aar` and is always assumed to be lib/main.dart. - argParser - // `flutter build aar` defaults to a build number of 1.0, so we do the - // same. - .addOption( - 'build-number', - help: 'The build number of the aar', - defaultsTo: '1.0', - ); - } - - @override - String get name => 'aar'; - - @override - String get description => 'Build an Android AAR file from your module.'; - - @override - Future run() async { - try { - await shorebirdValidator.validatePreconditions( - checkUserIsAuthenticated: true, - checkShorebirdInitialized: true, - ); - } on PreconditionFailedException catch (e) { - return e.exitCode.code; - } - - if (shorebirdEnv.androidPackageName == null) { - logger.err('Could not find androidPackage in pubspec.yaml.'); - return ExitCode.config.code; - } - - final buildNumber = results['build-number'] as String; - final buildProgress = logger.progress('Building aar'); - try { - await artifactBuilder.buildAar( - buildNumber: buildNumber, - args: results.forwardedArgs, - ); - } on ArtifactBuildException catch (error) { - buildProgress.fail('Failed to build: ${error.message}'); - return ExitCode.software.code; - } - - buildProgress.complete(); - - final aarPath = p.joinAll([ - 'build', - 'host', - 'outputs', - 'repo', - ...shorebirdEnv.androidPackageName!.split('.'), - 'flutter_release', - buildNumber, - 'flutter_release-$buildNumber.aar', - ]); - - logger.info(''' -📦 Generated an aar at: -${lightCyan.wrap(aarPath)}'''); - - return ExitCode.success.code; - } -} diff --git a/packages/shorebird_cli/lib/src/commands/build/build_apk_command.dart b/packages/shorebird_cli/lib/src/commands/build/build_apk_command.dart deleted file mode 100644 index 6043e81c..00000000 --- a/packages/shorebird_cli/lib/src/commands/build/build_apk_command.dart +++ /dev/null @@ -1,75 +0,0 @@ -import 'package:mason_logger/mason_logger.dart'; -import 'package:path/path.dart' as p; -import 'package:shorebird_cli/src/artifact_builder.dart'; -import 'package:shorebird_cli/src/doctor.dart'; -import 'package:shorebird_cli/src/extensions/arg_results.dart'; -import 'package:shorebird_cli/src/logger.dart'; -import 'package:shorebird_cli/src/shorebird_command.dart'; -import 'package:shorebird_cli/src/shorebird_validator.dart'; - -/// {@template build_apk_command} -/// -/// `shorebird build apk` -/// Build an Android APK file from your app. -/// {@endtemplate} -class BuildApkCommand extends ShorebirdCommand { - /// {@macro build_apk_command} - BuildApkCommand() { - argParser - ..addOption( - 'target', - abbr: 't', - help: 'The main entrypoint file of the application.', - ) - ..addOption( - 'flavor', - help: 'The product flavor to use when building the app.', - ); - } - - @override - String get description => 'Build an Android APK file from your app.'; - - @override - String get name => 'apk'; - - @override - Future run() async { - try { - await shorebirdValidator.validatePreconditions( - checkUserIsAuthenticated: true, - checkShorebirdInitialized: true, - validators: doctor.androidCommandValidators, - ); - } on PreconditionFailedException catch (e) { - return e.exitCode.code; - } - - final flavor = results['flavor'] as String?; - final target = results['target'] as String?; - final buildProgress = logger.progress('Building apk'); - try { - await artifactBuilder.buildApk( - flavor: flavor, - target: target, - args: results.forwardedArgs, - ); - } on ArtifactBuildException catch (error) { - buildProgress.fail(error.message); - return ExitCode.software.code; - } - - buildProgress.complete(); - - final apkDirPath = p.join('build', 'app', 'outputs', 'apk'); - final apkPath = flavor != null - ? p.join(apkDirPath, flavor, 'release', 'app-$flavor-release.apk') - : p.join(apkDirPath, 'release', 'app-release.apk'); - - logger.info(''' -📦 Generated an apk at: -${lightCyan.wrap(apkPath)}'''); - - return ExitCode.success.code; - } -} diff --git a/packages/shorebird_cli/lib/src/commands/build/build_app_bundle_command.dart b/packages/shorebird_cli/lib/src/commands/build/build_app_bundle_command.dart deleted file mode 100644 index f97998fd..00000000 --- a/packages/shorebird_cli/lib/src/commands/build/build_app_bundle_command.dart +++ /dev/null @@ -1,74 +0,0 @@ -import 'package:mason_logger/mason_logger.dart'; -import 'package:path/path.dart' as p; -import 'package:shorebird_cli/src/artifact_builder.dart'; -import 'package:shorebird_cli/src/doctor.dart'; -import 'package:shorebird_cli/src/extensions/arg_results.dart'; -import 'package:shorebird_cli/src/logger.dart'; -import 'package:shorebird_cli/src/shorebird_command.dart'; -import 'package:shorebird_cli/src/shorebird_validator.dart'; - -/// {@template build_app_bundle_command} -/// -/// `shorebird build appbundle` -/// Build an Android App Bundle file from your app. -/// {@endtemplate} -class BuildAppBundleCommand extends ShorebirdCommand { - /// {@macro build_app_bundle_command} - BuildAppBundleCommand() { - argParser - ..addOption( - 'target', - abbr: 't', - help: 'The main entrypoint file of the application.', - ) - ..addOption( - 'flavor', - help: 'The product flavor to use when building the app.', - ); - } - - @override - String get description => 'Build an Android App Bundle file from your app.'; - - @override - String get name => 'appbundle'; - - @override - Future run() async { - try { - await shorebirdValidator.validatePreconditions( - checkUserIsAuthenticated: true, - checkShorebirdInitialized: true, - validators: doctor.androidCommandValidators, - ); - } on PreconditionFailedException catch (e) { - return e.exitCode.code; - } - - final flavor = results['flavor'] as String?; - final target = results['target'] as String?; - final buildProgress = logger.progress('Building appbundle'); - try { - await artifactBuilder.buildAppBundle( - flavor: flavor, - target: target, - args: results.forwardedArgs, - ); - } on ArtifactBuildException catch (error) { - buildProgress.fail(error.message); - return ExitCode.software.code; - } - - final bundleDirPath = p.join('build', 'app', 'outputs', 'bundle'); - final bundlePath = flavor != null - ? p.join(bundleDirPath, '${flavor}Release', 'app-$flavor-release.aab') - : p.join(bundleDirPath, 'release', 'app-release.aab'); - - buildProgress.complete(); - logger.info(''' -📦 Generated an app bundle at: -${lightCyan.wrap(bundlePath)}'''); - - return ExitCode.success.code; - } -} diff --git a/packages/shorebird_cli/lib/src/commands/build/build_command.dart b/packages/shorebird_cli/lib/src/commands/build/build_command.dart deleted file mode 100644 index 64f70002..00000000 --- a/packages/shorebird_cli/lib/src/commands/build/build_command.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'package:shorebird_cli/src/commands/build/build.dart'; -import 'package:shorebird_cli/src/shorebird_command.dart'; - -/// {@template build_command} -/// `shorebird build` -/// Build a new release of your application. -/// {@endtemplate} -class BuildCommand extends ShorebirdCommand { - /// {@macro build_command} - BuildCommand() { - addSubcommand(BuildAarCommand()); - addSubcommand(BuildApkCommand()); - addSubcommand(BuildAppBundleCommand()); - addSubcommand(BuildIpaCommand()); - } - - @override - String get description => 'Build a new release of your application.'; - - @override - String get name => 'build'; - - @override - bool get hidden => true; -} diff --git a/packages/shorebird_cli/lib/src/commands/build/build_ipa_command.dart b/packages/shorebird_cli/lib/src/commands/build/build_ipa_command.dart deleted file mode 100644 index be7de8d9..00000000 --- a/packages/shorebird_cli/lib/src/commands/build/build_ipa_command.dart +++ /dev/null @@ -1,99 +0,0 @@ -import 'package:mason_logger/mason_logger.dart'; -import 'package:path/path.dart' as p; -import 'package:shorebird_cli/src/artifact_builder.dart'; -import 'package:shorebird_cli/src/doctor.dart'; -import 'package:shorebird_cli/src/extensions/arg_results.dart'; -import 'package:shorebird_cli/src/logger.dart'; -import 'package:shorebird_cli/src/shorebird_command.dart'; -import 'package:shorebird_cli/src/shorebird_validator.dart'; - -/// {@template build_ipa_command} -/// `shorebird build ipa` -/// Builds an .xcarchive and optionally .ipa for an iOS app to be generated for -/// App Store submission. -/// {@endtemplate} -class BuildIpaCommand extends ShorebirdCommand { - /// {@macro build_ipa_command} - BuildIpaCommand() { - argParser - ..addOption( - 'target', - abbr: 't', - help: 'The main entrypoint file of the application.', - ) - ..addOption( - 'flavor', - help: 'The product flavor to use when building the app.', - ) - ..addFlag( - 'codesign', - help: - '''Codesign the application bundle (only available on device builds).''', - ); - } - - @override - String get description => - '''Builds an .xcarchive and optionally .ipa for an iOS app to be generated for App Store submission.'''; - - @override - String get name => 'ipa'; - - @override - Future run() async { - try { - await shorebirdValidator.validatePreconditions( - checkUserIsAuthenticated: true, - checkShorebirdInitialized: true, - validators: doctor.iosCommandValidators, - ); - } on PreconditionFailedException catch (e) { - return e.exitCode.code; - } - - final flavor = results['flavor'] as String?; - final target = results['target'] as String?; - final codesign = results['codesign'] as bool; - - if (!codesign) { - logger.warn(''' -Codesigning is disabled. You must manually codesign before deploying to devices.'''); - } - - final buildProgress = logger.progress('Building ipa'); - try { - await artifactBuilder.buildIpa( - flavor: flavor, - target: target, - codesign: codesign, - args: results.forwardedArgs, - ); - } on ArtifactBuildException catch (error) { - buildProgress.fail('Failed to build: ${error.message}'); - return ExitCode.software.code; - } - - buildProgress.complete(); - - final xcarchivePath = p.join('build', 'ios', 'archive', 'Runner.xcarchive'); - - logger.info(''' -📦 Generated an xcode archive at: -${lightCyan.wrap(xcarchivePath)}'''); - - if (!codesign) { - logger.info( - 'Codesigning disabled via "--no-codesign". Skipping ipa generation.', - ); - return ExitCode.success.code; - } - - final ipaPath = p.join('build', 'ios', 'ipa', 'Runner.ipa'); - - logger.info(''' -📦 Generated an ipa at: -${lightCyan.wrap(ipaPath)}'''); - - return ExitCode.success.code; - } -} diff --git a/packages/shorebird_cli/lib/src/commands/commands.dart b/packages/shorebird_cli/lib/src/commands/commands.dart index 4ab59817..b1154d17 100644 --- a/packages/shorebird_cli/lib/src/commands/commands.dart +++ b/packages/shorebird_cli/lib/src/commands/commands.dart @@ -1,4 +1,3 @@ -export 'build/build_command.dart'; export 'cache/cache.dart'; export 'doctor_command.dart'; export 'flutter/flutter.dart'; diff --git a/packages/shorebird_cli/lib/src/shorebird_cli_command_runner.dart b/packages/shorebird_cli/lib/src/shorebird_cli_command_runner.dart index a75f40ad..b9aff0d1 100644 --- a/packages/shorebird_cli/lib/src/shorebird_cli_command_runner.dart +++ b/packages/shorebird_cli/lib/src/shorebird_cli_command_runner.dart @@ -67,7 +67,6 @@ class ShorebirdCliCommandRunner extends CompletionCommandRunner { help: 'The build of the local engine to use as the host platform.', ); - addCommand(BuildCommand()); addCommand(CacheCommand()); addCommand(DoctorCommand()); addCommand(FlutterCommand()); diff --git a/packages/shorebird_cli/test/src/commands/build/build_aar_command_test.dart b/packages/shorebird_cli/test/src/commands/build/build_aar_command_test.dart deleted file mode 100644 index 1e8553c7..00000000 --- a/packages/shorebird_cli/test/src/commands/build/build_aar_command_test.dart +++ /dev/null @@ -1,190 +0,0 @@ -import 'package:args/args.dart'; -import 'package:mason_logger/mason_logger.dart'; -import 'package:mocktail/mocktail.dart'; -import 'package:path/path.dart' as p; -import 'package:scoped_deps/scoped_deps.dart'; -import 'package:shorebird_cli/src/artifact_builder.dart'; -import 'package:shorebird_cli/src/commands/build/build.dart'; -import 'package:shorebird_cli/src/logger.dart'; -import 'package:shorebird_cli/src/shorebird_env.dart'; -import 'package:shorebird_cli/src/shorebird_validator.dart'; -import 'package:test/test.dart'; - -import '../../mocks.dart'; - -void main() { - group(BuildAarCommand, () { - const buildNumber = '1.0'; - const androidPackageName = 'com.example.my_flutter_module'; - - late ArgResults argResults; - late ArtifactBuilder artifactBuilder; - late ShorebirdLogger logger; - late Progress progress; - late ShorebirdEnv shorebirdEnv; - late ShorebirdValidator shorebirdValidator; - late BuildAarCommand command; - - R runWithOverrides(R Function() body) { - return runScoped( - body, - values: { - artifactBuilderRef.overrideWith(() => artifactBuilder), - loggerRef.overrideWith(() => logger), - shorebirdEnvRef.overrideWith(() => shorebirdEnv), - shorebirdValidatorRef.overrideWith(() => shorebirdValidator), - }, - ); - } - - setUp(() { - argResults = MockArgResults(); - artifactBuilder = MockArtifactBuilder(); - logger = MockShorebirdLogger(); - progress = MockProgress(); - shorebirdEnv = MockShorebirdEnv(); - shorebirdValidator = MockShorebirdValidator(); - - when(() => argResults['build-number']).thenReturn(buildNumber); - when(() => argResults.rest).thenReturn([]); - when(() => argResults.wasParsed(any())).thenReturn(false); - when(() => logger.progress(any())).thenReturn(progress); - when( - () => artifactBuilder.buildAar( - buildNumber: any(named: 'buildNumber'), - args: any(named: 'args'), - ), - ).thenAnswer((_) async => {}); - when( - () => shorebirdEnv.androidPackageName, - ).thenReturn(androidPackageName); - when( - () => shorebirdValidator.validatePreconditions( - checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'), - checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'), - ), - ).thenAnswer((_) async {}); - - command = runWithOverrides(BuildAarCommand.new) - ..testArgResults = argResults; - }); - - test('has a description', () { - expect(command.description, isNotEmpty); - }); - - test('exits when validation fails', () async { - final exception = ValidationFailedException(); - when( - () => shorebirdValidator.validatePreconditions( - checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'), - checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'), - ), - ).thenThrow(exception); - await expectLater( - runWithOverrides(command.run), - completion(equals(exception.exitCode.code)), - ); - verify( - () => shorebirdValidator.validatePreconditions( - checkUserIsAuthenticated: true, - checkShorebirdInitialized: true, - ), - ).called(1); - }); - - test('exits with 78 if no module entry exists in pubspec.yaml', () async { - when(() => shorebirdEnv.androidPackageName).thenReturn(null); - final result = await runWithOverrides(command.run); - expect(result, ExitCode.config.code); - }); - - test('exits with code 70 when building aar fails', () async { - when( - () => artifactBuilder.buildAar( - buildNumber: any(named: 'buildNumber'), - args: any(named: 'args'), - ), - ).thenThrow(ArtifactBuildException('Failed to build: error')); - - final result = await runWithOverrides(command.run); - - expect(result, equals(ExitCode.software.code)); - verify( - () => artifactBuilder.buildAar(buildNumber: buildNumber, args: []), - ).called(1); - verify( - () => progress.fail(any(that: contains('Failed to build'))), - ).called(1); - }); - - group('when platform was specified via arg results rest', () { - setUp(() { - when(() => argResults.rest).thenReturn(['android', '--verbose']); - }); - - test('exits with code 0 when building aar succeeds', () async { - final result = await runWithOverrides(command.run); - - expect(result, equals(ExitCode.success.code)); - - verify( - () => artifactBuilder.buildAar( - buildNumber: buildNumber, - args: ['--verbose'], - ), - ).called(1); - verify( - () => logger.info( - ''' -📦 Generated an aar at: -${lightCyan.wrap( - p.join( - 'build', - 'host', - 'outputs', - 'repo', - 'com', - 'example', - 'my_flutter_module', - 'flutter_release', - buildNumber, - 'flutter_release-$buildNumber.aar', - ), - )}''', - ), - ).called(1); - }); - }); - - test('exits with code 0 when building aar succeeds', () async { - final result = await runWithOverrides(command.run); - - expect(result, equals(ExitCode.success.code)); - - verify( - () => artifactBuilder.buildAar(buildNumber: buildNumber, args: []), - ).called(1); - verify( - () => logger.info( - ''' -📦 Generated an aar at: -${lightCyan.wrap( - p.join( - 'build', - 'host', - 'outputs', - 'repo', - 'com', - 'example', - 'my_flutter_module', - 'flutter_release', - buildNumber, - 'flutter_release-$buildNumber.aar', - ), - )}''', - ), - ).called(1); - }); - }); -} diff --git a/packages/shorebird_cli/test/src/commands/build/build_apk_command_test.dart b/packages/shorebird_cli/test/src/commands/build/build_apk_command_test.dart deleted file mode 100644 index 25081b18..00000000 --- a/packages/shorebird_cli/test/src/commands/build/build_apk_command_test.dart +++ /dev/null @@ -1,191 +0,0 @@ -import 'dart:io'; - -import 'package:args/args.dart'; -import 'package:mason_logger/mason_logger.dart'; -import 'package:mocktail/mocktail.dart'; -import 'package:path/path.dart' as p; -import 'package:scoped_deps/scoped_deps.dart'; -import 'package:shorebird_cli/src/artifact_builder.dart'; -import 'package:shorebird_cli/src/commands/build/build.dart'; -import 'package:shorebird_cli/src/doctor.dart'; -import 'package:shorebird_cli/src/logger.dart'; -import 'package:shorebird_cli/src/shorebird_validator.dart'; -import 'package:shorebird_cli/src/validators/validators.dart'; -import 'package:test/test.dart'; - -import '../../fakes.dart'; -import '../../mocks.dart'; - -void main() { - group(BuildApkCommand, () { - late ArgResults argResults; - late ArtifactBuilder artifactBuilder; - late Doctor doctor; - late ShorebirdLogger logger; - late ShorebirdFlutterValidator flutterValidator; - late ShorebirdValidator shorebirdValidator; - late BuildApkCommand command; - - R runWithOverrides(R Function() body) { - return runScoped( - body, - values: { - artifactBuilderRef.overrideWith(() => artifactBuilder), - doctorRef.overrideWith(() => doctor), - loggerRef.overrideWith(() => logger), - shorebirdValidatorRef.overrideWith(() => shorebirdValidator), - }, - ); - } - - setUpAll(() { - registerFallbackValue(Directory('')); - registerFallbackValue(FakeShorebirdProcess()); - }); - - setUp(() { - argResults = MockArgResults(); - artifactBuilder = MockArtifactBuilder(); - doctor = MockDoctor(); - logger = MockShorebirdLogger(); - flutterValidator = MockShorebirdFlutterValidator(); - shorebirdValidator = MockShorebirdValidator(); - - when(() => argResults.rest).thenReturn([]); - when(() => argResults.wasParsed(any())).thenReturn(false); - when(() => logger.progress(any())).thenReturn(MockProgress()); - when(() => logger.info(any())).thenReturn(null); - when( - () => shorebirdValidator.validatePreconditions( - checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'), - checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'), - validators: any(named: 'validators'), - ), - ).thenAnswer((_) async {}); - when( - () => doctor.androidCommandValidators, - ).thenReturn([flutterValidator]); - - when( - () => artifactBuilder.buildApk( - flavor: any(named: 'flavor'), - target: any(named: 'target'), - args: any(named: 'args'), - ), - ).thenAnswer((_) async => File('')); - - command = runWithOverrides(BuildApkCommand.new) - ..testArgResults = argResults; - }); - - test('has a description', () { - expect(command.description, isNotEmpty); - }); - - test('exits when validation fails', () async { - final exception = ValidationFailedException(); - when( - () => shorebirdValidator.validatePreconditions( - checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'), - checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'), - validators: any(named: 'validators'), - ), - ).thenThrow(exception); - await expectLater( - runWithOverrides(command.run), - completion(equals(exception.exitCode.code)), - ); - verify( - () => shorebirdValidator.validatePreconditions( - checkUserIsAuthenticated: true, - checkShorebirdInitialized: true, - validators: [flutterValidator], - ), - ).called(1); - }); - - test('exits with code 70 when building apk fails', () async { - when( - () => artifactBuilder.buildApk( - flavor: any(named: 'flavor'), - target: any(named: 'target'), - args: any(named: 'args'), - ), - ).thenThrow(ArtifactBuildException('oops')); - - final exitCode = await runWithOverrides(command.run); - - expect(exitCode, equals(ExitCode.software.code)); - verify( - () => artifactBuilder.buildApk(args: []), - ).called(1); - }); - - group('when platform was specified via arg results rest', () { - setUp(() { - when(() => argResults.rest).thenReturn(['android', '--verbose']); - }); - - test('exits with code 0 when building apk succeeds', () async { - final exitCode = await runWithOverrides(command.run); - - expect(exitCode, equals(ExitCode.success.code)); - - verify( - () => artifactBuilder.buildApk(args: ['--verbose']), - ).called(1); - verify( - () => logger.info( - ''' -📦 Generated an apk at: -${lightCyan.wrap(p.join('build', 'app', 'outputs', 'apk', 'release', 'app-release.apk'))}''', - ), - ).called(1); - }); - }); - - test('exits with code 0 when building apk succeeds', () async { - final exitCode = await runWithOverrides(command.run); - - expect(exitCode, equals(ExitCode.success.code)); - - verify( - () => artifactBuilder.buildApk(args: []), - ).called(1); - verify( - () => logger.info( - ''' -📦 Generated an apk at: -${lightCyan.wrap(p.join('build', 'app', 'outputs', 'apk', 'release', 'app-release.apk'))}''', - ), - ).called(1); - }); - - test( - 'exits with code 0 when building apk succeeds ' - 'with flavor and target', () async { - const flavor = 'development'; - final target = p.join('lib', 'main_development.dart'); - when(() => argResults['flavor']).thenReturn(flavor); - when(() => argResults['target']).thenReturn(target); - final exitCode = await runWithOverrides(command.run); - - expect(exitCode, equals(ExitCode.success.code)); - - verify( - () => artifactBuilder.buildApk( - flavor: flavor, - target: target, - args: [], - ), - ).called(1); - verify( - () => logger.info( - ''' -📦 Generated an apk at: -${lightCyan.wrap(p.join('build', 'app', 'outputs', 'apk', flavor, 'release', 'app-$flavor-release.apk'))}''', - ), - ).called(1); - }); - }); -} diff --git a/packages/shorebird_cli/test/src/commands/build/build_app_bundle_command_test.dart b/packages/shorebird_cli/test/src/commands/build/build_app_bundle_command_test.dart deleted file mode 100644 index 2c25812c..00000000 --- a/packages/shorebird_cli/test/src/commands/build/build_app_bundle_command_test.dart +++ /dev/null @@ -1,237 +0,0 @@ -import 'dart:io'; - -import 'package:args/args.dart'; -import 'package:mason_logger/mason_logger.dart'; -import 'package:mocktail/mocktail.dart'; -import 'package:path/path.dart' as p; -import 'package:scoped_deps/scoped_deps.dart'; -import 'package:shorebird_cli/src/artifact_builder.dart'; -import 'package:shorebird_cli/src/commands/build/build.dart'; -import 'package:shorebird_cli/src/doctor.dart'; -import 'package:shorebird_cli/src/engine_config.dart'; -import 'package:shorebird_cli/src/logger.dart'; -import 'package:shorebird_cli/src/platform/platform.dart'; -import 'package:shorebird_cli/src/shorebird_validator.dart'; -import 'package:shorebird_cli/src/validators/validators.dart'; -import 'package:test/test.dart'; - -import '../../fakes.dart'; -import '../../mocks.dart'; - -void main() { - group(BuildAppBundleCommand, () { - late ArgResults argResults; - late ArtifactBuilder artifactBuilder; - late Doctor doctor; - late ShorebirdLogger logger; - late BuildAppBundleCommand command; - late ShorebirdFlutterValidator flutterValidator; - late ShorebirdValidator shorebirdValidator; - - R runWithOverrides(R Function() body) { - return runScoped( - body, - values: { - artifactBuilderRef.overrideWith(() => artifactBuilder), - doctorRef.overrideWith(() => doctor), - engineConfigRef.overrideWith(() => const EngineConfig.empty()), - loggerRef.overrideWith(() => logger), - shorebirdValidatorRef.overrideWith(() => shorebirdValidator), - }, - ); - } - - setUpAll(() { - registerFallbackValue(FakeShorebirdProcess()); - registerFallbackValue(Directory('')); - }); - - setUp(() { - argResults = MockArgResults(); - artifactBuilder = MockArtifactBuilder(); - doctor = MockDoctor(); - logger = MockShorebirdLogger(); - flutterValidator = MockShorebirdFlutterValidator(); - shorebirdValidator = MockShorebirdValidator(); - - when(() => argResults.rest).thenReturn([]); - when(() => argResults.wasParsed(any())).thenReturn(false); - when(() => logger.progress(any())).thenReturn(MockProgress()); - when(() => logger.info(any())).thenReturn(null); - when( - () => doctor.androidCommandValidators, - ).thenReturn([flutterValidator]); - when( - () => shorebirdValidator.validatePreconditions( - checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'), - checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'), - validators: any(named: 'validators'), - ), - ).thenAnswer((_) async {}); - when( - () => artifactBuilder.buildAppBundle( - flavor: any(named: 'flavor'), - target: any(named: 'target'), - args: any(named: 'args'), - ), - ).thenAnswer((_) async => File('')); - - command = runWithOverrides(BuildAppBundleCommand.new) - ..testArgResults = argResults; - }); - - test('has a description', () { - expect(command.description, isNotEmpty); - }); - - test('exits when validation fails', () async { - final exception = ValidationFailedException(); - when( - () => shorebirdValidator.validatePreconditions( - checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'), - checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'), - validators: any(named: 'validators'), - ), - ).thenThrow(exception); - await expectLater( - runWithOverrides(command.run), - completion(equals(exception.exitCode.code)), - ); - verify( - () => shorebirdValidator.validatePreconditions( - checkUserIsAuthenticated: true, - checkShorebirdInitialized: true, - validators: [flutterValidator], - ), - ).called(1); - }); - - test('exits with code 70 when building appbundle fails', () async { - when( - () => artifactBuilder.buildAppBundle( - args: any(named: 'args'), - ), - ).thenThrow( - ArtifactBuildException('Failed to build: oops'), - ); - - final exitCode = await runWithOverrides(command.run); - - expect(exitCode, equals(ExitCode.software.code)); - verify( - () => artifactBuilder.buildAppBundle(args: []), - ).called(1); - }); - - group('when platform was specified via arg results rest', () { - setUp(() { - when(() => argResults.rest).thenReturn(['android', '--verbose']); - }); - - test('exits with code 0 when building appbundle succeeds', () async { - final exitCode = await runWithOverrides(command.run); - - expect(exitCode, equals(ExitCode.success.code)); - verify( - () => artifactBuilder.buildAppBundle( - args: ['--verbose'], - ), - ).called(1); - - verify( - () => logger.info( - ''' -📦 Generated an app bundle at: -${lightCyan.wrap(p.join('build', 'app', 'outputs', 'bundle', 'release', 'app-release.aab'))}''', - ), - ).called(1); - }); - }); - - test('exits with code 0 when building appbundle succeeds', () async { - final exitCode = await runWithOverrides(command.run); - - expect(exitCode, equals(ExitCode.success.code)); - verify( - () => artifactBuilder.buildAppBundle( - args: [], - ), - ).called(1); - - verify( - () => logger.info( - ''' -📦 Generated an app bundle at: -${lightCyan.wrap(p.join('build', 'app', 'outputs', 'bundle', 'release', 'app-release.aab'))}''', - ), - ).called(1); - }); - - test( - 'exits with code 0 when building appbundle succeeds ' - 'with flavor and target', () async { - const flavor = 'development'; - final target = p.join('lib', 'main_development.dart'); - when(() => argResults['flavor']).thenReturn(flavor); - when(() => argResults['target']).thenReturn(target); - final exitCode = await runWithOverrides(command.run); - - expect(exitCode, equals(ExitCode.success.code)); - verify( - () => artifactBuilder.buildAppBundle( - flavor: flavor, - target: target, - args: [], - ), - ).called(1); - - verify( - () => logger.info( - ''' -📦 Generated an app bundle at: -${lightCyan.wrap(p.join('build', 'app', 'outputs', 'bundle', '${flavor}Release', 'app-$flavor-release.aab'))}''', - ), - ).called(1); - }); - - test('local-engine and architectures', () async { - expect( - runWithOverrides(() => AndroidArch.availableAndroidArchs.length), - greaterThan(1), - ); - - expect( - runScoped( - () => AndroidArch.availableAndroidArchs.length, - values: { - engineConfigRef.overrideWith( - () => const EngineConfig( - localEngine: 'android_release_arm64', - localEngineSrcPath: 'path/to/engine/src', - localEngineHost: 'host_release', - ), - ), - }, - ), - equals(1), - ); - - // We only support a few release configs for now. - expect( - () => runScoped( - () => AndroidArch.availableAndroidArchs.length, - values: { - engineConfigRef.overrideWith( - () => const EngineConfig( - localEngine: 'android_debug_unopt', - localEngineSrcPath: 'path/to/engine/src', - localEngineHost: 'host_debug_unopt', - ), - ), - }, - ), - throwsException, - ); - }); - }); -} diff --git a/packages/shorebird_cli/test/src/commands/build/build_command_test.dart b/packages/shorebird_cli/test/src/commands/build/build_command_test.dart deleted file mode 100644 index d3aef21c..00000000 --- a/packages/shorebird_cli/test/src/commands/build/build_command_test.dart +++ /dev/null @@ -1,16 +0,0 @@ -import 'package:shorebird_cli/src/commands/build/build.dart'; -import 'package:test/test.dart'; - -void main() { - group('build', () { - late BuildCommand command; - - setUp(() { - command = BuildCommand(); - }); - - test('has a description', () async { - expect(command.description, isNotEmpty); - }); - }); -} diff --git a/packages/shorebird_cli/test/src/commands/build/build_ipa_command_test.dart b/packages/shorebird_cli/test/src/commands/build/build_ipa_command_test.dart deleted file mode 100644 index bcc14750..00000000 --- a/packages/shorebird_cli/test/src/commands/build/build_ipa_command_test.dart +++ /dev/null @@ -1,253 +0,0 @@ -import 'dart:io'; - -import 'package:args/args.dart'; -import 'package:mason_logger/mason_logger.dart'; -import 'package:mocktail/mocktail.dart'; -import 'package:path/path.dart' as p; -import 'package:scoped_deps/scoped_deps.dart'; -import 'package:shorebird_cli/src/artifact_builder.dart'; -import 'package:shorebird_cli/src/commands/build/build.dart'; -import 'package:shorebird_cli/src/doctor.dart'; -import 'package:shorebird_cli/src/logger.dart'; -import 'package:shorebird_cli/src/os/operating_system_interface.dart'; -import 'package:shorebird_cli/src/platform/platform.dart'; -import 'package:shorebird_cli/src/shorebird_env.dart'; -import 'package:shorebird_cli/src/shorebird_validator.dart'; -import 'package:shorebird_cli/src/validators/validators.dart'; -import 'package:test/test.dart'; - -import '../../fakes.dart'; -import '../../mocks.dart'; - -void main() { - group(BuildIpaCommand, () { - late ArgResults argResults; - late ArtifactBuilder artifactBuilder; - late Doctor doctor; - late Ios ios; - late ShorebirdLogger logger; - late OperatingSystemInterface operatingSystemInterface; - late BuildIpaCommand command; - late ShorebirdEnv shorebirdEnv; - late ShorebirdFlutterValidator flutterValidator; - late ShorebirdValidator shorebirdValidator; - - R runWithOverrides(R Function() body) { - return runScoped( - body, - values: { - artifactBuilderRef.overrideWith(() => artifactBuilder), - doctorRef.overrideWith(() => doctor), - iosRef.overrideWith(() => ios), - loggerRef.overrideWith(() => logger), - osInterfaceRef.overrideWith(() => operatingSystemInterface), - shorebirdEnvRef.overrideWith(() => shorebirdEnv), - shorebirdValidatorRef.overrideWith(() => shorebirdValidator), - }, - ); - } - - setUpAll(() { - registerFallbackValue(FakeShorebirdProcess()); - }); - - setUp(() { - artifactBuilder = MockArtifactBuilder(); - argResults = MockArgResults(); - doctor = MockDoctor(); - ios = MockIos(); - logger = MockShorebirdLogger(); - operatingSystemInterface = MockOperatingSystemInterface(); - flutterValidator = MockShorebirdFlutterValidator(); - shorebirdEnv = MockShorebirdEnv(); - shorebirdValidator = MockShorebirdValidator(); - - when(() => argResults['codesign']).thenReturn(true); - when(() => argResults.rest).thenReturn([]); - when(() => argResults.wasParsed(any())).thenReturn(false); - when( - () => artifactBuilder.buildIpa( - flavor: any(named: 'flavor'), - target: any(named: 'target'), - codesign: any(named: 'codesign'), - args: any(named: 'args'), - ), - ).thenAnswer((_) async => IpaBuildResult(kernelFile: File(''))); - when(() => ios.createExportOptionsPlist()).thenReturn(File('.')); - when(() => logger.progress(any())).thenReturn(MockProgress()); - when(() => logger.info(any())).thenReturn(null); - when(() => operatingSystemInterface.which('flutter')) - .thenReturn('/path/to/flutter'); - when(() => doctor.iosCommandValidators).thenReturn([flutterValidator]); - when(() => shorebirdEnv.flutterRevision).thenReturn('1234'); - when( - () => shorebirdValidator.validatePreconditions( - checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'), - checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'), - validators: any(named: 'validators'), - ), - ).thenAnswer((_) async {}); - - command = runWithOverrides(BuildIpaCommand.new) - ..testArgResults = argResults; - }); - - test('has a description', () { - expect(command.description, isNotEmpty); - }); - - test('exits when validation fails', () async { - final exception = ValidationFailedException(); - when( - () => shorebirdValidator.validatePreconditions( - checkUserIsAuthenticated: any(named: 'checkUserIsAuthenticated'), - checkShorebirdInitialized: any(named: 'checkShorebirdInitialized'), - validators: any(named: 'validators'), - ), - ).thenThrow(exception); - await expectLater( - runWithOverrides(command.run), - completion(equals(exception.exitCode.code)), - ); - verify( - () => shorebirdValidator.validatePreconditions( - checkUserIsAuthenticated: true, - checkShorebirdInitialized: true, - validators: [flutterValidator], - ), - ).called(1); - }); - - test('exits with code 70 when building ipa fails', () async { - when( - () => artifactBuilder.buildIpa( - flavor: any(named: 'flavor'), - target: any(named: 'target'), - codesign: any(named: 'codesign'), - args: any(named: 'args'), - ), - ).thenThrow(ArtifactBuildException('oops')); - - final exitCode = await runWithOverrides(command.run); - - expect(exitCode, equals(ExitCode.software.code)); - verify( - () => artifactBuilder.buildIpa( - args: [], - ), - ).called(1); - }); - - group('when platform was specified via arg results rest', () { - setUp(() { - when(() => argResults.rest).thenReturn(['ios', '--verbose']); - }); - - test('exits with code 0 when building ipa succeeds', () async { - final exitCode = await runWithOverrides(command.run); - - expect(exitCode, equals(ExitCode.success.code)); - - verify( - () => artifactBuilder.buildIpa(args: ['--verbose']), - ).called(1); - - verifyInOrder([ - () => logger.info( - ''' -📦 Generated an xcode archive at: -${lightCyan.wrap(p.join('build', 'ios', 'archive', 'Runner.xcarchive'))}''', - ), - () => logger.info( - ''' -📦 Generated an ipa at: -${lightCyan.wrap(p.join('build', 'ios', 'ipa', 'Runner.ipa'))}''', - ), - ]); - }); - }); - - test('exits with code 0 when building ipa succeeds', () async { - final exitCode = await runWithOverrides(command.run); - - expect(exitCode, equals(ExitCode.success.code)); - - verify(() => artifactBuilder.buildIpa(args: [])).called(1); - - verifyInOrder([ - () => logger.info( - ''' -📦 Generated an xcode archive at: -${lightCyan.wrap(p.join('build', 'ios', 'archive', 'Runner.xcarchive'))}''', - ), - () => logger.info( - ''' -📦 Generated an ipa at: -${lightCyan.wrap(p.join('build', 'ios', 'ipa', 'Runner.ipa'))}''', - ), - ]); - }); - - test( - 'exits with code 0 when building ipa succeeds ' - 'with flavor and target', () async { - const flavor = 'development'; - final target = p.join('lib', 'main_development.dart'); - when(() => argResults['flavor']).thenReturn(flavor); - when(() => argResults['target']).thenReturn(target); - final exitCode = await runWithOverrides(command.run); - - expect(exitCode, equals(ExitCode.success.code)); - - verify( - () => artifactBuilder.buildIpa( - flavor: flavor, - target: target, - args: [], - ), - ).called(1); - - verifyInOrder([ - () => logger.info( - ''' -📦 Generated an xcode archive at: -${lightCyan.wrap(p.join('build', 'ios', 'archive', 'Runner.xcarchive'))}''', - ), - () => logger.info( - ''' -📦 Generated an ipa at: -${lightCyan.wrap(p.join('build', 'ios', 'ipa', 'Runner.ipa'))}''', - ), - ]); - }); - - test( - 'exits with code 0 when building ipa succeeds ' - 'with --no-codesign', () async { - when(() => argResults['codesign']).thenReturn(false); - final exitCode = await runWithOverrides(command.run); - - expect(exitCode, equals(ExitCode.success.code)); - - verify( - () => artifactBuilder.buildIpa(codesign: false, args: []), - ).called(1); - - verify( - () => logger.info( - ''' -📦 Generated an xcode archive at: -${lightCyan.wrap(p.join('build', 'ios', 'archive', 'Runner.xcarchive'))}''', - ), - ).called(1); - - verifyNever( - () => logger.info( - ''' -📦 Generated an ipa at: -${lightCyan.wrap(p.join('build', 'ios', 'ipa', 'Runner.ipa'))}''', - ), - ); - }); - }); -}