Skip to content

Commit

Permalink
fix: improve error output for failed shorebird preview on iOS (#2634)
Browse files Browse the repository at this point in the history
  • Loading branch information
bryanoltman authored Nov 20, 2024
1 parent fe4cbbd commit bb1807c
Show file tree
Hide file tree
Showing 6 changed files with 334 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,8 @@ class Devicectl {
}

return rootError.userInfo.localizedFailureReason?.string ??
rootError.userInfo.localizedDescription?.string ??
rootError.userInfo.description?.string ??
'unknown failure reason';
}
}
80 changes: 71 additions & 9 deletions packages/shorebird_cli/lib/src/executables/devicectl/nserror.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// ignore_for_file: public_member_api_docs

import 'package:equatable/equatable.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';

Expand All @@ -10,8 +11,8 @@ part 'nserror.g.dart';
///
/// See https://developer.apple.com/documentation/foundation/nserror.
/// {@endtemplate}
@JsonSerializable(createToJson: false, fieldRename: FieldRename.none)
class NSError {
@JsonSerializable(fieldRename: FieldRename.none)
class NSError extends Equatable {
/// {@macro nserror}
const NSError({
required this.code,
Expand All @@ -25,16 +26,37 @@ class NSError {

/// Creates an [NSError] from JSON.
static NSError fromJson(Json json) => _$NSErrorFromJson(json);

Json toJson() => _$NSErrorToJson(this);

@override
String toString() => '''
NSError(
code: $code,
domain: $domain,
userInfo: $userInfo
)''';

@override
List<Object> get props => [
code,
domain,
userInfo,
];
}

@JsonSerializable(createToJson: false, fieldRename: FieldRename.none)
class UserInfo {
@JsonSerializable(fieldRename: FieldRename.none)
class UserInfo extends Equatable {
const UserInfo({
this.description,
this.localizedDescription,
this.localizedFailureReason,
this.underlyingError,
});

@JsonKey(name: 'NSDescription')
final StringContainer? description;

@JsonKey(name: 'NSLocalizedDescription')
final StringContainer? localizedDescription;

Expand All @@ -44,24 +66,64 @@ class UserInfo {
@JsonKey(name: 'NSUnderlyingError')
final NSUnderlyingError? underlyingError;

static const nullInfo = UserInfo();

static UserInfo fromJson(Json json) => _$UserInfoFromJson(json);

Json toJson() => _$UserInfoToJson(this);

@override
String toString() => '''
UserInfo(
description: $description,
localizedDescription: $localizedDescription,
localizedFailureReason: $localizedFailureReason,
underlyingError: $underlyingError
)''';

@override
List<Object?> get props => [
description,
localizedDescription,
localizedFailureReason,
underlyingError,
];
}

@JsonSerializable(createToJson: false, fieldRename: FieldRename.none)
class StringContainer {
const StringContainer({required this.string});
@JsonSerializable(fieldRename: FieldRename.none)
class StringContainer extends Equatable {
const StringContainer(this.string);

final String string;

static StringContainer fromJson(Json json) => _$StringContainerFromJson(json);

Json toJson() => _$StringContainerToJson(this);

@override
String toString() => string;

@override
List<Object> get props => [string];
}

@JsonSerializable(createToJson: false, fieldRename: FieldRename.none)
class NSUnderlyingError {
@JsonSerializable(fieldRename: FieldRename.none)
class NSUnderlyingError extends Equatable {
const NSUnderlyingError({required this.error});

final NSError? error;

static NSUnderlyingError fromJson(Json json) =>
_$NSUnderlyingErrorFromJson(json);

Json toJson() => _$NSUnderlyingErrorToJson(this);

@override
String toString() => '''
NSUnderlyingError(
$error
)''';

@override
List<Object?> get props => [error];
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"error": {
"code": 1,
"domain": "com.apple.CoreDevice.ControlChannelConnectionError",
"userInfo": {
"NSLocalizedDescription": {
"string": "Internal logic error: Connection was invalidated"
},
"NSUnderlyingError": {
"error": {
"code": 0,
"domain": "com.apple.CoreDevice.ControlChannelConnectionError",
"userInfo": {
"NSLocalizedDescription": {
"string": "Transport error"
},
"NSUnderlyingError": {
"error": {
"code": 60,
"domain": "Network.NWError",
"userInfo": {
"NSDescription": {
"string": "Operation timed out"
}
}
}
}
}
}
}
}
},
"info": {
"arguments": [
"devicectl",
"device",
"install",
"app",
"--device",
"00008110-000265A10E92801E",
"/Users/bryanoltman/shorebirdtech/_shorebird/shorebird/bin/cache/previews/3c2ca65a-6401-491a-8942-c9921ba43cec/ios_1.0.0+2_508316.app",
"--json-output",
"/var/folders/64/dj6krpq1093dmx08dy4r1cwh0000gn/T/AKL8Wl/devicectl.out.json"
],
"commandType": "devicectl.device.install.app",
"environment": {
"TERM": "xterm-256color"
},
"jsonVersion": 2,
"outcome": "failed",
"version": "397.24"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -398,9 +398,9 @@ void main() {
deviceListJsonOutput = File(
'$fixturesPath/device_list_success.json',
).readAsStringSync();
// I was not able to get this command to fail, so just use an empty
// string as the output.
installJsonOutput = '';
installJsonOutput = File(
'$fixturesPath/install_failure.json',
).readAsStringSync();
});

test('returns exit code 70 ', () async {
Expand All @@ -413,6 +413,10 @@ void main() {
),
equals(ExitCode.software.code),
);

verify(
() => progress.fail(any(that: contains('Operation timed out'))),
).called(1);
});
});

Expand All @@ -437,6 +441,16 @@ void main() {
),
equals(ExitCode.software.code),
);

verify(
() => progress.fail(
any(
that: contains(
'''Unable to launch dev.shorebird.ios-test because the device was not, or could not be, unlocked.''',
),
),
),
).called(1);
});
});

Expand Down
Loading

0 comments on commit bb1807c

Please sign in to comment.