From 5269a288fa2ce8333a875c8173129686600b4ada Mon Sep 17 00:00:00 2001 From: Bryan Oltman Date: Wed, 28 Aug 2024 10:34:08 -0400 Subject: [PATCH] feat: show progress when updating cache artifacts (#2448) --- packages/shorebird_cli/lib/src/cache.dart | 15 +++++++++- .../shorebird_cli/test/src/cache_test.dart | 30 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/packages/shorebird_cli/lib/src/cache.dart b/packages/shorebird_cli/lib/src/cache.dart index c38bd438..bf4936e4 100644 --- a/packages/shorebird_cli/lib/src/cache.dart +++ b/packages/shorebird_cli/lib/src/cache.dart @@ -180,6 +180,8 @@ abstract class CachedArtifact { // Clear any existing artifact files. await _delete(); + final updateProgress = logger.progress('Downloading $fileName...'); + final request = http.Request('GET', Uri.parse(storageUrl)); final http.StreamedResponse response; try { @@ -201,17 +203,27 @@ allowed to access $storageUrl.''', return; } + updateProgress.fail(); throw CacheUpdateFailure( '''Failed to download $fileName: ${response.statusCode} ${response.reasonPhrase}''', ); } + updateProgress.complete(); + + final extractProgress = logger.progress('Extracting $fileName...'); final artifactDirectory = Directory(p.dirname(file.path)); - await extractArtifact(response.stream, artifactDirectory.path); + try { + await extractArtifact(response.stream, artifactDirectory.path); + } catch (_) { + extractProgress.fail(); + rethrow; + } final expectedChecksum = checksum; if (expectedChecksum != null) { if (!checksumChecker.checkFile(file, expectedChecksum)) { + extractProgress.fail(); // Delete the artifact directory, so if the download is retried, it will // be re-downloaded. artifactDirectory.deleteSync(recursive: true); @@ -230,6 +242,7 @@ allowed to access $storageUrl.''', await result.exitCode; } + extractProgress.complete(); _writeStampFile(); } diff --git a/packages/shorebird_cli/test/src/cache_test.dart b/packages/shorebird_cli/test/src/cache_test.dart index 325eb2a1..6e0315fd 100644 --- a/packages/shorebird_cli/test/src/cache_test.dart +++ b/packages/shorebird_cli/test/src/cache_test.dart @@ -32,6 +32,7 @@ void main() { late ShorebirdLogger logger; late Platform platform; late Process chmodProcess; + late Progress progress; late ShorebirdEnv shorebirdEnv; late ShorebirdProcess shorebirdProcess; @@ -77,6 +78,7 @@ void main() { httpClient = MockHttpClient(); logger = MockShorebirdLogger(); platform = MockPlatform(); + progress = MockProgress(); shorebirdEnv = MockShorebirdEnv(); shorebirdProcess = MockShorebirdProcess(); @@ -90,6 +92,7 @@ void main() { (invocation.namedArguments[#outputDirectory] as Directory) .createSync(recursive: true); }); + when(() => logger.progress(any())).thenReturn(progress); when( () => shorebirdEnv.shorebirdEngineRevision, ).thenReturn(shorebirdEngineRevision); @@ -276,11 +279,31 @@ void main() { expect(patchArtifactDirectory.existsSync(), isTrue); }); + group('when extraction fails', () { + setUp(() { + when( + () => artifactManager.extractZip( + zipFile: any(named: 'zipFile'), + outputDirectory: any(named: 'outputDirectory'), + ), + ).thenThrow(Exception('test')); + }); + + test('throws exception, logs failure', () async { + await expectLater( + () => runWithOverrides(cache.updateAll), + throwsException, + ); + verify(() => progress.fail()).called(3); + }); + }); + group('when checksum validation fails', () { setUp(() { when(() => checksumChecker.checkFile(any(), any())) .thenReturn(false); }); + test('fails with the correct message', () async { await expectLater( () => runWithOverrides(cache.updateAll), @@ -294,6 +317,8 @@ void main() { ), ), ); + + verify(() => progress.fail()).called(3); }); }); @@ -375,6 +400,7 @@ void main() { late http.Client httpClient; late ShorebirdLogger logger; late Platform platform; + late Progress progress; late _TestCachedArtifact cachedArtifact; R runWithOverrides(R Function() body) { @@ -399,6 +425,7 @@ void main() { httpClient = MockHttpClient(); logger = MockShorebirdLogger(); platform = MockPlatform(); + progress = MockProgress(); when(() => httpClient.send(any())).thenAnswer( (_) async => http.StreamedResponse( @@ -406,6 +433,9 @@ void main() { HttpStatus.notFound, ), ); + + when(() => logger.progress(any())).thenReturn(progress); + cachedArtifact = _TestCachedArtifact(cache: cache, platform: platform); });