feat(code_push_protocol): add GetReleasesResponse with createdAt and updatedAt (#1315)

This commit is contained in:
Felix Angelov
2023-09-22 17:01:46 -05:00
committed by GitHub
parent a2711ed15a
commit 2cbda7adf4
20 changed files with 190 additions and 32 deletions
@@ -79,13 +79,15 @@ void main() {
const flutterRevision = '123';
const displayName = 'TestApp';
const releaseVersion = '1.0.0';
const release = Release(
final release = Release(
id: 1,
appId: appId,
version: releaseVersion,
flutterRevision: flutterRevision,
displayName: displayName,
platformStatuses: {},
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
);
final partchArtifactBundle = PatchArtifactBundle(
arch: arch.name,
@@ -435,7 +437,7 @@ void main() {
expect(
() => runWithOverrides(
() => codePushClientWrapper.ensureReleaseIsNotActive(
release: const Release(
release: Release(
id: releaseId,
appId: appId,
version: releaseVersion,
@@ -444,6 +446,8 @@ void main() {
platformStatuses: {
releasePlatform: ReleaseStatus.active,
},
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
),
platform: releasePlatform,
),
@@ -467,13 +471,15 @@ Please bump your version number and try again.''',
await expectLater(
runWithOverrides(
() async => codePushClientWrapper.ensureReleaseIsNotActive(
release: const Release(
release: Release(
id: releaseId,
appId: appId,
version: releaseVersion,
flutterRevision: flutterRevision,
displayName: displayName,
platformStatuses: {},
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
),
platform: releasePlatform,
),
@@ -489,13 +495,15 @@ Please bump your version number and try again.''',
await expectLater(
runWithOverrides(
() async => codePushClientWrapper.ensureReleaseIsNotActive(
release: const Release(
release: Release(
id: releaseId,
appId: appId,
version: releaseVersion,
flutterRevision: flutterRevision,
displayName: displayName,
platformStatuses: {releasePlatform: ReleaseStatus.draft},
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
),
platform: releasePlatform,
),
@@ -66,13 +66,15 @@ void main() {
size: 42,
url: 'https://example.com/release.aar',
);
const release = Release(
final release = Release(
id: 0,
appId: appId,
version: version,
flutterRevision: flutterRevision,
displayName: '1.2.3+1',
platformStatuses: {},
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
);
late AndroidArchiveDiffer archiveDiffer;
@@ -436,7 +438,7 @@ ${release.version}'''),
when(
() => codePushClientWrapper.getReleases(appId: any(named: 'appId')),
).thenAnswer(
(_) async => const [
(_) async => [
Release(
id: 0,
appId: appId,
@@ -444,6 +446,8 @@ ${release.version}'''),
flutterRevision: flutterRevision,
displayName: '1.2.3+1',
platformStatuses: {ReleasePlatform.android: ReleaseStatus.draft},
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
),
],
);
@@ -466,7 +470,7 @@ Please re-run the release command for this version or create a new release.'''),
when(
() => codePushClientWrapper.getReleases(appId: any(named: 'appId')),
).thenAnswer(
(_) async => const [
(_) async => [
Release(
id: 0,
appId: appId,
@@ -474,6 +478,8 @@ Please re-run the release command for this version or create a new release.'''),
flutterRevision: flutterRevision,
displayName: '1.2.3+1',
platformStatuses: {ReleasePlatform.ios: ReleaseStatus.draft},
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
),
],
);
@@ -68,13 +68,15 @@ void main() {
size: 42,
url: 'https://example.com/release.aab',
);
const release = Release(
final release = Release(
id: 0,
appId: appId,
version: version,
flutterRevision: flutterRevision,
displayName: '1.2.3+1',
platformStatuses: {},
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
);
const pubspecYamlContent = '''
name: example
@@ -417,13 +419,15 @@ flutter:
releaseVersion: any(named: 'releaseVersion'),
),
).thenAnswer(
(_) async => const Release(
(_) async => Release(
id: 0,
appId: appId,
version: version,
flutterRevision: flutterRevision,
displayName: '1.2.3+1',
platformStatuses: {releasePlatform: ReleaseStatus.draft},
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
),
);
final tempDir = setUpTempDir();
@@ -447,7 +451,7 @@ Please re-run the release command for this version or create a new release.'''),
appId: any(named: 'appId'),
),
).thenAnswer(
(_) async => const [
(_) async => [
Release(
id: 0,
appId: appId,
@@ -455,6 +459,8 @@ Please re-run the release command for this version or create a new release.'''),
flutterRevision: flutterRevision,
displayName: '1.2.3+1',
platformStatuses: {ReleasePlatform.ios: ReleaseStatus.draft},
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
),
],
);
@@ -105,13 +105,15 @@ flutter:
size: 42,
url: 'https://example.com/release.ipa',
);
const release = Release(
final release = Release(
id: 0,
appId: appId,
version: version,
flutterRevision: flutterRevision,
displayName: '1.2.3+1',
platformStatuses: {ReleasePlatform.ios: ReleaseStatus.active},
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
);
group(PatchIosCommand, () {
@@ -517,13 +519,15 @@ error: exportArchive: No signing certificate "iOS Distribution" found
releaseVersion: any(named: 'releaseVersion'),
),
).thenAnswer(
(_) async => const Release(
(_) async => Release(
id: 0,
appId: appId,
version: version,
flutterRevision: flutterRevision,
displayName: '1.2.3+1',
platformStatuses: {ReleasePlatform.android: ReleaseStatus.active},
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
),
);
final tempDir = setUpTempDir();
@@ -545,13 +549,15 @@ error: exportArchive: No signing certificate "iOS Distribution" found
releaseVersion: any(named: 'releaseVersion'),
),
).thenAnswer(
(_) async => const Release(
(_) async => Release(
id: 0,
appId: appId,
version: version,
flutterRevision: flutterRevision,
displayName: '1.2.3+1',
platformStatuses: {ReleasePlatform.ios: ReleaseStatus.draft},
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
),
);
final tempDir = setUpTempDir();
@@ -576,7 +582,7 @@ Please re-run the release command for this version or create a new release.'''),
releaseVersion: any(named: 'releaseVersion'),
),
).thenAnswer(
(_) async => const Release(
(_) async => Release(
id: 0,
appId: appId,
version: version,
@@ -586,6 +592,8 @@ Please re-run the release command for this version or create a new release.'''),
ReleasePlatform.android: ReleaseStatus.draft,
ReleasePlatform.ios: ReleaseStatus.active,
},
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
),
);
final tempDir = setUpTempDir();
@@ -60,13 +60,15 @@ flutter:
size: 42,
url: 'https://example.com/release.xcframework',
);
const release = Release(
final release = Release(
id: 0,
appId: appId,
version: version,
flutterRevision: flutterRevision,
displayName: '1.2.3+1',
platformStatuses: {},
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
);
late ArgResults argResults;
@@ -400,7 +402,7 @@ ${release.version}'''),
when(
() => codePushClientWrapper.getReleases(appId: any(named: 'appId')),
).thenAnswer(
(_) async => const [
(_) async => [
Release(
id: 0,
appId: appId,
@@ -408,6 +410,8 @@ ${release.version}'''),
flutterRevision: flutterRevision,
displayName: '1.2.3+1',
platformStatuses: {ReleasePlatform.ios: ReleaseStatus.draft},
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
),
],
);
@@ -430,7 +434,7 @@ Please re-run the release command for this version or create a new release.'''),
when(
() => codePushClientWrapper.getReleases(appId: any(named: 'appId')),
).thenAnswer(
(_) async => const [
(_) async => [
Release(
id: 0,
appId: appId,
@@ -438,6 +442,8 @@ Please re-run the release command for this version or create a new release.'''),
flutterRevision: flutterRevision,
displayName: '1.2.3+1',
platformStatuses: {ReleasePlatform.android: ReleaseStatus.draft},
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
),
],
);
@@ -40,13 +40,15 @@ void main() {
const versionName = '1.2.3';
const versionCode = '1';
const version = '$versionName+$versionCode';
const release = Release(
final release = Release(
id: 0,
appId: appId,
version: version,
flutterRevision: flutterRevision,
displayName: '1.2.3+1',
platformStatuses: {},
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
);
const releasePlatform = ReleasePlatform.android;
const buildNumber = '1.0';
@@ -44,13 +44,15 @@ void main() {
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
);
const release = Release(
final release = Release(
id: 0,
appId: appId,
version: version,
flutterRevision: flutterRevision,
displayName: '1.2.3+1',
platformStatuses: {},
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
);
const javaHome = 'test-java-home';
@@ -42,13 +42,15 @@ void main() {
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
);
const release = Release(
final release = Release(
id: 0,
appId: appId,
version: version,
flutterRevision: flutterRevision,
displayName: '1.2.3+1',
platformStatuses: {},
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
);
const infoPlistContent = '''
<?xml version="1.0" encoding="UTF-8"?>
@@ -39,13 +39,15 @@ void main() {
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
);
const release = Release(
final release = Release(
id: 0,
appId: appId,
version: version,
flutterRevision: flutterRevision,
displayName: '1.2.3+1',
platformStatuses: {},
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
);
const pubspecYamlContent = '''
name: example
@@ -464,10 +464,10 @@ class CodePushClient {
throw _parseErrorResponse(response.statusCode, response.body);
}
final releases = json.decode(response.body) as List;
return releases
.map((release) => Release.fromJson(release as Map<String, dynamic>))
.toList();
final decoded = GetReleasesResponse.fromJson(
json.decode(response.body) as Map<String, dynamic>,
);
return decoded.releases;
}
/// Get all release artifacts for a specific [releaseId]
@@ -1125,6 +1125,8 @@ void main() {
flutterRevision: flutterRevision,
displayName: displayName,
platformStatuses: {},
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
),
),
),
@@ -1871,13 +1873,15 @@ void main() {
test('completes when request succeeds (empty)', () async {
when(() => httpClient.send(any())).thenAnswer(
(_) async => http.StreamedResponse(
Stream.value(utf8.encode(json.encode([]))),
Stream.value(
utf8.encode(json.encode(GetReleasesResponse(releases: []))),
),
HttpStatus.ok,
),
);
final apps = await codePushClient.getReleases(appId: appId);
expect(apps, isEmpty);
final releases = await codePushClient.getReleases(appId: appId);
expect(releases, isEmpty);
});
test('completes when request succeeds (populated)', () async {
@@ -1889,6 +1893,8 @@ void main() {
flutterRevision: flutterRevision,
displayName: 'v1.0.0',
platformStatuses: {ReleasePlatform.android: ReleaseStatus.draft},
createdAt: DateTime(2022),
updatedAt: DateTime(2023),
),
Release(
id: 1,
@@ -1897,12 +1903,16 @@ void main() {
flutterRevision: flutterRevision,
displayName: 'v1.0.1',
platformStatuses: {},
createdAt: DateTime(2022),
updatedAt: DateTime(2023),
),
];
when(() => httpClient.send(any())).thenAnswer(
(_) async => http.StreamedResponse(
Stream.value(utf8.encode(json.encode(expected))),
Stream.value(
utf8.encode(json.encode(GetReleasesResponse(releases: expected))),
),
HttpStatus.ok,
),
);
@@ -0,0 +1 @@
export 'get_releases_response.dart';
@@ -0,0 +1,23 @@
import 'package:json_annotation/json_annotation.dart';
import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart';
part 'get_releases_response.g.dart';
/// {@template get_releases_response}
/// The response body for GET /api/v1/apps/:id/releases
/// {@endtemplate}
@JsonSerializable()
class GetReleasesResponse {
/// {@macro get_releases_response}
const GetReleasesResponse({required this.releases});
/// Converts a Map<String, dynamic> to a [GetReleasesResponse].
factory GetReleasesResponse.fromJson(Map<String, dynamic> json) =>
_$GetReleasesResponseFromJson(json);
/// Converts a [GetReleasesResponse] to a Map<String, dynamic>.
Json toJson() => _$GetReleasesResponseToJson(this);
/// The list of releases for the app.
final List<Release> releases;
}
@@ -0,0 +1,31 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: implicit_dynamic_parameter, require_trailing_commas, cast_nullable_to_non_nullable, lines_longer_than_80_chars
part of 'get_releases_response.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
GetReleasesResponse _$GetReleasesResponseFromJson(Map<String, dynamic> json) =>
$checkedCreate(
'GetReleasesResponse',
json,
($checkedConvert) {
final val = GetReleasesResponse(
releases: $checkedConvert(
'releases',
(v) => (v as List<dynamic>)
.map((e) => Release.fromJson(e as Map<String, dynamic>))
.toList()),
);
return val;
},
);
Map<String, dynamic> _$GetReleasesResponseToJson(
GetReleasesResponse instance) =>
<String, dynamic>{
'releases': instance.releases.map((e) => e.toJson()).toList(),
};
@@ -14,6 +14,7 @@ export 'get_apps/get_apps.dart';
export 'get_overages/get_overages.dart';
export 'get_release_artifacts/get_release_artifacts.dart';
export 'get_release_patches/get_release_patches.dart';
export 'get_releases/get_releases.dart';
export 'get_usage/get_usage.dart';
export 'promote_patch/promote_patch.dart';
export 'update_overages/update_overages.dart';
@@ -17,6 +17,8 @@ class Release {
required this.flutterRevision,
required this.displayName,
required this.platformStatuses,
required this.createdAt,
required this.updatedAt,
});
/// Converts a Map<String, dynamic> to a [Release]
@@ -43,4 +45,10 @@ class Release {
/// The status of the release for each platform.
final Map<ReleasePlatform, ReleaseStatus> platformStatuses;
/// The date and time the release was created.
final DateTime createdAt;
/// The date and time the release was last updated.
final DateTime updatedAt;
}
@@ -25,6 +25,10 @@ Release _$ReleaseFromJson(Map<String, dynamic> json) => $checkedCreate(
(k, e) => MapEntry($enumDecode(_$ReleasePlatformEnumMap, k),
$enumDecode(_$ReleaseStatusEnumMap, e)),
)),
createdAt:
$checkedConvert('created_at', (v) => DateTime.parse(v as String)),
updatedAt:
$checkedConvert('updated_at', (v) => DateTime.parse(v as String)),
);
return val;
},
@@ -32,7 +36,9 @@ Release _$ReleaseFromJson(Map<String, dynamic> json) => $checkedCreate(
'appId': 'app_id',
'flutterRevision': 'flutter_revision',
'displayName': 'display_name',
'platformStatuses': 'platform_statuses'
'platformStatuses': 'platform_statuses',
'createdAt': 'created_at',
'updatedAt': 'updated_at'
},
);
@@ -44,6 +50,8 @@ Map<String, dynamic> _$ReleaseToJson(Release instance) => <String, dynamic>{
'display_name': instance.displayName,
'platform_statuses': instance.platformStatuses.map((k, e) =>
MapEntry(_$ReleasePlatformEnumMap[k]!, _$ReleaseStatusEnumMap[e]!)),
'created_at': instance.createdAt.toIso8601String(),
'updated_at': instance.updatedAt.toIso8601String(),
};
const _$ReleaseStatusEnumMap = {
@@ -4,7 +4,7 @@ import 'package:test/test.dart';
void main() {
group(CreateReleaseResponse, () {
test('can be (de)serialized', () {
const response = CreateReleaseResponse(
final response = CreateReleaseResponse(
release: Release(
id: 0,
appId: 'test-app-id',
@@ -12,6 +12,8 @@ void main() {
displayName: 'v1.0.0',
flutterRevision: 'flutter-revision',
platformStatuses: {},
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
),
);
expect(
@@ -0,0 +1,30 @@
import 'package:shorebird_code_push_protocol/shorebird_code_push_protocol.dart';
import 'package:test/test.dart';
void main() {
group(GetReleasesResponse, () {
test('can be (de)serialized', () {
final response = GetReleasesResponse(
releases: [
Release(
id: 0,
displayName: 'v1.0.0',
appId: 'test-app-id',
flutterRevision: 'flutter-revision',
version: '1.0.0',
platformStatuses: {
ReleasePlatform.ios: ReleaseStatus.draft,
ReleasePlatform.android: ReleaseStatus.active,
},
createdAt: DateTime(2022),
updatedAt: DateTime(2023),
)
],
);
expect(
GetReleasesResponse.fromJson(response.toJson()).toJson(),
equals(response.toJson()),
);
});
});
}
@@ -4,13 +4,15 @@ import 'package:test/test.dart';
void main() {
group(Release, () {
test('can be (de)serialized', () {
const release = Release(
final release = Release(
id: 1,
appId: 'app-id',
version: '1.0.0',
flutterRevision: '83305b5088e6fe327fb3334a73ff190828d85713',
displayName: 'v1.0.0',
platformStatuses: {ReleasePlatform.android: ReleaseStatus.active},
createdAt: DateTime(2023),
updatedAt: DateTime(2023),
);
expect(
Release.fromJson(release.toJson()).toJson(),