feat(shorebird_cli): add base_url to shorebird.yaml (#99)
This commit is contained in:
@@ -5,10 +5,12 @@ import 'package:args/command_runner.dart';
|
||||
import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:shorebird_cli/src/auth/auth.dart';
|
||||
import 'package:shorebird_cli/src/command_runner.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
|
||||
typedef CodePushClientBuilder = CodePushClient Function({
|
||||
required String apiKey,
|
||||
Uri? hostedUri,
|
||||
});
|
||||
|
||||
typedef StartProcess = Future<Process> Function(
|
||||
@@ -17,12 +19,6 @@ typedef StartProcess = Future<Process> Function(
|
||||
bool runInShell,
|
||||
});
|
||||
|
||||
typedef RunProcess = Future<ProcessResult> Function(
|
||||
String executable,
|
||||
List<String> arguments, {
|
||||
bool runInShell,
|
||||
});
|
||||
|
||||
abstract class ShorebirdCommand extends Command<int> {
|
||||
ShorebirdCommand({
|
||||
required this.logger,
|
||||
|
||||
@@ -55,7 +55,10 @@ Defaults to the app_id in "shorebird.yaml".''',
|
||||
appId = appIdArg;
|
||||
}
|
||||
|
||||
final client = buildCodePushClient(apiKey: session.apiKey);
|
||||
final client = buildCodePushClient(
|
||||
apiKey: session.apiKey,
|
||||
hostedUri: hostedUri,
|
||||
);
|
||||
|
||||
try {
|
||||
await client.createApp(appId: appId);
|
||||
|
||||
@@ -55,7 +55,10 @@ Defaults to the app_id in "shorebird.yaml".''',
|
||||
appId = appIdArg;
|
||||
}
|
||||
|
||||
final client = buildCodePushClient(apiKey: session.apiKey);
|
||||
final client = buildCodePushClient(
|
||||
apiKey: session.apiKey,
|
||||
hostedUri: hostedUri,
|
||||
);
|
||||
|
||||
final confirm = logger.confirm('Deleting an app is permanent. Continue?');
|
||||
if (!confirm) {
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'dart:async';
|
||||
|
||||
import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:shorebird_cli/src/command.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
|
||||
/// {@template list_apps_command}
|
||||
@@ -9,7 +10,7 @@ import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
/// `shorebird apps list`
|
||||
/// List all apps using Shorebird.
|
||||
/// {@endtemplate}
|
||||
class ListAppsCommand extends ShorebirdCommand {
|
||||
class ListAppsCommand extends ShorebirdCommand with ShorebirdConfigMixin {
|
||||
/// {@macro list_apps_command}
|
||||
ListAppsCommand({
|
||||
required super.logger,
|
||||
@@ -34,7 +35,10 @@ class ListAppsCommand extends ShorebirdCommand {
|
||||
return ExitCode.noUser.code;
|
||||
}
|
||||
|
||||
final client = buildCodePushClient(apiKey: session.apiKey);
|
||||
final client = buildCodePushClient(
|
||||
apiKey: session.apiKey,
|
||||
hostedUri: hostedUri,
|
||||
);
|
||||
|
||||
late final List<App> apps;
|
||||
try {
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'dart:io';
|
||||
|
||||
import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:shorebird_cli/src/command.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_engine_mixin.dart';
|
||||
|
||||
typedef RunProcess = Future<ProcessResult> Function(
|
||||
@@ -15,7 +16,8 @@ typedef RunProcess = Future<ProcessResult> Function(
|
||||
/// `shorebird build`
|
||||
/// Build a new release of your application.
|
||||
/// {@endtemplate}
|
||||
class BuildCommand extends ShorebirdCommand with ShorebirdEngineMixin {
|
||||
class BuildCommand extends ShorebirdCommand
|
||||
with ShorebirdConfigMixin, ShorebirdEngineMixin {
|
||||
/// {@macro build_command}
|
||||
BuildCommand({
|
||||
required super.logger,
|
||||
|
||||
@@ -68,7 +68,10 @@ class PublishCommand extends ShorebirdCommand with ShorebirdConfigMixin {
|
||||
try {
|
||||
final pubspecYaml = getPubspecYaml()!;
|
||||
final shorebirdYaml = getShorebirdYaml()!;
|
||||
final codePushClient = buildCodePushClient(apiKey: session.apiKey);
|
||||
final codePushClient = buildCodePushClient(
|
||||
apiKey: session.apiKey,
|
||||
hostedUri: hostedUri,
|
||||
);
|
||||
logger.detail(
|
||||
'''Deploying ${artifact.path} to ${shorebirdYaml.appId} (${pubspecYaml.version})''',
|
||||
);
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'dart:io';
|
||||
|
||||
import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:shorebird_cli/src/command.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_engine_mixin.dart';
|
||||
|
||||
typedef StartProcess = Future<Process> Function(
|
||||
@@ -16,7 +17,8 @@ typedef StartProcess = Future<Process> Function(
|
||||
/// `shorebird run`
|
||||
/// Run the Flutter application.
|
||||
/// {@endtemplate}
|
||||
class RunCommand extends ShorebirdCommand with ShorebirdEngineMixin {
|
||||
class RunCommand extends ShorebirdCommand
|
||||
with ShorebirdConfigMixin, ShorebirdEngineMixin {
|
||||
/// {@macro run_command}
|
||||
RunCommand({
|
||||
required super.logger,
|
||||
|
||||
@@ -8,10 +8,11 @@ part 'shorebird_yaml.g.dart';
|
||||
createToJson: false,
|
||||
)
|
||||
class ShorebirdYaml {
|
||||
const ShorebirdYaml({required this.appId});
|
||||
const ShorebirdYaml({required this.appId, this.baseUrl});
|
||||
|
||||
factory ShorebirdYaml.fromJson(Map<dynamic, dynamic> json) =>
|
||||
_$ShorebirdYamlFromJson(json);
|
||||
|
||||
final String appId;
|
||||
final String? baseUrl;
|
||||
}
|
||||
|
||||
@@ -14,12 +14,13 @@ ShorebirdYaml _$ShorebirdYamlFromJson(Map json) => $checkedCreate(
|
||||
($checkedConvert) {
|
||||
$checkKeys(
|
||||
json,
|
||||
allowedKeys: const ['app_id'],
|
||||
allowedKeys: const ['app_id', 'base_url'],
|
||||
);
|
||||
final val = ShorebirdYaml(
|
||||
appId: $checkedConvert('app_id', (v) => v as String),
|
||||
baseUrl: $checkedConvert('base_url', (v) => v as String?),
|
||||
);
|
||||
return val;
|
||||
},
|
||||
fieldKeyMap: const {'appId': 'app_id'},
|
||||
fieldKeyMap: const {'appId': 'app_id', 'baseUrl': 'base_url'},
|
||||
);
|
||||
|
||||
@@ -16,6 +16,15 @@ mixin ShorebirdConfigMixin on ShorebirdCommand {
|
||||
return hasShorebirdYaml && pubspecContainsShorebirdYaml;
|
||||
}
|
||||
|
||||
Uri? get hostedUri {
|
||||
try {
|
||||
final baseUrl = getShorebirdYaml()?.baseUrl;
|
||||
return baseUrl == null ? null : Uri.tryParse(baseUrl);
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
bool get pubspecContainsShorebirdYaml {
|
||||
final file = File(p.join(Directory.current.path, 'pubspec.yaml'));
|
||||
final pubspecContents = file.readAsStringSync();
|
||||
|
||||
@@ -5,9 +5,10 @@ import 'dart:isolate';
|
||||
import 'package:archive/archive_io.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:shorebird_cli/src/command.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_config_mixin.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
|
||||
mixin ShorebirdEngineMixin on ShorebirdCommand {
|
||||
mixin ShorebirdEngineMixin on ShorebirdConfigMixin {
|
||||
String get shorebirdEnginePath {
|
||||
return p.join(
|
||||
Directory.current.path,
|
||||
@@ -31,6 +32,7 @@ mixin ShorebirdEngineMixin on ShorebirdCommand {
|
||||
try {
|
||||
final codePushClient = buildCodePushClient(
|
||||
apiKey: auth.currentSession!.apiKey,
|
||||
hostedUri: hostedUri,
|
||||
);
|
||||
await _downloadShorebirdEngine(
|
||||
codePushClient,
|
||||
|
||||
@@ -34,7 +34,9 @@ void main() {
|
||||
codePushClient = _MockCodePushClient();
|
||||
command = CreateAppCommand(
|
||||
auth: auth,
|
||||
buildCodePushClient: ({required String apiKey}) => codePushClient,
|
||||
buildCodePushClient: ({required String apiKey, Uri? hostedUri}) {
|
||||
return codePushClient;
|
||||
},
|
||||
logger: logger,
|
||||
)..testArgResults = argResults;
|
||||
|
||||
|
||||
@@ -34,7 +34,9 @@ void main() {
|
||||
codePushClient = _MockCodePushClient();
|
||||
command = DeleteAppCommand(
|
||||
auth: auth,
|
||||
buildCodePushClient: ({required String apiKey}) => codePushClient,
|
||||
buildCodePushClient: ({required String apiKey, Uri? hostedUri}) {
|
||||
return codePushClient;
|
||||
},
|
||||
logger: logger,
|
||||
)..testArgResults = argResults;
|
||||
|
||||
|
||||
@@ -28,7 +28,9 @@ void main() {
|
||||
logger = _MockLogger();
|
||||
command = ListAppsCommand(
|
||||
auth: auth,
|
||||
buildCodePushClient: ({required String apiKey}) => codePushClient,
|
||||
buildCodePushClient: ({required String apiKey, Uri? hostedUri}) {
|
||||
return codePushClient;
|
||||
},
|
||||
logger: logger,
|
||||
);
|
||||
|
||||
|
||||
@@ -41,7 +41,9 @@ void main() {
|
||||
processResult = _MockProcessResult();
|
||||
buildCommand = BuildCommand(
|
||||
auth: auth,
|
||||
buildCodePushClient: ({required String apiKey}) => codePushClient,
|
||||
buildCodePushClient: ({required String apiKey, Uri? hostedUri}) {
|
||||
return codePushClient;
|
||||
},
|
||||
logger: logger,
|
||||
runProcess: (executable, arguments, {bool runInShell = false}) async {
|
||||
return processResult;
|
||||
|
||||
@@ -46,6 +46,7 @@ flutter:
|
||||
late Logger logger;
|
||||
late CodePushClient codePushClient;
|
||||
late PublishCommand command;
|
||||
late Uri? capturedHostedUri;
|
||||
|
||||
Directory setUpTempDir() {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
@@ -65,7 +66,10 @@ flutter:
|
||||
codePushClient = _MockCodePushClient();
|
||||
command = PublishCommand(
|
||||
auth: auth,
|
||||
buildCodePushClient: ({required String apiKey}) => codePushClient,
|
||||
buildCodePushClient: ({required String apiKey, Uri? hostedUri}) {
|
||||
capturedHostedUri = hostedUri;
|
||||
return codePushClient;
|
||||
},
|
||||
logger: logger,
|
||||
)
|
||||
..testArgResults = argResults
|
||||
@@ -191,6 +195,26 @@ flutter:
|
||||
),
|
||||
).called(1);
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
expect(capturedHostedUri, isNull);
|
||||
});
|
||||
|
||||
test('succeeds when publish is successful using custom base_url', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
const baseUrl = 'https://example.com';
|
||||
File(
|
||||
p.join(tempDir.path, 'shorebird.yaml'),
|
||||
).writeAsStringSync(
|
||||
'''
|
||||
app_id: $appId
|
||||
base_url: $baseUrl''',
|
||||
);
|
||||
final artifact = File(p.join(tempDir.path, 'patch.txt'))..createSync();
|
||||
when(() => argResults.rest).thenReturn([artifact.path]);
|
||||
await IOOverrides.runZoned(
|
||||
command.run,
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
expect(capturedHostedUri, equals(Uri.parse(baseUrl)));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ void main() {
|
||||
runCommand = RunCommand(
|
||||
auth: auth,
|
||||
logger: logger,
|
||||
buildCodePushClient: ({required String apiKey}) {
|
||||
buildCodePushClient: ({required String apiKey, Uri? hostedUri}) {
|
||||
return codePushClient;
|
||||
},
|
||||
startProcess: (executable, arguments, {bool runInShell = false}) async {
|
||||
|
||||
Reference in New Issue
Block a user