fix(shorebird_cli): handle multi-dimensional flavors on android (#1960)
Co-authored-by: Felix Angelov <felix@shorebird.dev> Co-authored-by: Bryan Oltman <bryan@shorebird.dev>
This commit is contained in:
@@ -18,6 +18,7 @@ import 'package:shorebird_cli/src/patch_diff_checker.dart';
|
||||
import 'package:shorebird_cli/src/platform.dart';
|
||||
import 'package:shorebird_cli/src/platform/platform.dart';
|
||||
import 'package:shorebird_cli/src/pubspec_editor.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_android_artifacts.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_artifacts.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_env.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_flutter.dart';
|
||||
@@ -55,6 +56,7 @@ Future<void> main(List<String> args) async {
|
||||
platformRef,
|
||||
processRef,
|
||||
pubspecEditorRef,
|
||||
shorebirdAndroidArtifactsRef,
|
||||
shorebirdArtifactsRef,
|
||||
shorebirdEnvRef,
|
||||
shorebirdFlutterRef,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:scoped/scoped.dart';
|
||||
import 'package:shorebird_cli/src/code_push_client_wrapper.dart';
|
||||
import 'package:shorebird_cli/src/command.dart';
|
||||
@@ -12,6 +11,7 @@ import 'package:shorebird_cli/src/extensions/arg_results.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/platform.dart';
|
||||
import 'package:shorebird_cli/src/platform/platform.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_android_artifacts.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_build_mixin.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_env.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_flutter.dart';
|
||||
@@ -195,43 +195,35 @@ Use `shorebird flutter versions list` to list available versions.
|
||||
final appId = shorebirdYaml.getAppId(flavor: flavor);
|
||||
final app = await codePushClientWrapper.getApp(appId: appId);
|
||||
|
||||
final bundleDirPath = p.join(
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
'bundle',
|
||||
);
|
||||
|
||||
final apkDirPath = p.join(
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
'apk',
|
||||
);
|
||||
final bundlePath = flavor != null
|
||||
? p.join(
|
||||
bundleDirPath,
|
||||
'${flavor}Release',
|
||||
'app-$flavor-release.aab',
|
||||
)
|
||||
: p.join(bundleDirPath, 'release', 'app-release.aab');
|
||||
final apkPath = flavor != null
|
||||
? p.join(
|
||||
apkDirPath,
|
||||
flavor,
|
||||
'release',
|
||||
'app-$flavor-release.apk',
|
||||
)
|
||||
: p.join(apkDirPath, 'release', 'app-release.apk');
|
||||
late final File apkFile;
|
||||
final File aabFile;
|
||||
try {
|
||||
aabFile = shorebirdAndroidArtifacts.findAab(
|
||||
project: projectRoot,
|
||||
flavor: flavor,
|
||||
);
|
||||
if (generateApk) {
|
||||
apkFile = shorebirdAndroidArtifacts.findApk(
|
||||
project: projectRoot,
|
||||
flavor: flavor,
|
||||
);
|
||||
}
|
||||
} on ArtifactNotFoundException catch (error) {
|
||||
logger.err(error.toString());
|
||||
return ExitCode.software.code;
|
||||
} on MultipleArtifactsFoundException catch (error) {
|
||||
logger.err(error.toString());
|
||||
return ExitCode.software.code;
|
||||
}
|
||||
|
||||
final String releaseVersion;
|
||||
final detectReleaseVersionProgress = logger.progress(
|
||||
'Detecting release version',
|
||||
);
|
||||
try {
|
||||
releaseVersion = await extractReleaseVersionFromAppBundle(bundlePath);
|
||||
releaseVersion = await extractReleaseVersionFromAppBundle(
|
||||
aabFile.path,
|
||||
);
|
||||
detectReleaseVersionProgress.complete();
|
||||
} catch (error) {
|
||||
detectReleaseVersionProgress.fail('$error');
|
||||
@@ -308,7 +300,7 @@ ${summary.join('\n')}
|
||||
appId: app.appId,
|
||||
releaseId: release.id,
|
||||
projectRoot: projectRoot.path,
|
||||
aabPath: bundlePath,
|
||||
aabPath: aabFile.path,
|
||||
platform: releasePlatform,
|
||||
architectures: architectures,
|
||||
flavor: flavor,
|
||||
@@ -338,7 +330,7 @@ ${summary.join('\n')}
|
||||
? '''
|
||||
|
||||
Or distribute the apk:
|
||||
${lightCyan.wrap(apkPath)}
|
||||
${lightCyan.wrap(apkFile.path)}
|
||||
'''
|
||||
: '';
|
||||
|
||||
@@ -347,7 +339,7 @@ ${lightCyan.wrap(apkPath)}
|
||||
..info('''
|
||||
|
||||
Your next step is to upload the app bundle to the Play Store:
|
||||
${lightCyan.wrap(bundlePath)}
|
||||
${lightCyan.wrap(aabFile.path)}
|
||||
$apkText
|
||||
For information on uploading to the Play Store, see:
|
||||
${link(uri: Uri.parse('https://support.google.com/googleplay/android-developer/answer/9859152?hl=en'))}
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:scoped/scoped.dart';
|
||||
import 'package:shorebird_cli/src/command.dart';
|
||||
|
||||
/// Thrown when multiple artifacts are found in the build directory.
|
||||
class MultipleArtifactsFoundException implements Exception {
|
||||
MultipleArtifactsFoundException({
|
||||
required this.buildDir,
|
||||
required this.foundArtifacts,
|
||||
});
|
||||
|
||||
final String buildDir;
|
||||
final List<FileSystemEntity> foundArtifacts;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Multiple artifacts found in $buildDir: '
|
||||
'${foundArtifacts.map((e) => e.path)}';
|
||||
}
|
||||
}
|
||||
|
||||
/// Thrown when no artifact is found in the build directory.
|
||||
class ArtifactNotFoundException implements Exception {
|
||||
ArtifactNotFoundException({
|
||||
required this.artifactName,
|
||||
required this.buildDir,
|
||||
});
|
||||
|
||||
final String artifactName;
|
||||
final String buildDir;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Artifact $artifactName not found in $buildDir';
|
||||
}
|
||||
}
|
||||
|
||||
/// When building android artifacts, gradlew names these artifacts in an
|
||||
/// inconsistent way.
|
||||
///
|
||||
/// Example:
|
||||
///
|
||||
/// ## AABs
|
||||
/// Without flavors
|
||||
/// ...bundle/release/app-release.aab
|
||||
///
|
||||
/// With flavors
|
||||
/// ...bundle/flavor/app-flavor-release.aab
|
||||
///
|
||||
/// With multi dimensional flavors
|
||||
/// ...bundle/fullFlavorCamelCase/app-flavor1-flavor2-release.aab
|
||||
///
|
||||
/// The pattern follows for APKs.
|
||||
///
|
||||
/// The only thing that is consistent is the artifactId which is the name of the
|
||||
/// artifact will follow always the same order of name of the flavors.
|
||||
///
|
||||
/// To get around this, we create an identifier for the artifact
|
||||
/// that is the file name lowercased and without any non-word characters.
|
||||
/// This allows us to reliably find the artifact generated by the
|
||||
/// flutter build command.
|
||||
extension on String {
|
||||
String get artifactId => replaceAll(RegExp(r'\W'), '').toLowerCase();
|
||||
}
|
||||
|
||||
final shorebirdAndroidArtifactsRef = create(ShorebirdAndroidArtifacts.new);
|
||||
|
||||
ShorebirdAndroidArtifacts get shorebirdAndroidArtifacts =>
|
||||
read(shorebirdAndroidArtifactsRef);
|
||||
|
||||
/// Mixin on [ShorebirdCommand] which exposes methods
|
||||
// to find the artifacts generated for android
|
||||
class ShorebirdAndroidArtifacts {
|
||||
/// Find the artifact in the build directory.
|
||||
File _findArtifact({
|
||||
required String artifactName,
|
||||
required Directory directory,
|
||||
}) {
|
||||
// Remove all non characters and digits from the artifact name.
|
||||
final artifactId = artifactName.artifactId;
|
||||
|
||||
if (!directory.existsSync()) {
|
||||
throw ArtifactNotFoundException(
|
||||
artifactName: artifactName,
|
||||
buildDir: directory.path,
|
||||
);
|
||||
}
|
||||
|
||||
final allFiles = directory.listSync();
|
||||
final artifactCandidates = allFiles.whereType<File>().where((file) {
|
||||
final fileName = p.basename(file.path);
|
||||
return fileName.artifactId == artifactId;
|
||||
}).toList();
|
||||
|
||||
if (artifactCandidates.isEmpty) {
|
||||
throw ArtifactNotFoundException(
|
||||
artifactName: artifactName,
|
||||
buildDir: directory.path,
|
||||
);
|
||||
}
|
||||
|
||||
if (artifactCandidates.length > 1) {
|
||||
throw MultipleArtifactsFoundException(
|
||||
buildDir: directory.path,
|
||||
foundArtifacts: artifactCandidates,
|
||||
);
|
||||
}
|
||||
|
||||
return artifactCandidates.first;
|
||||
}
|
||||
|
||||
/// Find the app bundle in the provided [project] [Directory].
|
||||
File findAab({
|
||||
required Directory project,
|
||||
required String? flavor,
|
||||
}) {
|
||||
final buildDir = p.join(
|
||||
project.path,
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
'bundle',
|
||||
flavor != null ? '${flavor}Release' : 'release',
|
||||
);
|
||||
|
||||
final artifactName =
|
||||
flavor == null ? 'app-release.aab' : 'app-$flavor-release.aab';
|
||||
|
||||
return _findArtifact(
|
||||
directory: Directory(buildDir),
|
||||
artifactName: artifactName,
|
||||
);
|
||||
}
|
||||
|
||||
/// Find the apk in the provided [project] [Directory].
|
||||
File findApk({
|
||||
required Directory project,
|
||||
required String? flavor,
|
||||
}) {
|
||||
final buildDir = p.join(
|
||||
project.path,
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
'flutter-apk',
|
||||
);
|
||||
|
||||
final artifactName =
|
||||
flavor == null ? 'app-release.apk' : 'app-$flavor-release.apk';
|
||||
|
||||
return _findArtifact(
|
||||
directory: Directory(buildDir),
|
||||
artifactName: artifactName,
|
||||
);
|
||||
}
|
||||
}
|
||||
+117
-18
@@ -18,6 +18,7 @@ import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/os/operating_system_interface.dart';
|
||||
import 'package:shorebird_cli/src/platform.dart';
|
||||
import 'package:shorebird_cli/src/platform/platform.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_android_artifacts.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_env.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_flutter.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_process.dart';
|
||||
@@ -83,8 +84,12 @@ void main() {
|
||||
late ShorebirdEnv shorebirdEnv;
|
||||
late ShorebirdFlutter shorebirdFlutter;
|
||||
late ShorebirdValidator shorebirdValidator;
|
||||
late ShorebirdAndroidArtifacts shorebirdAndroidArtifacts;
|
||||
late ReleaseAndroidCommand command;
|
||||
|
||||
late String aabPath;
|
||||
late String apkPath;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
return runScoped(
|
||||
body,
|
||||
@@ -102,6 +107,8 @@ void main() {
|
||||
shorebirdEnvRef.overrideWith(() => shorebirdEnv),
|
||||
shorebirdFlutterRef.overrideWith(() => shorebirdFlutter),
|
||||
shorebirdValidatorRef.overrideWith(() => shorebirdValidator),
|
||||
shorebirdAndroidArtifactsRef
|
||||
.overrideWith(() => shorebirdAndroidArtifacts),
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -111,6 +118,7 @@ void main() {
|
||||
registerFallbackValue(ReleaseStatus.draft);
|
||||
registerFallbackValue(FakeRelease());
|
||||
registerFallbackValue(FakeShorebirdProcess());
|
||||
registerFallbackValue(Directory(''));
|
||||
});
|
||||
|
||||
setUp(() {
|
||||
@@ -134,6 +142,28 @@ void main() {
|
||||
shorebirdEnv = MockShorebirdEnv();
|
||||
shorebirdFlutter = MockShorebirdFlutter();
|
||||
shorebirdValidator = MockShorebirdValidator();
|
||||
shorebirdAndroidArtifacts = ShorebirdAndroidArtifacts();
|
||||
|
||||
aabPath = p.join(
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
'bundle',
|
||||
'release',
|
||||
'app-release.aab',
|
||||
);
|
||||
apkPath = p.join(
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
'flutter-apk',
|
||||
'app-release.apk',
|
||||
);
|
||||
|
||||
File(apkPath).createSync(recursive: true);
|
||||
File(aabPath).createSync(recursive: true);
|
||||
|
||||
when(() => shorebirdEnv.getShorebirdYaml()).thenReturn(shorebirdYaml);
|
||||
when(
|
||||
@@ -555,24 +585,6 @@ ${link(uri: Uri.parse('https://support.google.com/googleplay/android-developer/a
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
verify(() => logger.success('\n✅ Published Release $version!')).called(1);
|
||||
// Verify info message does include apk instructions.
|
||||
final aabPath = p.join(
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
'bundle',
|
||||
'release',
|
||||
'app-release.aab',
|
||||
);
|
||||
final apkPath = p.join(
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
'apk',
|
||||
'release',
|
||||
'app-release.apk',
|
||||
);
|
||||
verify(
|
||||
() => logger.info('''
|
||||
|
||||
@@ -760,6 +772,26 @@ Either run `flutter pub get` manually, or follow the steps in ${link(uri: Uri.pa
|
||||
test(
|
||||
'succeeds when release is successful '
|
||||
'with flavors and target', () async {
|
||||
aabPath = p.join(
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
'bundle',
|
||||
'developmentRelease',
|
||||
'app-development-release.aab',
|
||||
);
|
||||
apkPath = p.join(
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
'flutter-apk',
|
||||
'app-development-release.apk',
|
||||
);
|
||||
|
||||
File(apkPath).createSync(recursive: true);
|
||||
File(aabPath).createSync(recursive: true);
|
||||
const flavor = 'development';
|
||||
final target = p.join('lib', 'main_development.dart');
|
||||
when(() => argResults['flavor']).thenReturn(flavor);
|
||||
@@ -888,5 +920,72 @@ Note: ${lightCyan.wrap('shorebird patch android --flavor=$flavor --target=$targe
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verifyNever(() => logger.confirm(any()));
|
||||
});
|
||||
|
||||
test('errors when the app bundle cannot be found', () async {
|
||||
shorebirdAndroidArtifacts = MockShorebirdAndroidArtifacts();
|
||||
when(
|
||||
() => shorebirdAndroidArtifacts.findAab(
|
||||
project: any(named: 'project'),
|
||||
flavor: any(named: 'flavor'),
|
||||
),
|
||||
).thenThrow(
|
||||
ArtifactNotFoundException(
|
||||
artifactName: 'app-release.aab',
|
||||
buildDir: 'buildDir',
|
||||
),
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
verify(
|
||||
() => logger.err('Artifact app-release.aab not found in buildDir'),
|
||||
).called(1);
|
||||
expect(exitCode, ExitCode.software.code);
|
||||
});
|
||||
|
||||
test('errors when the apk cannot be found', () async {
|
||||
shorebirdAndroidArtifacts = MockShorebirdAndroidArtifacts();
|
||||
when(() => argResults['artifact']).thenReturn('apk');
|
||||
when(
|
||||
() => shorebirdAndroidArtifacts.findAab(
|
||||
project: any(named: 'project'),
|
||||
flavor: any(named: 'flavor'),
|
||||
),
|
||||
).thenReturn(File('app-release.aab'));
|
||||
when(
|
||||
() => shorebirdAndroidArtifacts.findApk(
|
||||
project: any(named: 'project'),
|
||||
flavor: any(named: 'flavor'),
|
||||
),
|
||||
).thenThrow(
|
||||
ArtifactNotFoundException(
|
||||
artifactName: 'app-release.apk',
|
||||
buildDir: 'buildDir',
|
||||
),
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
verify(
|
||||
() => logger.err('Artifact app-release.apk not found in buildDir'),
|
||||
).called(1);
|
||||
expect(exitCode, ExitCode.software.code);
|
||||
});
|
||||
|
||||
test('errors when multiple artifacts are found', () async {
|
||||
shorebirdAndroidArtifacts = MockShorebirdAndroidArtifacts();
|
||||
when(
|
||||
() => shorebirdAndroidArtifacts.findAab(
|
||||
project: any(named: 'project'),
|
||||
flavor: any(named: 'flavor'),
|
||||
),
|
||||
).thenThrow(
|
||||
MultipleArtifactsFoundException(
|
||||
foundArtifacts: [File('a'), File('b')],
|
||||
buildDir: 'buildDir',
|
||||
),
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
verify(
|
||||
() => logger.err('Multiple artifacts found in buildDir: (a, b)'),
|
||||
).called(1);
|
||||
expect(exitCode, ExitCode.software.code);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import 'package:shorebird_cli/src/os/os.dart';
|
||||
import 'package:shorebird_cli/src/patch_diff_checker.dart';
|
||||
import 'package:shorebird_cli/src/platform/platform.dart';
|
||||
import 'package:shorebird_cli/src/pubspec_editor.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_android_artifacts.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_artifacts.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_env.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_flutter.dart';
|
||||
@@ -124,6 +125,9 @@ class MockRelease extends Mock implements Release {}
|
||||
|
||||
class MockReleaseArtifact extends Mock implements ReleaseArtifact {}
|
||||
|
||||
class MockShorebirdAndroidArtifacts extends Mock
|
||||
implements ShorebirdAndroidArtifacts {}
|
||||
|
||||
class MockShorebirdArtifacts extends Mock implements ShorebirdArtifacts {}
|
||||
|
||||
class MockShorebirdEnv extends Mock implements ShorebirdEnv {}
|
||||
|
||||
@@ -0,0 +1,354 @@
|
||||
import 'package:path/path.dart' as path;
|
||||
import 'package:shorebird_cli/src/shorebird_android_artifacts.dart';
|
||||
import 'package:shorebird_cli/src/third_party/flutter_tools/lib/flutter_tools.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group(ShorebirdAndroidArtifacts, () {
|
||||
late Directory project;
|
||||
late ShorebirdAndroidArtifacts shorebirdAndroidArtifacts;
|
||||
|
||||
setUp(() {
|
||||
project = Directory.systemTemp.createTempSync();
|
||||
shorebirdAndroidArtifacts = ShorebirdAndroidArtifacts();
|
||||
});
|
||||
|
||||
group('when no build folder exists', () {
|
||||
test('throws ArtifactNotFoundException for aabs', () {
|
||||
expect(
|
||||
() => shorebirdAndroidArtifacts.findAab(
|
||||
project: project,
|
||||
flavor: null,
|
||||
),
|
||||
throwsA(isA<ArtifactNotFoundException>()),
|
||||
);
|
||||
});
|
||||
|
||||
test('throws ArtifactNotFoundException for apks', () {
|
||||
expect(
|
||||
() => shorebirdAndroidArtifacts.findApk(
|
||||
project: project,
|
||||
flavor: null,
|
||||
),
|
||||
throwsA(isA<ArtifactNotFoundException>()),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('when build folder exists but not the file', () {
|
||||
test('throws ArtifactNotFoundException for aabs', () {
|
||||
Directory(
|
||||
path.join(
|
||||
project.path,
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
'bundle',
|
||||
'release',
|
||||
),
|
||||
).createSync(recursive: true);
|
||||
expect(
|
||||
() => shorebirdAndroidArtifacts.findAab(
|
||||
project: project,
|
||||
flavor: null,
|
||||
),
|
||||
throwsA(isA<ArtifactNotFoundException>()),
|
||||
);
|
||||
});
|
||||
|
||||
test('throws ArtifactNotFoundException for apks', () {
|
||||
Directory(
|
||||
path.join(
|
||||
project.path,
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
'flutter-apk',
|
||||
),
|
||||
).createSync(recursive: true);
|
||||
expect(
|
||||
() => shorebirdAndroidArtifacts.findApk(
|
||||
project: project,
|
||||
flavor: null,
|
||||
),
|
||||
throwsA(isA<ArtifactNotFoundException>()),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('when using no flavors', () {
|
||||
test('finds the app bundle flavors', () {
|
||||
final artifactPath = path.join(
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
'bundle',
|
||||
'release',
|
||||
'app-release.aab',
|
||||
);
|
||||
final artifact = File(
|
||||
path.join(project.path, artifactPath),
|
||||
)..createSync(recursive: true);
|
||||
|
||||
expect(
|
||||
shorebirdAndroidArtifacts
|
||||
.findAab(
|
||||
project: project,
|
||||
flavor: null,
|
||||
)
|
||||
.path,
|
||||
equals(artifact.path),
|
||||
);
|
||||
});
|
||||
|
||||
test('finds the apk', () {
|
||||
final artifactPath = path.join(
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
'flutter-apk',
|
||||
'app-release.apk',
|
||||
);
|
||||
final artifact = File(
|
||||
path.join(project.path, artifactPath),
|
||||
)..createSync(recursive: true);
|
||||
|
||||
expect(
|
||||
shorebirdAndroidArtifacts
|
||||
.findApk(
|
||||
project: project,
|
||||
flavor: null,
|
||||
)
|
||||
.path,
|
||||
equals(artifact.path),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('when using single-dimensional flavor', () {
|
||||
test('finds the app bundle', () {
|
||||
final artifactPath = path.join(
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
'bundle',
|
||||
'internalRelease',
|
||||
'app-internal-release.aab',
|
||||
);
|
||||
final artifact = File(
|
||||
path.join(project.path, artifactPath),
|
||||
)..createSync(recursive: true);
|
||||
|
||||
const flavor = 'internal';
|
||||
|
||||
expect(
|
||||
shorebirdAndroidArtifacts
|
||||
.findAab(
|
||||
project: project,
|
||||
flavor: flavor,
|
||||
)
|
||||
.path,
|
||||
equals(artifact.path),
|
||||
);
|
||||
});
|
||||
|
||||
test('finds the apk', () {
|
||||
final artifactPath = path.join(
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
'flutter-apk',
|
||||
'app-internal-release.apk',
|
||||
);
|
||||
final artifact = File(
|
||||
path.join(project.path, artifactPath),
|
||||
)..createSync(recursive: true);
|
||||
|
||||
const flavor = 'internal';
|
||||
|
||||
expect(
|
||||
shorebirdAndroidArtifacts
|
||||
.findApk(
|
||||
project: project,
|
||||
flavor: flavor,
|
||||
)
|
||||
.path,
|
||||
equals(artifact.path),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('when using multi-dimensional flavors', () {
|
||||
test('finds the app bundle', () {
|
||||
final artifactPath = path.join(
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
'bundle',
|
||||
'stableGlobalRelease',
|
||||
'app-stable-global-release.aab',
|
||||
);
|
||||
final artifact = File(
|
||||
path.join(project.path, artifactPath),
|
||||
)..createSync(recursive: true);
|
||||
|
||||
const flavor = 'stableGlobal';
|
||||
|
||||
expect(
|
||||
shorebirdAndroidArtifacts
|
||||
.findAab(
|
||||
project: project,
|
||||
flavor: flavor,
|
||||
)
|
||||
.path,
|
||||
equals(artifact.path),
|
||||
);
|
||||
});
|
||||
|
||||
test('finds the apk', () {
|
||||
final artifactPath = path.join(
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
'flutter-apk',
|
||||
'app-stableglobal-release.apk',
|
||||
);
|
||||
final artifact = File(
|
||||
path.join(project.path, artifactPath),
|
||||
)..createSync(recursive: true);
|
||||
|
||||
const flavor = 'stableGlobal';
|
||||
|
||||
expect(
|
||||
shorebirdAndroidArtifacts
|
||||
.findApk(
|
||||
project: project,
|
||||
flavor: flavor,
|
||||
)
|
||||
.path,
|
||||
equals(artifact.path),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('when using multi-dimensional flavors and multi-word flavor name',
|
||||
() {
|
||||
test('finds the app bundle', () {
|
||||
final artifactPath = path.join(
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
'bundle',
|
||||
'stablePlayStoreRelease',
|
||||
'app-stable-playStore-release.aab',
|
||||
);
|
||||
final artifact = File(
|
||||
path.join(project.path, artifactPath),
|
||||
)..createSync(recursive: true);
|
||||
|
||||
const flavor = 'stablePlayStore';
|
||||
|
||||
expect(
|
||||
shorebirdAndroidArtifacts
|
||||
.findAab(
|
||||
project: project,
|
||||
flavor: flavor,
|
||||
)
|
||||
.path,
|
||||
equals(artifact.path),
|
||||
);
|
||||
});
|
||||
|
||||
test('finds the apk', () {
|
||||
final artifactPath = path.join(
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
'flutter-apk',
|
||||
'app-stableplaystore-release.apk',
|
||||
);
|
||||
final artifact = File(
|
||||
path.join(project.path, artifactPath),
|
||||
)..createSync(recursive: true);
|
||||
|
||||
const flavor = 'stablePlayStore';
|
||||
|
||||
expect(
|
||||
shorebirdAndroidArtifacts
|
||||
.findApk(
|
||||
project: project,
|
||||
flavor: flavor,
|
||||
)
|
||||
.path,
|
||||
equals(artifact.path),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('when multiple files are found', () {
|
||||
test('throws MultipleArtifactsFoundException when looking for aab', () {
|
||||
final duplicatedArtifactPath = path.join(
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
'bundle',
|
||||
'stablePlayStoreRelease',
|
||||
'app---stable-playStore-release.aab',
|
||||
);
|
||||
File(
|
||||
path.join(project.path, duplicatedArtifactPath),
|
||||
).createSync(recursive: true);
|
||||
|
||||
const artifactPath =
|
||||
'build/app/outputs/bundle/stablePlayStoreRelease/app-stable-playStore-release.aab';
|
||||
File(
|
||||
path.join(project.path, artifactPath),
|
||||
).createSync(recursive: true);
|
||||
|
||||
const flavor = 'stablePlayStore';
|
||||
|
||||
expect(
|
||||
() => shorebirdAndroidArtifacts.findAab(
|
||||
project: project,
|
||||
flavor: flavor,
|
||||
),
|
||||
throwsA(isA<MultipleArtifactsFoundException>()),
|
||||
);
|
||||
});
|
||||
|
||||
test('throws MultipleArtifactsFoundException when looking for apk', () {
|
||||
final duplicatedArtifactPath = path.join(
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
'flutter-apk',
|
||||
'app----stableplaystore-release.apk',
|
||||
);
|
||||
File(
|
||||
path.join(project.path, duplicatedArtifactPath),
|
||||
).createSync(recursive: true);
|
||||
|
||||
final artifactPath = path.join(
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
'flutter-apk',
|
||||
'app-stableplaystore-release.apk',
|
||||
);
|
||||
File(
|
||||
path.join(project.path, artifactPath),
|
||||
).createSync(recursive: true);
|
||||
|
||||
const flavor = 'stablePlayStore';
|
||||
|
||||
expect(
|
||||
() => shorebirdAndroidArtifacts.findApk(
|
||||
project: project,
|
||||
flavor: flavor,
|
||||
),
|
||||
throwsA(isA<MultipleArtifactsFoundException>()),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user