From 37b3a1d79273aed164c09d90d49d0a4b776845a6 Mon Sep 17 00:00:00 2001 From: Bryan Oltman Date: Mon, 16 Oct 2023 17:20:57 -0400 Subject: [PATCH] feat(shorebird_cli): add release-version flag to iOS and Android patch commands (#1400) --- .../commands/patch/patch_android_command.dart | 36 ++++++++++----- .../src/commands/patch/patch_ios_command.dart | 28 +++++++++--- .../patch/patch_android_command_test.dart | 33 +++++++++++++- .../patch/patch_ios_command_test.dart | 44 ++++++++++++++++++- 4 files changed, 121 insertions(+), 20 deletions(-) diff --git a/packages/shorebird_cli/lib/src/commands/patch/patch_android_command.dart b/packages/shorebird_cli/lib/src/commands/patch/patch_android_command.dart index bfabae27..3c618403 100644 --- a/packages/shorebird_cli/lib/src/commands/patch/patch_android_command.dart +++ b/packages/shorebird_cli/lib/src/commands/patch/patch_android_command.dart @@ -50,6 +50,13 @@ class PatchAndroidCommand extends ShorebirdCommand 'flavor', help: 'The product flavor to use when building the app.', ) + ..addOption( + 'release-version', + help: ''' +The version of the release being patched (e.g. "1.0.0+1"). + +If this option is not provided, the version number will be determined from the patch artifact.''', + ) ..addFlag( 'force', abbr: 'f', @@ -125,19 +132,26 @@ class PatchAndroidCommand extends ShorebirdCommand ? './build/app/outputs/bundle/${flavor}Release/app-$flavor-release.aab' : './build/app/outputs/bundle/release/app-release.aab'; - final detectReleaseVersionProgress = logger.progress( - 'Detecting release version', - ); - final String releaseVersion; - try { - releaseVersion = await extractReleaseVersionFromAppBundle(bundlePath); - detectReleaseVersionProgress.complete( - 'Detected release version $releaseVersion', + final argReleaseVersion = results['release-version'] as String?; + if (argReleaseVersion != null) { + logger.detail('Using release version $argReleaseVersion from argument.'); + releaseVersion = argReleaseVersion; + } else { + logger.detail('No release version provided. Determining from bundle.'); + final detectReleaseVersionProgress = logger.progress( + 'Detecting release version', ); - } catch (error) { - detectReleaseVersionProgress.fail('$error'); - return ExitCode.software.code; + + try { + releaseVersion = await extractReleaseVersionFromAppBundle(bundlePath); + detectReleaseVersionProgress.complete( + 'Detected release version $releaseVersion', + ); + } catch (error) { + detectReleaseVersionProgress.fail('$error'); + return ExitCode.software.code; + } } final release = await codePushClientWrapper.getRelease( diff --git a/packages/shorebird_cli/lib/src/commands/patch/patch_ios_command.dart b/packages/shorebird_cli/lib/src/commands/patch/patch_ios_command.dart index 9a6a74cf..1c0776c2 100644 --- a/packages/shorebird_cli/lib/src/commands/patch/patch_ios_command.dart +++ b/packages/shorebird_cli/lib/src/commands/patch/patch_ios_command.dart @@ -43,6 +43,13 @@ class PatchIosCommand extends ShorebirdCommand 'flavor', help: 'The product flavor to use when building the app.', ) + ..addOption( + 'release-version', + help: ''' +The version of the release being patched (e.g. "1.0.0+1"). + +If this option is not provided, the version number will be determined from the patch artifact.''', + ) ..addFlag( 'codesign', help: 'Codesign the application bundle.', @@ -129,14 +136,21 @@ class PatchIosCommand extends ShorebirdCommand final plist = Plist(file: plistFile); final String releaseVersion; - try { - releaseVersion = plist.versionNumber; - } catch (error) { - logger.err('Failed to determine release version: $error'); - return ExitCode.software.code; - } + final argReleaseVersion = results['release-version'] as String?; + if (argReleaseVersion != null) { + logger.detail('Using release version $argReleaseVersion from argument.'); + releaseVersion = argReleaseVersion; + } else { + logger.detail('No release version provided. Determining from archive.'); + try { + releaseVersion = plist.versionNumber; + } catch (error) { + logger.err('Failed to determine release version: $error'); + return ExitCode.software.code; + } - logger.info('Detected release version $releaseVersion'); + logger.info('Detected release version $releaseVersion'); + } final release = await codePushClientWrapper.getRelease( appId: appId, diff --git a/packages/shorebird_cli/test/src/commands/patch/patch_android_command_test.dart b/packages/shorebird_cli/test/src/commands/patch/patch_android_command_test.dart index fb673ce9..e6bf3bb4 100644 --- a/packages/shorebird_cli/test/src/commands/patch/patch_android_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/patch/patch_android_command_test.dart @@ -270,7 +270,6 @@ flutter: when(() => argResults['staging']).thenReturn(false); when(() => argResults['dry-run']).thenReturn(false); when(() => argResults['force']).thenReturn(false); - when(() => argResults['release-version']).thenReturn(release.version); when(() => auth.isAuthenticated).thenReturn(true); when(() => auth.client).thenReturn(httpClient); when(() => logger.progress(any())).thenReturn(progress); @@ -530,6 +529,38 @@ Please re-run the release command for this version or create a new release.'''), }, ); + group('when release-version option is provided', () { + setUp(() { + when(() => argResults['release-version']).thenReturn(release.version); + }); + + test('does not extract release version from app bundle', () async { + final tempDir = setUpTempDir(); + setUpTempArtifacts(tempDir); + await IOOverrides.runZoned( + () => runWithOverrides(command.run), + getCurrentDirectory: () => tempDir, + ); + verifyNever(() => bundletool.getVersionName(any())); + verifyNever(() => bundletool.getVersionCode(any())); + verifyNever(() => logger.progress('Detecting release version')); + }); + }); + + group('when release-version option is not provided', () { + test('extracts release version from app bundle', () async { + final tempDir = setUpTempDir(); + setUpTempArtifacts(tempDir); + await IOOverrides.runZoned( + () => runWithOverrides(command.run), + getCurrentDirectory: () => tempDir, + ); + verify(() => bundletool.getVersionName(any())).called(1); + verify(() => bundletool.getVersionCode(any())).called(1); + verify(() => logger.progress('Detecting release version')).called(1); + }); + }); + test('errors when detecting release version name fails', () async { final exception = Exception( 'Failed to extract version name from app bundle: oops', diff --git a/packages/shorebird_cli/test/src/commands/patch/patch_ios_command_test.dart b/packages/shorebird_cli/test/src/commands/patch/patch_ios_command_test.dart index d5268fba..dc77fa2a 100644 --- a/packages/shorebird_cli/test/src/commands/patch/patch_ios_command_test.dart +++ b/packages/shorebird_cli/test/src/commands/patch/patch_ios_command_test.dart @@ -254,7 +254,6 @@ flutter: when(() => argResults['arch']).thenReturn(arch); when(() => argResults['dry-run']).thenReturn(false); when(() => argResults['force']).thenReturn(false); - when(() => argResults['release-version']).thenReturn(release.version); when(() => argResults['codesign']).thenReturn(true); when(() => argResults['staging']).thenReturn(false); when(() => argResults.rest).thenReturn([]); @@ -669,6 +668,49 @@ Please re-run the release command for this version or create a new release.'''), }, ); + group('when release-version option is provided', () { + const customReleaseVersion = 'custom-release-version'; + + setUp(() { + when(() => argResults['release-version']) + .thenReturn(customReleaseVersion); + }); + + test('does not extract release version from archive', () async { + final tempDir = setUpTempDir(); + setUpTempArtifacts(tempDir); + await IOOverrides.runZoned( + () => runWithOverrides(command.run), + getCurrentDirectory: () => tempDir, + ); + + verify( + () => codePushClientWrapper.getRelease( + appId: appId, + releaseVersion: customReleaseVersion, + ), + ).called(1); + }); + }); + + group('when release-version option is not provided', () { + test('extracts release version from app bundle', () async { + final tempDir = setUpTempDir(); + setUpTempArtifacts(tempDir); + await IOOverrides.runZoned( + () => runWithOverrides(command.run), + getCurrentDirectory: () => tempDir, + ); + + verify( + () => codePushClientWrapper.getRelease( + appId: appId, + releaseVersion: release.version, + ), + ).called(1); + }); + }); + test('exits with code 70 when release version cannot be determiend', () async { final tempDir = setUpTempDir();