feat: support patch_verification config in shorebird.yaml (#3463)

This commit is contained in:
Eric Seidel
2026-01-16 16:57:03 -07:00
committed by GitHub
parent 87181c4e5e
commit 825f3596d9
4 changed files with 97 additions and 9 deletions
+1 -1
View File
@@ -1 +1 @@
55c197eb61ef2219a709002c39ffa445b05600f8
8f934ceac62ce289fda9492b0dfc846ecb214fc6
@@ -2,6 +2,17 @@ import 'package:json_annotation/json_annotation.dart';
part 'shorebird_yaml.g.dart';
/// The patch verification mode for the app.
@JsonEnum(fieldRename: FieldRename.snake)
enum PatchVerification {
/// Verify the patch signature and hash before installing and loading.
strict,
/// Verify the patch signature and hash before installing, but not when
/// loading from cache.
installOnly,
}
/// {@template shorebird_yaml}
/// A Shorebird configuration file which contains metadata about the app.
/// {@endtemplate}
@@ -13,6 +24,7 @@ class ShorebirdYaml {
this.flavors,
this.baseUrl,
this.autoUpdate,
this.patchVerification,
});
/// Creates a [ShorebirdYaml] from a JSON map.
@@ -46,6 +58,9 @@ class ShorebirdYaml {
/// Whether or not to automatically update the app.
final bool? autoUpdate;
/// The patch verification mode for the app.
final PatchVerification? patchVerification;
}
/// Extension on [ShorebirdYaml] to get the app id for a specific flavor.
@@ -14,7 +14,13 @@ ShorebirdYaml _$ShorebirdYamlFromJson(Map json) => $checkedCreate(
($checkedConvert) {
$checkKeys(
json,
allowedKeys: const ['app_id', 'flavors', 'base_url', 'auto_update'],
allowedKeys: const [
'app_id',
'flavors',
'base_url',
'auto_update',
'patch_verification',
],
);
final val = ShorebirdYaml(
appId: $checkedConvert('app_id', (v) => v as String),
@@ -24,6 +30,10 @@ ShorebirdYaml _$ShorebirdYamlFromJson(Map json) => $checkedCreate(
),
baseUrl: $checkedConvert('base_url', (v) => v as String?),
autoUpdate: $checkedConvert('auto_update', (v) => v as bool?),
patchVerification: $checkedConvert(
'patch_verification',
(v) => $enumDecodeNullable(_$PatchVerificationEnumMap, v),
),
);
return val;
},
@@ -31,13 +41,21 @@ ShorebirdYaml _$ShorebirdYamlFromJson(Map json) => $checkedCreate(
'appId': 'app_id',
'baseUrl': 'base_url',
'autoUpdate': 'auto_update',
'patchVerification': 'patch_verification',
},
);
Map<String, dynamic> _$ShorebirdYamlToJson(ShorebirdYaml instance) =>
<String, dynamic>{
'app_id': instance.appId,
'flavors': instance.flavors,
'base_url': instance.baseUrl,
'auto_update': instance.autoUpdate,
};
Map<String, dynamic> _$ShorebirdYamlToJson(
ShorebirdYaml instance,
) => <String, dynamic>{
'app_id': instance.appId,
'flavors': instance.flavors,
'base_url': instance.baseUrl,
'auto_update': instance.autoUpdate,
'patch_verification': _$PatchVerificationEnumMap[instance.patchVerification],
};
const _$PatchVerificationEnumMap = {
PatchVerification.strict: 'strict',
PatchVerification.installOnly: 'install_only',
};
@@ -67,6 +67,61 @@ auto_update: true
expect(shorebirdYaml.autoUpdate, isTrue);
});
test('can be deserialized without patch_verification', () {
const yaml = '''
app_id: test_app_id
''';
final shorebirdYaml = checkedYamlDecode(
yaml,
(m) => ShorebirdYaml.fromJson(m!),
);
expect(shorebirdYaml.appId, 'test_app_id');
expect(shorebirdYaml.patchVerification, isNull);
});
test('can be deserialized with patch_verification: strict', () {
const yaml = '''
app_id: test_app_id
patch_verification: strict
''';
final shorebirdYaml = checkedYamlDecode(
yaml,
(m) => ShorebirdYaml.fromJson(m!),
);
expect(shorebirdYaml.appId, 'test_app_id');
expect(shorebirdYaml.patchVerification, PatchVerification.strict);
});
test('can be deserialized with patch_verification: install_only', () {
const yaml = '''
app_id: test_app_id
patch_verification: install_only
''';
final shorebirdYaml = checkedYamlDecode(
yaml,
(m) => ShorebirdYaml.fromJson(m!),
);
expect(shorebirdYaml.appId, 'test_app_id');
expect(shorebirdYaml.patchVerification, PatchVerification.installOnly);
});
test('throws when patch_verification has invalid value', () {
const yaml = '''
app_id: test_app_id
patch_verification: invalid_value
''';
expect(
() => checkedYamlDecode(yaml, (m) => ShorebirdYaml.fromJson(m!)),
throwsA(
isA<ParsedYamlException>().having(
(e) => e.message,
'message',
contains('patch_verification'),
),
),
);
});
group('AppIdExtension', () {
test('getAppId returns base app id when no flavor is provided', () {
const shorebirdYaml = ShorebirdYaml(appId: 'test_app_id');