From 4f6e4d7532a7f997907f37a4fc5b31e15d36e06c Mon Sep 17 00:00:00 2001 From: Bryan Oltman Date: Tue, 21 Jan 2025 15:25:18 -0500 Subject: [PATCH] fix: make `shorebird preview` exit early if no previewable releases exist for the specified platform (#2792) --- .../lib/src/commands/preview_command.dart | 46 +++++++------ .../src/commands/preview_command_test.dart | 65 +++++++++++++++---- 2 files changed, 79 insertions(+), 32 deletions(-) diff --git a/packages/shorebird_cli/lib/src/commands/preview_command.dart b/packages/shorebird_cli/lib/src/commands/preview_command.dart index b30e18b7..25e41e1b 100644 --- a/packages/shorebird_cli/lib/src/commands/preview_command.dart +++ b/packages/shorebird_cli/lib/src/commands/preview_command.dart @@ -209,22 +209,35 @@ This is only applicable when previewing Android releases.''', final maybePlatform = results['platform'] != null ? ReleasePlatform.values.byName(results['platform'] as String) : null; + final platformReleases = sideloadableReleases + .where( + (r) => + maybePlatform == null || + r.activePlatforms.contains(maybePlatform), + ) + .toList(); + + if (platformReleases.isEmpty) { + if (maybePlatform != null) { + logger.err( + '''No previewable ${maybePlatform.displayName} releases found''', + ); + } else { + logger.err('No previewable releases found for this app'); + } + return ExitCode.usage.code; + } final releaseVersion = results['release-version'] as String? ?? - // Prompt only for releases that have previewable platforms - // and filter by the specified platform. - await promptForReleaseVersion( - sideloadableReleases, - maybePlatform, - ); + await promptForReleaseVersion(platformReleases); - final release = sideloadableReleases.firstWhereOrNull( + final release = platformReleases.firstWhereOrNull( (r) => r.version == releaseVersion, ); - if (releaseVersion == null || release == null) { - logger.info('No previewable releases found'); - return ExitCode.success.code; + if (release == null) { + logger.err('No previewable releases found for version $releaseVersion'); + return ExitCode.usage.code; } final availablePlatforms = release.activePlatforms @@ -237,7 +250,7 @@ This is only applicable when previewing Android releases.''', logger.err( '''This release can only be previewed on platforms that support $activePlatformsString''', ); - return ExitCode.software.code; + return ExitCode.usage.code; } final releaseWithAllPlatforms = allReleases.firstWhere( @@ -304,16 +317,7 @@ This is only applicable when previewing Android releases.''', } /// Prompts the user to choose a release version to preview. - Future promptForReleaseVersion( - List releases, - ReleasePlatform? platform, - ) async { - if (releases.isEmpty) return null; - if (platform != null) { - releases.removeWhere( - (release) => !release.platformStatuses.keys.contains(platform), - ); - } + Future promptForReleaseVersion(List releases) async { final release = logger.chooseOne( 'Which release would you like to preview?', choices: releases, diff --git a/packages/shorebird_cli/test/src/commands/preview_command_test.dart b/packages/shorebird_cli/test/src/commands/preview_command_test.dart index 79535653..92d985db 100644 --- a/packages/shorebird_cli/test/src/commands/preview_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/preview_command_test.dart @@ -28,7 +28,6 @@ import 'package:shorebird_cli/src/shorebird_validator.dart'; import 'package:shorebird_code_push_client/shorebird_code_push_client.dart'; import 'package:test/test.dart'; -import '../matchers.dart'; import '../mocks.dart'; void main() { @@ -308,6 +307,49 @@ void main() { }); }); + group('when no releases exist', () { + setUp(() { + when( + () => codePushClientWrapper.getReleases( + appId: any(named: 'appId'), + sideloadableOnly: any(named: 'sideloadableOnly'), + ), + ).thenAnswer((_) async => []); + }); + + test('prints error and exits with usage code', () async { + final result = await runWithOverrides(command.run); + expect(result, ExitCode.usage.code); + verify( + () => logger.err('No previewable releases found for this app'), + ).called(1); + }); + }); + + group('when no releases are found for the specified release', () { + setUp(() { + when( + () => codePushClientWrapper.getReleases( + appId: any(named: 'appId'), + sideloadableOnly: any(named: 'sideloadableOnly'), + ), + ).thenAnswer((_) async => [release]); + when( + () => argResults['release-version'], + ).thenReturn('not-a-real-version'); + }); + + test('prints error and exits with usage code', () async { + final result = await runWithOverrides(command.run); + expect(result, ExitCode.usage.code); + verify( + () => logger.err( + 'No previewable releases found for version not-a-real-version', + ), + ).called(1); + }); + }); + group('when release is not supported on the current OS', () { setUp(() { when(() => platform.isLinux).thenReturn(false); @@ -321,7 +363,7 @@ void main() { test('prints error message and exits with code 70', () async { final result = await runWithOverrides(command.run); - expect(result, ExitCode.software.code); + expect(result, ExitCode.usage.code); verify( () => logger.err( 'This release can only be previewed on platforms that support iOS', @@ -1173,9 +1215,9 @@ channel: ${track.channel} ).thenAnswer((_) async => []); }); - test('exits early', () async { + test('logs error message exits early', () async { final result = await runWithOverrides(command.run); - expect(result, equals(ExitCode.success.code)); + expect(result, equals(ExitCode.usage.code)); verifyNever( () => logger.chooseOne( any(), @@ -1189,7 +1231,9 @@ channel: ${track.channel} sideloadableOnly: true, ), ).called(1); - verify(() => logger.info('No previewable releases found')).called(1); + verify( + () => logger.err('No previewable Android releases found'), + ).called(1); }); }); @@ -1690,16 +1734,15 @@ channel: ${DeploymentTrack.staging.channel} ).thenAnswer((_) async => [releaseWithAllPlatforms]); }); - test('err about the platform and exits', () async { + test('prints error that platform is not previewable and exits', + () async { await expectLater( - () => runWithOverrides(command.run), - exitsWithCode(ExitCode.software), + runWithOverrides(command.run), + completion(equals(ExitCode.usage.code)), ); verify( - () => logger.err( - '''The ${ReleasePlatform.ios.displayName} artifact for this release is not previewable.''', - ), + () => logger.err('No previewable iOS releases found'), ).called(1); }); });