feat(shorebird_cli): publish using shorebird_code_push_api_client (#6)

This commit is contained in:
Felix Angelov
2023-03-03 10:04:24 -06:00
committed by GitHub
parent c5ed30f5ec
commit 1943f413f5
4 changed files with 36 additions and 57 deletions
@@ -1,11 +1,11 @@
import 'package:args/args.dart';
import 'package:args/command_runner.dart';
import 'package:cli_completion/cli_completion.dart';
import 'package:http/http.dart' as http;
import 'package:mason_logger/mason_logger.dart';
import 'package:pub_updater/pub_updater.dart';
import 'package:shorebird_cli/src/commands/commands.dart';
import 'package:shorebird_cli/src/version.dart';
import 'package:shorebird_code_push_api_client/shorebird_code_push_api_client.dart';
const executableName = 'shorebird';
const packageName = 'shorebird_cli';
@@ -22,7 +22,7 @@ class ShorebirdCliCommandRunner extends CompletionCommandRunner<int> {
/// {@macro shorebird_cli_command_runner}
ShorebirdCliCommandRunner({
Logger? logger,
http.Client? httpClient,
ShorebirdCodePushApiClient? codePushApiClient,
PubUpdater? pubUpdater,
}) : _logger = logger ?? Logger(),
_pubUpdater = pubUpdater ?? PubUpdater(),
@@ -41,7 +41,9 @@ class ShorebirdCliCommandRunner extends CompletionCommandRunner<int> {
);
// Add sub commands
addCommand(PublishCommand(logger: _logger, httpClient: httpClient));
addCommand(
PublishCommand(logger: _logger, codePushApiClient: codePushApiClient),
);
addCommand(UpdateCommand(logger: _logger, pubUpdater: _pubUpdater));
}
@@ -1,19 +1,21 @@
import 'dart:io';
import 'package:args/command_runner.dart';
import 'package:http/http.dart' as http;
import 'package:mason_logger/mason_logger.dart';
import 'package:shorebird_code_push_api_client/shorebird_code_push_api_client.dart';
/// {@template sample_command}
/// {@template publish_command}
///
/// `shorebird sample`
/// A [Command] to exemplify a sub command
/// `shorebird publish <path/to/artifact>`
/// Publish new releases to the Shorebird CodePush server.
/// {@endtemplate}
class PublishCommand extends Command<int> {
/// {@macro sample_command}
PublishCommand({required Logger logger, http.Client? httpClient})
: _logger = logger,
_httpClient = httpClient ?? http.Client();
/// {@macro publish_command}
PublishCommand({
required Logger logger,
ShorebirdCodePushApiClient? codePushApiClient,
}) : _logger = logger,
_codePushApiClient = codePushApiClient ?? ShorebirdCodePushApiClient();
@override
String get description => 'Publish an update.';
@@ -22,7 +24,7 @@ class PublishCommand extends Command<int> {
String get name => 'publish';
final Logger _logger;
final http.Client _httpClient;
final ShorebirdCodePushApiClient _codePushApiClient;
@override
Future<int> run() async {
@@ -37,23 +39,14 @@ class PublishCommand extends Command<int> {
return ExitCode.noInput.code;
}
final request = http.MultipartRequest(
'POST',
Uri.parse('http://localhost:8080/api/v1/releases'),
);
final file = await http.MultipartFile.fromPath('file', artifact.path);
request.files.add(file);
final response = await _httpClient.send(request);
if (response.statusCode != HttpStatus.created) {
_logger.err(
'Failed to deploy: ${response.statusCode} ${response.reasonPhrase}',
);
try {
await _codePushApiClient.createRelease(artifact.path);
} catch (error) {
_logger.err('Failed to deploy: $error');
return ExitCode.software.code;
}
_logger.success('Deployed ${artifact.path}!');
return ExitCode.success.code;
}
}
+4 -1
View File
@@ -2,16 +2,19 @@ name: shorebird_cli
description: The shorebird command-line tool
version: 0.0.1
publish_to: none
environment:
sdk: ">=2.19.0 <3.0.0"
dependencies:
args: ^2.3.1
cli_completion: ^0.2.0
http: ^0.13.5
mason_logger: ^0.2.4
path: ^1.8.3
pub_updater: ^0.2.4
shorebird_code_push_api_client:
path: ../shorebird_code_push_api_client
dev_dependencies:
build_runner: ^2.0.0
@@ -1,34 +1,27 @@
import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:mason_logger/mason_logger.dart';
import 'package:mocktail/mocktail.dart';
import 'package:path/path.dart' as p;
import 'package:shorebird_cli/src/command_runner.dart';
import 'package:shorebird_code_push_api_client/shorebird_code_push_api_client.dart';
import 'package:test/test.dart';
class _MockLogger extends Mock implements Logger {}
class _MockHttpClient extends Mock implements http.Client {}
class _FakeBaseRequest extends Fake implements http.BaseRequest {}
class _MockShorebirdCodePushApiClient extends Mock
implements ShorebirdCodePushApiClient {}
void main() {
group('publish', () {
late Logger logger;
late http.Client httpClient;
late _MockShorebirdCodePushApiClient codePushApiClient;
late ShorebirdCliCommandRunner commandRunner;
setUpAll(() {
registerFallbackValue(_FakeBaseRequest());
});
setUp(() {
logger = _MockLogger();
httpClient = _MockHttpClient();
codePushApiClient = _MockShorebirdCodePushApiClient();
commandRunner = ShorebirdCliCommandRunner(
logger: logger,
httpClient: httpClient,
codePushApiClient: codePushApiClient,
);
});
@@ -58,30 +51,18 @@ void main() {
});
test('throws error when release fails.', () async {
const statusCode = HttpStatus.internalServerError;
const reasonPhrase = 'something went wrong';
when(() => httpClient.send(any())).thenAnswer(
(_) async => http.StreamedResponse(
const Stream.empty(),
statusCode,
reasonPhrase: reasonPhrase,
),
);
const error = 'something went wrong';
when(() => codePushApiClient.createRelease(any())).thenThrow(error);
final release = p.join('test', 'fixtures', 'release.txt');
final exitCode = await commandRunner.run(['publish', release]);
verify(
() => logger.err('Failed to deploy: $statusCode $reasonPhrase'),
).called(1);
verify(() => logger.err('Failed to deploy: $error')).called(1);
expect(exitCode, ExitCode.software.code);
});
test('succeeds when release is successful.', () async {
when(() => httpClient.send(any())).thenAnswer(
(_) async => http.StreamedResponse(
const Stream.empty(),
HttpStatus.created,
),
);
when(
() => codePushApiClient.createRelease(any()),
).thenAnswer((_) async {});
final release = p.join('test', 'fixtures', 'release.txt');
final exitCode = await commandRunner.run(['publish', release]);
verify(() => logger.success('Deployed $release!')).called(1);