fix(shorebird_cli): shorebird should work within child directories (#1492)
This commit is contained in:
@@ -363,6 +363,7 @@ Please create a release using "shorebird release" and try again.
|
||||
required String appId,
|
||||
required int releaseId,
|
||||
required ReleasePlatform platform,
|
||||
required String projectRoot,
|
||||
required String aabPath,
|
||||
required Map<Arch, ArchMetadata> architectures,
|
||||
String? flavor,
|
||||
@@ -370,7 +371,7 @@ Please create a release using "shorebird release" and try again.
|
||||
final createArtifactProgress = logger.progress('Creating artifacts');
|
||||
for (final archMetadata in architectures.values) {
|
||||
final artifactPath = p.join(
|
||||
Directory.current.path,
|
||||
projectRoot,
|
||||
'build',
|
||||
'app',
|
||||
'intermediates',
|
||||
|
||||
@@ -52,7 +52,7 @@ class InitCommand extends ShorebirdCommand {
|
||||
if (!shorebirdEnv.hasPubspecYaml) {
|
||||
logger.err('''
|
||||
Could not find a "pubspec.yaml".
|
||||
Please make sure you are running "shorebird init" from the root of your Flutter project.
|
||||
Please make sure you are running "shorebird init" from within your Flutter project.
|
||||
''');
|
||||
return ExitCode.noInput.code;
|
||||
}
|
||||
@@ -66,11 +66,12 @@ Please make sure you are running "shorebird init" from the root of your Flutter
|
||||
Set<String>? androidFlavors;
|
||||
Set<String>? iosFlavors;
|
||||
var productFlavors = <String>{};
|
||||
final projectRoot = shorebirdEnv.getFlutterProjectRoot()!;
|
||||
final detectFlavorsProgress = logger.progress('Detecting product flavors');
|
||||
try {
|
||||
final flavors = await Future.wait([
|
||||
_maybeGetAndroidFlavors(Directory.current.path),
|
||||
_maybeGetiOSFlavors(Directory.current.path),
|
||||
_maybeGetAndroidFlavors(projectRoot.path),
|
||||
_maybeGetiOSFlavors(projectRoot.path),
|
||||
]);
|
||||
androidFlavors = flavors[0];
|
||||
iosFlavors = flavors[1];
|
||||
@@ -133,7 +134,8 @@ Please make sure you are running "shorebird init" from the root of your Flutter
|
||||
flavorsToAppIds[flavor] = app.id;
|
||||
}
|
||||
_addShorebirdYamlToProject(
|
||||
shorebirdYaml.appId,
|
||||
projectRoot: projectRoot,
|
||||
appId: shorebirdYaml.appId,
|
||||
flavors: flavorsToAppIds,
|
||||
);
|
||||
updateShorebirdYamlProgress.complete('Flavors added to shorebird.yaml');
|
||||
@@ -201,10 +203,16 @@ Please make sure you are running "shorebird init" from the root of your Flutter
|
||||
return ExitCode.software.code;
|
||||
}
|
||||
|
||||
_addShorebirdYamlToProject(appId, flavors: flavors);
|
||||
_addShorebirdYamlToProject(
|
||||
projectRoot: projectRoot,
|
||||
appId: appId,
|
||||
flavors: flavors,
|
||||
);
|
||||
|
||||
if (!shorebirdEnv.pubspecContainsShorebirdYaml) {
|
||||
_addShorebirdYamlToPubspecAssets();
|
||||
_addShorebirdYamlToPubspecAssets(
|
||||
shorebirdEnv.getPubspecYamlFile(cwd: projectRoot),
|
||||
);
|
||||
}
|
||||
|
||||
logger.info(
|
||||
@@ -274,8 +282,9 @@ For more information about Shorebird, visit ${link(uri: Uri.parse('https://shore
|
||||
}
|
||||
}
|
||||
|
||||
ShorebirdYaml _addShorebirdYamlToProject(
|
||||
String appId, {
|
||||
ShorebirdYaml _addShorebirdYamlToProject({
|
||||
required String appId,
|
||||
required Directory projectRoot,
|
||||
Map<String, String>? flavors,
|
||||
}) {
|
||||
const content = '''
|
||||
@@ -299,13 +308,14 @@ app_id:
|
||||
|
||||
if (flavors != null) editor.update(['flavors'], flavors);
|
||||
|
||||
shorebirdEnv.getShorebirdYamlFile().writeAsStringSync(editor.toString());
|
||||
shorebirdEnv
|
||||
.getShorebirdYamlFile(cwd: projectRoot)
|
||||
.writeAsStringSync(editor.toString());
|
||||
|
||||
return ShorebirdYaml(appId: appId);
|
||||
}
|
||||
|
||||
void _addShorebirdYamlToPubspecAssets() {
|
||||
final pubspecFile = shorebirdEnv.getPubspecYamlFile();
|
||||
void _addShorebirdYamlToPubspecAssets(File pubspecFile) {
|
||||
final pubspecContents = pubspecFile.readAsStringSync();
|
||||
final yaml = loadYaml(pubspecContents, sourceUrl: pubspecFile.uri) as Map;
|
||||
final editor = YamlEditor(pubspecContents);
|
||||
|
||||
@@ -128,9 +128,18 @@ If this option is not provided, the version number will be determined from the p
|
||||
return ExitCode.software.code;
|
||||
}
|
||||
|
||||
final projectRoot = shorebirdEnv.getShorebirdProjectRoot()!;
|
||||
|
||||
final bundleDirPath = p.join(
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
'bundle',
|
||||
);
|
||||
final bundlePath = flavor != null
|
||||
? './build/app/outputs/bundle/${flavor}Release/app-$flavor-release.aab'
|
||||
: './build/app/outputs/bundle/release/app-release.aab';
|
||||
? p.join(bundleDirPath, '${flavor}Release', 'app-$flavor-release.aab')
|
||||
: p.join(bundleDirPath, 'release', 'app-release.aab');
|
||||
|
||||
final String releaseVersion;
|
||||
final argReleaseVersion = results['release-version'] as String?;
|
||||
@@ -251,7 +260,7 @@ Current Flutter Revision: $originalFlutterRevision
|
||||
for (final releaseArtifactPath in releaseArtifactPaths.entries) {
|
||||
final archMetadata = architectures[releaseArtifactPath.key]!;
|
||||
final patchArtifactPath = p.join(
|
||||
Directory.current.path,
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'app',
|
||||
'intermediates',
|
||||
|
||||
@@ -278,8 +278,11 @@ ${summary.join('\n')}
|
||||
return ExitCode.success.code;
|
||||
}
|
||||
|
||||
String get _aotOutputPath =>
|
||||
p.join(Directory.current.path, 'build', 'out.aot');
|
||||
String get _aotOutputPath => p.join(
|
||||
shorebirdEnv.getShorebirdProjectRoot()!.path,
|
||||
'build',
|
||||
'out.aot',
|
||||
);
|
||||
|
||||
Future<void> _buildPatch() async {
|
||||
final target = results['target'] as String?;
|
||||
|
||||
@@ -158,7 +158,11 @@ Please re-run the release command for this version or create a new release.''');
|
||||
final newestDillFile = newestAppDill();
|
||||
aotFile = await buildElfAotSnapshot(
|
||||
appDillPath: newestDillFile.path,
|
||||
outFilePath: p.join(Directory.current.path, 'build', 'out.aot'),
|
||||
outFilePath: p.join(
|
||||
shorebirdEnv.getShorebirdProjectRoot()!.path,
|
||||
'build',
|
||||
'out.aot',
|
||||
),
|
||||
);
|
||||
} catch (error) {
|
||||
buildProgress.fail('$error');
|
||||
|
||||
@@ -156,13 +156,10 @@ ${summary.join('\n')}
|
||||
|
||||
// Copy release AAR to a new directory to avoid overwriting with subsequent
|
||||
// patch builds.
|
||||
final sourceLibraryDirectory = Directory(
|
||||
aarLibraryPath(
|
||||
packageName: shorebirdEnv.androidPackageName!,
|
||||
),
|
||||
final sourceLibraryDirectory = Directory(aarLibraryPath);
|
||||
final targetLibraryDirectory = Directory(
|
||||
p.join(shorebirdEnv.getShorebirdProjectRoot()!.path, 'release'),
|
||||
);
|
||||
final targetLibraryDirectory =
|
||||
Directory(p.join(Directory.current.path, 'release'));
|
||||
await copyPath(sourceLibraryDirectory.path, targetLibraryDirectory.path);
|
||||
|
||||
final extractAarProgress = logger.progress('Creating artifacts');
|
||||
@@ -209,7 +206,7 @@ dependencyResolutionManagement {
|
||||
google()
|
||||
mavenCentral()
|
||||
+ maven {
|
||||
+ url '../${p.basename(Directory.current.path)}/${p.relative(targetLibraryDirectory.path)}'
|
||||
+ url '../${p.basename(shorebirdEnv.getShorebirdProjectRoot()!.path)}/${p.relative(targetLibraryDirectory.path)}'
|
||||
+ }
|
||||
+ maven {
|
||||
- url 'https://storage.googleapis.com/download.flutter.io'
|
||||
|
||||
@@ -110,15 +110,28 @@ Please comment and upvote ${link(uri: Uri.parse('https://github.com/shorebirdtec
|
||||
return ExitCode.software.code;
|
||||
}
|
||||
|
||||
final projectRoot = shorebirdEnv.getShorebirdProjectRoot()!;
|
||||
final shorebirdYaml = shorebirdEnv.getShorebirdYaml()!;
|
||||
final appId = shorebirdYaml.getAppId(flavor: flavor);
|
||||
final app = await codePushClientWrapper.getApp(appId: appId);
|
||||
|
||||
final bundleDirPath = p.join('build', 'app', 'outputs', 'bundle');
|
||||
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 apkDirPath = p.join('build', 'app', 'outputs', 'apk');
|
||||
final apkPath = flavor != null
|
||||
? p.join(apkDirPath, flavor, 'release', 'app-$flavor-release.apk')
|
||||
: p.join(apkDirPath, 'release', 'app-release.apk');
|
||||
@@ -194,6 +207,7 @@ ${summary.join('\n')}
|
||||
await codePushClientWrapper.createAndroidReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: release.id,
|
||||
projectRoot: projectRoot.path,
|
||||
aabPath: bundlePath,
|
||||
platform: platform,
|
||||
architectures: architectures,
|
||||
|
||||
@@ -4,22 +4,26 @@ import 'package:collection/collection.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:shorebird_cli/src/command.dart';
|
||||
import 'package:shorebird_cli/src/logger.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_env.dart';
|
||||
|
||||
mixin ShorebirdArtifactMixin on ShorebirdCommand {
|
||||
String aarLibraryPath({required String packageName}) => p.joinAll([
|
||||
Directory.current.path,
|
||||
'build',
|
||||
'host',
|
||||
'outputs',
|
||||
'repo',
|
||||
]);
|
||||
String get aarLibraryPath {
|
||||
final projectRoot = shorebirdEnv.getShorebirdProjectRoot()!;
|
||||
return p.joinAll([
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'host',
|
||||
'outputs',
|
||||
'repo',
|
||||
]);
|
||||
}
|
||||
|
||||
String aarArtifactDirectory({
|
||||
required String packageName,
|
||||
required String buildNumber,
|
||||
}) =>
|
||||
p.joinAll([
|
||||
aarLibraryPath(packageName: packageName),
|
||||
aarLibraryPath,
|
||||
...packageName.split('.'),
|
||||
'flutter_release',
|
||||
buildNumber,
|
||||
@@ -69,18 +73,17 @@ mixin ShorebirdArtifactMixin on ShorebirdCommand {
|
||||
/// Returns the .xcarchive directory generated by `flutter build ipa`. This
|
||||
/// was traditionally named `Runner.xcarchive`, but can now be renamed.
|
||||
Directory? getXcarchiveDirectory() {
|
||||
final projectRoot = shorebirdEnv.getShorebirdProjectRoot()!;
|
||||
final archiveDirectory = Directory(
|
||||
p.join(
|
||||
Directory.current.path,
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'ios',
|
||||
'archive',
|
||||
),
|
||||
);
|
||||
|
||||
if (!archiveDirectory.existsSync()) {
|
||||
return null;
|
||||
}
|
||||
if (!archiveDirectory.existsSync()) return null;
|
||||
|
||||
return archiveDirectory
|
||||
.listSync()
|
||||
@@ -118,9 +121,10 @@ mixin ShorebirdArtifactMixin on ShorebirdCommand {
|
||||
/// an exception if there is not exactly one .ipa file in the build directory,
|
||||
/// or if there is no build directory.
|
||||
String getIpaPath() {
|
||||
final projectRoot = shorebirdEnv.getShorebirdProjectRoot()!;
|
||||
final ipaBuildDirectory = Directory(
|
||||
p.join(
|
||||
Directory.current.path,
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'ios',
|
||||
'ipa',
|
||||
@@ -161,23 +165,27 @@ mixin ShorebirdArtifactMixin on ShorebirdCommand {
|
||||
/// Returns the [Directory] containing the App.xcframework generated by
|
||||
/// `shorebird release ios-framework-alpha` or
|
||||
/// `shorebird patch ios-framework-alpha`.
|
||||
Directory getAppXcframeworkDirectory() => Directory(
|
||||
p.join(
|
||||
Directory.current.path,
|
||||
'build',
|
||||
'ios',
|
||||
'framework',
|
||||
'Release',
|
||||
),
|
||||
);
|
||||
Directory getAppXcframeworkDirectory() {
|
||||
final projectRoot = shorebirdEnv.getShorebirdProjectRoot()!;
|
||||
return Directory(
|
||||
p.join(
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'ios',
|
||||
'framework',
|
||||
'Release',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Finds the most recently-edited app.dill file in the .dart_tool directory.
|
||||
// TODO(bryanoltman): This is an enormous hack – we don't know that this is
|
||||
// the correct file.
|
||||
File newestAppDill() {
|
||||
final projectRoot = shorebirdEnv.getShorebirdProjectRoot()!;
|
||||
final dartToolBuildDir = Directory(
|
||||
p.join(
|
||||
Directory.current.path,
|
||||
projectRoot.path,
|
||||
'.dart_tool',
|
||||
'flutter_build',
|
||||
),
|
||||
|
||||
@@ -7,7 +7,6 @@ import 'package:scoped/scoped.dart';
|
||||
import 'package:shorebird_cli/src/config/shorebird_yaml.dart';
|
||||
import 'package:shorebird_cli/src/platform.dart';
|
||||
import 'package:shorebird_code_push_client/shorebird_code_push_client.dart';
|
||||
import 'package:yaml/yaml.dart';
|
||||
|
||||
/// A reference to a [ShorebirdEnv] instance.
|
||||
final shorebirdEnvRef = create(ShorebirdEnv.new);
|
||||
@@ -94,13 +93,48 @@ class ShorebirdEnv {
|
||||
}
|
||||
|
||||
/// The `shorebird.yaml` file for this project.
|
||||
File getShorebirdYamlFile() {
|
||||
return File(p.join(Directory.current.path, 'shorebird.yaml'));
|
||||
File getShorebirdYamlFile({required Directory cwd}) {
|
||||
return File(p.join(cwd.path, 'shorebird.yaml'));
|
||||
}
|
||||
|
||||
/// The `pubspec.yaml` file for this project.
|
||||
File getPubspecYamlFile() {
|
||||
return File(p.join(Directory.current.path, 'pubspec.yaml'));
|
||||
File getPubspecYamlFile({required Directory cwd}) {
|
||||
return File(p.join(cwd.path, 'pubspec.yaml'));
|
||||
}
|
||||
|
||||
/// Finds nearest ancestor file
|
||||
/// relative to the [cwd] that satisfies [where].
|
||||
File? findNearestAncestor({
|
||||
required File? Function(String path) where,
|
||||
Directory? cwd,
|
||||
}) {
|
||||
Directory? prev;
|
||||
var dir = cwd ?? Directory.current;
|
||||
while (prev?.path != dir.path) {
|
||||
final file = where(dir.path);
|
||||
if (file?.existsSync() ?? false) return file;
|
||||
prev = dir;
|
||||
dir = dir.parent;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// Returns the root directory of the nearest Shorebird project.
|
||||
Directory? getShorebirdProjectRoot() {
|
||||
final file = findNearestAncestor(
|
||||
where: (path) => getShorebirdYamlFile(cwd: Directory(path)),
|
||||
);
|
||||
if (file == null || !file.existsSync()) return null;
|
||||
return Directory(p.dirname(file.path));
|
||||
}
|
||||
|
||||
/// Returns the root directory of the nearest Flutter project.
|
||||
Directory? getFlutterProjectRoot() {
|
||||
final file = findNearestAncestor(
|
||||
where: (path) => getPubspecYamlFile(cwd: Directory(path)),
|
||||
);
|
||||
if (file == null || !file.existsSync()) return null;
|
||||
return Directory(p.dirname(file.path));
|
||||
}
|
||||
|
||||
/// The `shorebird.yaml` file for this project, parsed into a [ShorebirdYaml]
|
||||
@@ -109,9 +143,9 @@ class ShorebirdEnv {
|
||||
/// Returns `null` if the file does not exist.
|
||||
/// Throws a [ParsedYamlException] if the file exists but is invalid.
|
||||
ShorebirdYaml? getShorebirdYaml() {
|
||||
final file = getShorebirdYamlFile();
|
||||
if (!file.existsSync()) return null;
|
||||
final yaml = file.readAsStringSync();
|
||||
final root = getShorebirdProjectRoot();
|
||||
if (root == null) return null;
|
||||
final yaml = getShorebirdYamlFile(cwd: root).readAsStringSync();
|
||||
return checkedYamlDecode(yaml, (m) => ShorebirdYaml.fromJson(m!));
|
||||
}
|
||||
|
||||
@@ -120,10 +154,14 @@ class ShorebirdEnv {
|
||||
/// Returns `null` if the file does not exist.
|
||||
/// Throws a [ParsedYamlException] if the file exists but is invalid.
|
||||
Pubspec? getPubspecYaml() {
|
||||
final file = getPubspecYamlFile();
|
||||
if (!file.existsSync()) return null;
|
||||
final yaml = file.readAsStringSync();
|
||||
return Pubspec.parse(yaml);
|
||||
final root = getFlutterProjectRoot();
|
||||
if (root == null) return null;
|
||||
final yaml = getPubspecYamlFile(cwd: root).readAsStringSync();
|
||||
try {
|
||||
return Pubspec.parse(yaml);
|
||||
} catch (_) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether `shorebird init` has been run in the current project.
|
||||
@@ -132,7 +170,7 @@ class ShorebirdEnv {
|
||||
}
|
||||
|
||||
/// Whether the current project has a `shorebird.yaml` file.
|
||||
bool get hasShorebirdYaml => getShorebirdYamlFile().existsSync();
|
||||
bool get hasShorebirdYaml => getShorebirdYaml() != null;
|
||||
|
||||
/// Whether the current project has a `pubspec.yaml` file.
|
||||
bool get hasPubspecYaml => getPubspecYaml() != null;
|
||||
@@ -140,13 +178,11 @@ class ShorebirdEnv {
|
||||
/// Whether the current project's `pubspec.yaml` file contains a reference to
|
||||
/// `shorebird.yaml` in its `assets` section.
|
||||
bool get pubspecContainsShorebirdYaml {
|
||||
final file = File(p.join(Directory.current.path, 'pubspec.yaml'));
|
||||
final pubspecContents = file.readAsStringSync();
|
||||
final yaml = loadYaml(pubspecContents, sourceUrl: file.uri) as Map;
|
||||
if (!yaml.containsKey('flutter')) return false;
|
||||
if (yaml['flutter'] is! Map) return false;
|
||||
if (!(yaml['flutter'] as Map).containsKey('assets')) return false;
|
||||
final assets = (yaml['flutter'] as Map)['assets'] as List;
|
||||
final pubspec = getPubspecYaml();
|
||||
if (pubspec == null) return false;
|
||||
if (pubspec.flutter == null) return false;
|
||||
if (pubspec.flutter!['assets'] == null) return false;
|
||||
final assets = pubspec.flutter!['assets'] as List;
|
||||
return assets.contains('shorebird.yaml');
|
||||
}
|
||||
|
||||
|
||||
+17
-12
@@ -1,6 +1,7 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:shorebird_cli/src/shorebird_env.dart';
|
||||
import 'package:shorebird_cli/src/validators/validators.dart';
|
||||
import 'package:xml/xml.dart';
|
||||
|
||||
@@ -22,20 +23,20 @@ class AndroidInternetPermissionValidator extends Validator {
|
||||
'AndroidManifest.xml files contain INTERNET permission';
|
||||
|
||||
@override
|
||||
bool canRunInCurrentContext() => _androidSrcDirectory.existsSync();
|
||||
bool canRunInCurrentContext() => _androidSrcDirectory?.existsSync() ?? false;
|
||||
|
||||
// coverage:ignore-start
|
||||
@override
|
||||
String get incorrectContextMessage => '''
|
||||
The ${_androidSrcDirectory.path} directory does not exist.
|
||||
The ${_androidSrcDirectory?.path ?? 'android/app/src'} directory does not exist.
|
||||
|
||||
The command you are running must be run at the root of a Flutter app project that supports the Android platform. If you are releasing a Flutter module, use 'aar' in place of 'android' in your shorebird command.''';
|
||||
The command you are running must be run within a Flutter app project that supports the Android platform. If you are releasing a Flutter module, use 'aar' in place of 'android' in your shorebird command.''';
|
||||
// coverage:ignore-end
|
||||
|
||||
@override
|
||||
Future<List<ValidationIssue>> validate() async {
|
||||
final manifestFilePath = p.join(
|
||||
_androidSrcDirectory.path,
|
||||
_androidSrcDirectory!.path,
|
||||
'main',
|
||||
'AndroidManifest.xml',
|
||||
);
|
||||
@@ -63,14 +64,18 @@ The command you are running must be run at the root of a Flutter app project tha
|
||||
return [];
|
||||
}
|
||||
|
||||
Directory get _androidSrcDirectory => Directory(
|
||||
p.join(
|
||||
Directory.current.path,
|
||||
'android',
|
||||
'app',
|
||||
'src',
|
||||
),
|
||||
);
|
||||
Directory? get _androidSrcDirectory {
|
||||
final root = shorebirdEnv.getFlutterProjectRoot();
|
||||
if (root == null) return null;
|
||||
return Directory(
|
||||
p.join(
|
||||
root.path,
|
||||
'android',
|
||||
'app',
|
||||
'src',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
bool _androidManifestHasInternetPermission(String path) {
|
||||
final xmlDocument = XmlDocument.parse(File(path).readAsStringSync());
|
||||
|
||||
@@ -119,6 +119,7 @@ void main() {
|
||||
late Progress progress;
|
||||
late CodePushClientWrapper codePushClientWrapper;
|
||||
late Platform platform;
|
||||
late Directory projectRoot;
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
return runScoped(
|
||||
@@ -143,6 +144,7 @@ void main() {
|
||||
logger = MockLogger();
|
||||
platform = MockPlatform();
|
||||
progress = MockProgress();
|
||||
projectRoot = Directory.systemTemp.createTempSync();
|
||||
|
||||
codePushClientWrapper = runWithOverrides(
|
||||
() => CodePushClientWrapper(codePushClient: codePushClient),
|
||||
@@ -720,7 +722,7 @@ Please bump your version number and try again.''',
|
||||
platform: any(named: 'platform'),
|
||||
status: any(named: 'status'),
|
||||
),
|
||||
).thenAnswer((_) async => {});
|
||||
).thenAnswer((_) async {});
|
||||
|
||||
final result = await runWithOverrides(
|
||||
() async => codePushClientWrapper.createRelease(
|
||||
@@ -989,13 +991,12 @@ Please bump your version number and try again.''',
|
||||
group('createAndroidReleaseArtifacts', () {
|
||||
final aabPath = p.join('path', 'to', 'app.aab');
|
||||
|
||||
Directory setUpTempDir({String? flavor}) {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
File(p.join(tempDir.path, aabPath)).createSync(recursive: true);
|
||||
void setUpProjectRoot({String? flavor}) {
|
||||
File(p.join(projectRoot.path, aabPath)).createSync(recursive: true);
|
||||
for (final archMetadata
|
||||
in ShorebirdBuildMixin.allAndroidArchitectures.values) {
|
||||
final artifactPath = p.join(
|
||||
tempDir.path,
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'app',
|
||||
'intermediates',
|
||||
@@ -1008,7 +1009,6 @@ Please bump your version number and try again.''',
|
||||
);
|
||||
File(artifactPath).createSync(recursive: true);
|
||||
}
|
||||
return tempDir;
|
||||
}
|
||||
|
||||
setUp(() {
|
||||
@@ -1022,7 +1022,7 @@ Please bump your version number and try again.''',
|
||||
hash: any(named: 'hash'),
|
||||
canSideload: any(named: 'canSideload'),
|
||||
),
|
||||
).thenAnswer((_) async => {});
|
||||
).thenAnswer((_) async {});
|
||||
});
|
||||
|
||||
test('exits with code 70 when artifact creation fails', () async {
|
||||
@@ -1038,22 +1038,20 @@ Please bump your version number and try again.''',
|
||||
canSideload: any(named: 'canSideload'),
|
||||
),
|
||||
).thenThrow(error);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
|
||||
await IOOverrides.runZoned(
|
||||
() async => expectLater(
|
||||
() async => runWithOverrides(
|
||||
() async => codePushClientWrapper.createAndroidReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
platform: releasePlatform,
|
||||
aabPath: p.join(tempDir.path, aabPath),
|
||||
architectures: ShorebirdBuildMixin.allAndroidArchitectures,
|
||||
),
|
||||
await expectLater(
|
||||
() async => runWithOverrides(
|
||||
() async => codePushClientWrapper.createAndroidReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
platform: releasePlatform,
|
||||
projectRoot: projectRoot.path,
|
||||
aabPath: p.join(projectRoot.path, aabPath),
|
||||
architectures: ShorebirdBuildMixin.allAndroidArchitectures,
|
||||
),
|
||||
exitsWithCode(ExitCode.software),
|
||||
),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
exitsWithCode(ExitCode.software),
|
||||
);
|
||||
|
||||
verify(() => progress.fail(any(that: contains(error)))).called(1);
|
||||
@@ -1072,22 +1070,20 @@ Please bump your version number and try again.''',
|
||||
canSideload: any(named: 'canSideload'),
|
||||
),
|
||||
).thenThrow(error);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
|
||||
await IOOverrides.runZoned(
|
||||
() async => expectLater(
|
||||
() async => runWithOverrides(
|
||||
() async => codePushClientWrapper.createAndroidReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
platform: releasePlatform,
|
||||
aabPath: p.join(tempDir.path, aabPath),
|
||||
architectures: ShorebirdBuildMixin.allAndroidArchitectures,
|
||||
),
|
||||
await expectLater(
|
||||
() async => runWithOverrides(
|
||||
() async => codePushClientWrapper.createAndroidReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
platform: releasePlatform,
|
||||
projectRoot: projectRoot.path,
|
||||
aabPath: p.join(projectRoot.path, aabPath),
|
||||
architectures: ShorebirdBuildMixin.allAndroidArchitectures,
|
||||
),
|
||||
exitsWithCode(ExitCode.software),
|
||||
),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
exitsWithCode(ExitCode.software),
|
||||
);
|
||||
|
||||
verify(() => progress.fail(any(that: contains(error)))).called(1);
|
||||
@@ -1107,18 +1103,16 @@ Please bump your version number and try again.''',
|
||||
canSideload: any(named: 'canSideload'),
|
||||
),
|
||||
).thenThrow(const CodePushConflictException(message: error));
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
|
||||
await runWithOverrides(
|
||||
() async => IOOverrides.runZoned(
|
||||
() async => codePushClientWrapper.createAndroidReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
platform: releasePlatform,
|
||||
aabPath: p.join(tempDir.path, aabPath),
|
||||
architectures: ShorebirdBuildMixin.allAndroidArchitectures,
|
||||
),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
() => codePushClientWrapper.createAndroidReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
platform: releasePlatform,
|
||||
projectRoot: projectRoot.path,
|
||||
aabPath: p.join(projectRoot.path, aabPath),
|
||||
architectures: ShorebirdBuildMixin.allAndroidArchitectures,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1144,18 +1138,16 @@ Please bump your version number and try again.''',
|
||||
canSideload: any(named: 'canSideload'),
|
||||
),
|
||||
).thenThrow(const CodePushConflictException(message: error));
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
|
||||
await runWithOverrides(
|
||||
() async => IOOverrides.runZoned(
|
||||
() async => codePushClientWrapper.createAndroidReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
platform: releasePlatform,
|
||||
aabPath: p.join(tempDir.path, aabPath),
|
||||
architectures: ShorebirdBuildMixin.allAndroidArchitectures,
|
||||
),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
() async => codePushClientWrapper.createAndroidReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
platform: releasePlatform,
|
||||
projectRoot: projectRoot.path,
|
||||
aabPath: p.join(projectRoot.path, aabPath),
|
||||
architectures: ShorebirdBuildMixin.allAndroidArchitectures,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1178,19 +1170,17 @@ Please bump your version number and try again.''',
|
||||
hash: any(named: 'hash'),
|
||||
canSideload: any(named: 'canSideload'),
|
||||
),
|
||||
).thenAnswer((_) async => {});
|
||||
final tempDir = setUpTempDir();
|
||||
).thenAnswer((_) async {});
|
||||
setUpProjectRoot();
|
||||
|
||||
await runWithOverrides(
|
||||
() async => IOOverrides.runZoned(
|
||||
() async => codePushClientWrapper.createAndroidReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
platform: releasePlatform,
|
||||
aabPath: p.join(tempDir.path, aabPath),
|
||||
architectures: ShorebirdBuildMixin.allAndroidArchitectures,
|
||||
),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
() async => codePushClientWrapper.createAndroidReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
platform: releasePlatform,
|
||||
projectRoot: projectRoot.path,
|
||||
aabPath: p.join(projectRoot.path, aabPath),
|
||||
architectures: ShorebirdBuildMixin.allAndroidArchitectures,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1210,20 +1200,18 @@ Please bump your version number and try again.''',
|
||||
hash: any(named: 'hash'),
|
||||
canSideload: any(named: 'canSideload'),
|
||||
),
|
||||
).thenAnswer((_) async => {});
|
||||
final tempDir = setUpTempDir(flavor: flavorName);
|
||||
).thenAnswer((_) async {});
|
||||
setUpProjectRoot(flavor: flavorName);
|
||||
|
||||
await runWithOverrides(
|
||||
() async => IOOverrides.runZoned(
|
||||
() async => codePushClientWrapper.createAndroidReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
platform: releasePlatform,
|
||||
aabPath: p.join(tempDir.path, aabPath),
|
||||
architectures: ShorebirdBuildMixin.allAndroidArchitectures,
|
||||
flavor: flavorName,
|
||||
),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
() async => codePushClientWrapper.createAndroidReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
platform: releasePlatform,
|
||||
projectRoot: projectRoot.path,
|
||||
aabPath: p.join(projectRoot.path, aabPath),
|
||||
architectures: ShorebirdBuildMixin.allAndroidArchitectures,
|
||||
flavor: flavorName,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1263,12 +1251,11 @@ Please bump your version number and try again.''',
|
||||
final aarPath = p.join(aarDir, 'flutter_release-$buildNumber.aar');
|
||||
final extractedAarPath = p.join(aarDir, 'flutter_release-$buildNumber');
|
||||
|
||||
Directory setUpTempDir({String? flavor}) {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
void setUpProjectRoot({String? flavor}) {
|
||||
for (final archMetadata
|
||||
in ShorebirdBuildMixin.allAndroidArchitectures.values) {
|
||||
final artifactPath = p.join(
|
||||
tempDir.path,
|
||||
projectRoot.path,
|
||||
extractedAarPath,
|
||||
'jni',
|
||||
archMetadata.path,
|
||||
@@ -1276,8 +1263,7 @@ Please bump your version number and try again.''',
|
||||
);
|
||||
File(artifactPath).createSync(recursive: true);
|
||||
}
|
||||
File(p.join(tempDir.path, aarPath)).createSync(recursive: true);
|
||||
return tempDir;
|
||||
File(p.join(projectRoot.path, aarPath)).createSync(recursive: true);
|
||||
}
|
||||
|
||||
setUp(() {
|
||||
@@ -1291,7 +1277,7 @@ Please bump your version number and try again.''',
|
||||
hash: any(named: 'hash'),
|
||||
canSideload: any(named: 'canSideload'),
|
||||
),
|
||||
).thenAnswer((_) async => {});
|
||||
).thenAnswer((_) async {});
|
||||
});
|
||||
|
||||
test('exits with code 70 when artifact creation fails', () async {
|
||||
@@ -1307,24 +1293,21 @@ Please bump your version number and try again.''',
|
||||
canSideload: any(named: 'canSideload'),
|
||||
),
|
||||
).thenThrow(error);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
|
||||
await IOOverrides.runZoned(
|
||||
() async => expectLater(
|
||||
() async => runWithOverrides(
|
||||
() async =>
|
||||
codePushClientWrapper.createAndroidArchiveReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
platform: releasePlatform,
|
||||
aarPath: p.join(tempDir.path, aarPath),
|
||||
extractedAarDir: p.join(tempDir.path, extractedAarPath),
|
||||
architectures: ShorebirdBuildMixin.allAndroidArchitectures,
|
||||
),
|
||||
await expectLater(
|
||||
() async => runWithOverrides(
|
||||
() async =>
|
||||
codePushClientWrapper.createAndroidArchiveReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
platform: releasePlatform,
|
||||
aarPath: p.join(projectRoot.path, aarPath),
|
||||
extractedAarDir: p.join(projectRoot.path, extractedAarPath),
|
||||
architectures: ShorebirdBuildMixin.allAndroidArchitectures,
|
||||
),
|
||||
exitsWithCode(ExitCode.software),
|
||||
),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
exitsWithCode(ExitCode.software),
|
||||
);
|
||||
|
||||
verify(() => progress.fail(any(that: contains(error)))).called(1);
|
||||
@@ -1343,24 +1326,21 @@ Please bump your version number and try again.''',
|
||||
canSideload: any(named: 'canSideload'),
|
||||
),
|
||||
).thenThrow(error);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
|
||||
await IOOverrides.runZoned(
|
||||
() async => expectLater(
|
||||
() async => runWithOverrides(
|
||||
() async =>
|
||||
codePushClientWrapper.createAndroidArchiveReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
platform: releasePlatform,
|
||||
aarPath: p.join(tempDir.path, aarPath),
|
||||
extractedAarDir: p.join(tempDir.path, extractedAarPath),
|
||||
architectures: ShorebirdBuildMixin.allAndroidArchitectures,
|
||||
),
|
||||
await expectLater(
|
||||
() async => runWithOverrides(
|
||||
() async =>
|
||||
codePushClientWrapper.createAndroidArchiveReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
platform: releasePlatform,
|
||||
aarPath: p.join(projectRoot.path, aarPath),
|
||||
extractedAarDir: p.join(projectRoot.path, extractedAarPath),
|
||||
architectures: ShorebirdBuildMixin.allAndroidArchitectures,
|
||||
),
|
||||
exitsWithCode(ExitCode.software),
|
||||
),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
exitsWithCode(ExitCode.software),
|
||||
);
|
||||
|
||||
verify(() => progress.fail(any(that: contains(error)))).called(1);
|
||||
@@ -1380,20 +1360,17 @@ Please bump your version number and try again.''',
|
||||
canSideload: any(named: 'canSideload'),
|
||||
),
|
||||
).thenThrow(const CodePushConflictException(message: error));
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
|
||||
await runWithOverrides(
|
||||
() async => IOOverrides.runZoned(
|
||||
() async =>
|
||||
codePushClientWrapper.createAndroidArchiveReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
platform: releasePlatform,
|
||||
aarPath: p.join(tempDir.path, aarPath),
|
||||
extractedAarDir: p.join(tempDir.path, extractedAarPath),
|
||||
architectures: ShorebirdBuildMixin.allAndroidArchitectures,
|
||||
),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
() async =>
|
||||
codePushClientWrapper.createAndroidArchiveReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
platform: releasePlatform,
|
||||
aarPath: p.join(projectRoot.path, aarPath),
|
||||
extractedAarDir: p.join(projectRoot.path, extractedAarPath),
|
||||
architectures: ShorebirdBuildMixin.allAndroidArchitectures,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1419,20 +1396,17 @@ Please bump your version number and try again.''',
|
||||
canSideload: any(named: 'canSideload'),
|
||||
),
|
||||
).thenThrow(const CodePushConflictException(message: error));
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
|
||||
await runWithOverrides(
|
||||
() async => IOOverrides.runZoned(
|
||||
() async =>
|
||||
codePushClientWrapper.createAndroidArchiveReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
platform: releasePlatform,
|
||||
aarPath: p.join(tempDir.path, aarPath),
|
||||
extractedAarDir: p.join(tempDir.path, extractedAarPath),
|
||||
architectures: ShorebirdBuildMixin.allAndroidArchitectures,
|
||||
),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
() async =>
|
||||
codePushClientWrapper.createAndroidArchiveReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
platform: releasePlatform,
|
||||
aarPath: p.join(projectRoot.path, aarPath),
|
||||
extractedAarDir: p.join(projectRoot.path, extractedAarPath),
|
||||
architectures: ShorebirdBuildMixin.allAndroidArchitectures,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1455,21 +1429,18 @@ Please bump your version number and try again.''',
|
||||
hash: any(named: 'hash'),
|
||||
canSideload: any(named: 'canSideload'),
|
||||
),
|
||||
).thenAnswer((_) async => {});
|
||||
final tempDir = setUpTempDir();
|
||||
).thenAnswer((_) async {});
|
||||
setUpProjectRoot();
|
||||
|
||||
await runWithOverrides(
|
||||
() async => IOOverrides.runZoned(
|
||||
() async =>
|
||||
codePushClientWrapper.createAndroidArchiveReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
platform: releasePlatform,
|
||||
aarPath: p.join(tempDir.path, aarPath),
|
||||
extractedAarDir: p.join(tempDir.path, extractedAarPath),
|
||||
architectures: ShorebirdBuildMixin.allAndroidArchitectures,
|
||||
),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
() async =>
|
||||
codePushClientWrapper.createAndroidArchiveReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
platform: releasePlatform,
|
||||
aarPath: p.join(projectRoot.path, aarPath),
|
||||
extractedAarDir: p.join(projectRoot.path, extractedAarPath),
|
||||
architectures: ShorebirdBuildMixin.allAndroidArchitectures,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1489,21 +1460,18 @@ Please bump your version number and try again.''',
|
||||
hash: any(named: 'hash'),
|
||||
canSideload: any(named: 'canSideload'),
|
||||
),
|
||||
).thenAnswer((_) async => {});
|
||||
final tempDir = setUpTempDir(flavor: flavorName);
|
||||
).thenAnswer((_) async {});
|
||||
setUpProjectRoot(flavor: flavorName);
|
||||
|
||||
await runWithOverrides(
|
||||
() async => IOOverrides.runZoned(
|
||||
() async =>
|
||||
codePushClientWrapper.createAndroidArchiveReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
platform: releasePlatform,
|
||||
aarPath: p.join(tempDir.path, aarPath),
|
||||
extractedAarDir: p.join(tempDir.path, extractedAarPath),
|
||||
architectures: ShorebirdBuildMixin.allAndroidArchitectures,
|
||||
),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
() async =>
|
||||
codePushClientWrapper.createAndroidArchiveReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
platform: releasePlatform,
|
||||
aarPath: p.join(projectRoot.path, aarPath),
|
||||
extractedAarDir: p.join(projectRoot.path, extractedAarPath),
|
||||
architectures: ShorebirdBuildMixin.allAndroidArchitectures,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1528,12 +1496,13 @@ Please bump your version number and try again.''',
|
||||
final xcarchivePath = p.join('path', 'to', 'app.xcarchive');
|
||||
final runnerPath = p.join('path', 'to', 'runner.app');
|
||||
|
||||
Directory setUpTempDir({String? flavor}) {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
Directory(p.join(tempDir.path, xcarchivePath))
|
||||
.createSync(recursive: true);
|
||||
Directory(p.join(tempDir.path, runnerPath)).createSync(recursive: true);
|
||||
return tempDir;
|
||||
void setUpProjectRoot({String? flavor}) {
|
||||
Directory(
|
||||
p.join(projectRoot.path, xcarchivePath),
|
||||
).createSync(recursive: true);
|
||||
Directory(
|
||||
p.join(projectRoot.path, runnerPath),
|
||||
).createSync(recursive: true);
|
||||
}
|
||||
|
||||
setUp(() {
|
||||
@@ -1547,7 +1516,7 @@ Please bump your version number and try again.''',
|
||||
hash: any(named: 'hash'),
|
||||
canSideload: any(named: 'canSideload'),
|
||||
),
|
||||
).thenAnswer((_) async => {});
|
||||
).thenAnswer((_) async {});
|
||||
});
|
||||
|
||||
test('exits with code 70 when xcarchive artifact creation fails',
|
||||
@@ -1565,22 +1534,19 @@ Please bump your version number and try again.''',
|
||||
canSideload: any(named: 'canSideload'),
|
||||
),
|
||||
).thenThrow(error);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
|
||||
await IOOverrides.runZoned(
|
||||
() async => expectLater(
|
||||
() async => runWithOverrides(
|
||||
() async => codePushClientWrapper.createIosReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
xcarchivePath: p.join(tempDir.path, xcarchivePath),
|
||||
runnerPath: p.join(tempDir.path, runnerPath),
|
||||
isCodesigned: true,
|
||||
),
|
||||
await expectLater(
|
||||
() async => runWithOverrides(
|
||||
() async => codePushClientWrapper.createIosReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
xcarchivePath: p.join(projectRoot.path, xcarchivePath),
|
||||
runnerPath: p.join(projectRoot.path, runnerPath),
|
||||
isCodesigned: true,
|
||||
),
|
||||
exitsWithCode(ExitCode.software),
|
||||
),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
exitsWithCode(ExitCode.software),
|
||||
);
|
||||
|
||||
verify(() => progress.fail(any(that: contains(error)))).called(1);
|
||||
@@ -1592,8 +1558,10 @@ Please bump your version number and try again.''',
|
||||
when(
|
||||
() => codePushClient.createReleaseArtifact(
|
||||
appId: any(named: 'appId'),
|
||||
artifactPath:
|
||||
any(named: 'artifactPath', that: endsWith('.xcarchive.zip')),
|
||||
artifactPath: any(
|
||||
named: 'artifactPath',
|
||||
that: endsWith('.xcarchive.zip'),
|
||||
),
|
||||
releaseId: any(named: 'releaseId'),
|
||||
arch: any(named: 'arch'),
|
||||
platform: any(named: 'platform'),
|
||||
@@ -1601,22 +1569,19 @@ Please bump your version number and try again.''',
|
||||
canSideload: any(named: 'canSideload'),
|
||||
),
|
||||
).thenThrow(const CodePushConflictException(message: error));
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
|
||||
await IOOverrides.runZoned(
|
||||
() async => expectLater(
|
||||
() async => runWithOverrides(
|
||||
() async => codePushClientWrapper.createIosReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
xcarchivePath: p.join(tempDir.path, xcarchivePath),
|
||||
runnerPath: p.join(tempDir.path, runnerPath),
|
||||
isCodesigned: false,
|
||||
),
|
||||
await expectLater(
|
||||
() async => runWithOverrides(
|
||||
() async => codePushClientWrapper.createIosReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
xcarchivePath: p.join(projectRoot.path, xcarchivePath),
|
||||
runnerPath: p.join(projectRoot.path, runnerPath),
|
||||
isCodesigned: false,
|
||||
),
|
||||
exitsWithCode(ExitCode.software),
|
||||
),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
exitsWithCode(ExitCode.software),
|
||||
);
|
||||
|
||||
verify(() => progress.fail(any(that: contains(error)))).called(1);
|
||||
@@ -1639,22 +1604,19 @@ Please bump your version number and try again.''',
|
||||
canSideload: any(named: 'canSideload'),
|
||||
),
|
||||
).thenThrow(error);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
|
||||
await IOOverrides.runZoned(
|
||||
() async => expectLater(
|
||||
() async => runWithOverrides(
|
||||
() async => codePushClientWrapper.createIosReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
xcarchivePath: p.join(tempDir.path, xcarchivePath),
|
||||
runnerPath: p.join(tempDir.path, runnerPath),
|
||||
isCodesigned: false,
|
||||
),
|
||||
await expectLater(
|
||||
() async => runWithOverrides(
|
||||
() async => codePushClientWrapper.createIosReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
xcarchivePath: p.join(projectRoot.path, xcarchivePath),
|
||||
runnerPath: p.join(projectRoot.path, runnerPath),
|
||||
isCodesigned: false,
|
||||
),
|
||||
exitsWithCode(ExitCode.software),
|
||||
),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
exitsWithCode(ExitCode.software),
|
||||
);
|
||||
|
||||
verify(() => progress.fail(any(that: contains(error)))).called(1);
|
||||
@@ -1671,19 +1633,16 @@ Please bump your version number and try again.''',
|
||||
hash: any(named: 'hash'),
|
||||
canSideload: any(named: 'canSideload'),
|
||||
),
|
||||
).thenAnswer((_) async => {});
|
||||
final tempDir = setUpTempDir();
|
||||
).thenAnswer((_) async {});
|
||||
setUpProjectRoot();
|
||||
|
||||
await runWithOverrides(
|
||||
() async => IOOverrides.runZoned(
|
||||
() async => codePushClientWrapper.createIosReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
xcarchivePath: p.join(tempDir.path, xcarchivePath),
|
||||
runnerPath: p.join(tempDir.path, runnerPath),
|
||||
isCodesigned: true,
|
||||
),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
() async => codePushClientWrapper.createIosReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
xcarchivePath: p.join(projectRoot.path, xcarchivePath),
|
||||
runnerPath: p.join(projectRoot.path, runnerPath),
|
||||
isCodesigned: true,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1695,11 +1654,10 @@ Please bump your version number and try again.''',
|
||||
group('createIosFrameworkReleaseArtifacts', () {
|
||||
final frameworkPath = p.join('path', 'to', 'App.xcframework');
|
||||
|
||||
Directory setUpTempDir({String? flavor}) {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
Directory(p.join(tempDir.path, frameworkPath))
|
||||
.createSync(recursive: true);
|
||||
return tempDir;
|
||||
void setUpProjectRoot({String? flavor}) {
|
||||
Directory(
|
||||
p.join(projectRoot.path, frameworkPath),
|
||||
).createSync(recursive: true);
|
||||
}
|
||||
|
||||
test(
|
||||
@@ -1715,17 +1673,15 @@ Please bump your version number and try again.''',
|
||||
hash: any(named: 'hash'),
|
||||
canSideload: any(named: 'canSideload'),
|
||||
),
|
||||
).thenThrow(
|
||||
Exception('oh no'),
|
||||
);
|
||||
final tempDir = setUpTempDir();
|
||||
).thenThrow(Exception('oh no'));
|
||||
setUpProjectRoot();
|
||||
|
||||
await expectLater(
|
||||
() async => runWithOverrides(
|
||||
() => codePushClientWrapper.createIosFrameworkReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
appFrameworkPath: p.join(tempDir.path, frameworkPath),
|
||||
appFrameworkPath: p.join(projectRoot.path, frameworkPath),
|
||||
),
|
||||
),
|
||||
exitsWithCode(ExitCode.software),
|
||||
@@ -1744,21 +1700,18 @@ Please bump your version number and try again.''',
|
||||
hash: any(named: 'hash'),
|
||||
canSideload: any(named: 'canSideload'),
|
||||
),
|
||||
).thenAnswer((_) async => {});
|
||||
final tempDir = setUpTempDir();
|
||||
).thenAnswer((_) async {});
|
||||
setUpProjectRoot();
|
||||
|
||||
await IOOverrides.runZoned(
|
||||
() async => expectLater(
|
||||
runWithOverrides(
|
||||
() => codePushClientWrapper.createIosFrameworkReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
appFrameworkPath: p.join(tempDir.path, frameworkPath),
|
||||
),
|
||||
await expectLater(
|
||||
runWithOverrides(
|
||||
() => codePushClientWrapper.createIosFrameworkReleaseArtifacts(
|
||||
appId: app.appId,
|
||||
releaseId: releaseId,
|
||||
appFrameworkPath: p.join(projectRoot.path, frameworkPath),
|
||||
),
|
||||
completes,
|
||||
),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
completes,
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1798,7 +1751,7 @@ Please bump your version number and try again.''',
|
||||
platform: any(named: 'platform'),
|
||||
status: any(named: 'status'),
|
||||
),
|
||||
).thenAnswer((_) async => {});
|
||||
).thenAnswer((_) async {});
|
||||
|
||||
await runWithOverrides(
|
||||
() => codePushClientWrapper.updateReleaseStatus(
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:args/args.dart';
|
||||
import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
@@ -124,14 +122,10 @@ void main() {
|
||||
test('exits with code 70 when building apk fails', () async {
|
||||
when(() => buildProcessResult.exitCode).thenReturn(1);
|
||||
when(() => buildProcessResult.stderr).thenReturn('oops');
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
|
||||
final result = await IOOverrides.runZoned(
|
||||
() async => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.software.code));
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(
|
||||
() => shorebirdProcess.run(
|
||||
'flutter',
|
||||
@@ -143,13 +137,9 @@ void main() {
|
||||
|
||||
test('exits with code 0 when building apk succeeds', () async {
|
||||
when(() => buildProcessResult.exitCode).thenReturn(ExitCode.success.code);
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
final result = await IOOverrides.runZoned(
|
||||
() async => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.success.code));
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
|
||||
verify(
|
||||
() => shorebirdProcess.run(
|
||||
@@ -170,12 +160,8 @@ ${lightCyan.wrap(p.join('build', 'app', 'outputs', 'apk', 'release', 'app-releas
|
||||
test('runs flutter pub get with system flutter after successful build',
|
||||
() async {
|
||||
when(() => buildProcessResult.exitCode).thenReturn(ExitCode.success.code);
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
|
||||
await IOOverrides.runZoned(
|
||||
() async => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
await runWithOverrides(command.run);
|
||||
|
||||
verify(
|
||||
() => shorebirdProcess.run(
|
||||
@@ -195,13 +181,9 @@ ${lightCyan.wrap(p.join('build', 'app', 'outputs', 'apk', 'release', 'app-releas
|
||||
when(() => argResults['flavor']).thenReturn(flavor);
|
||||
when(() => argResults['target']).thenReturn(target);
|
||||
when(() => buildProcessResult.exitCode).thenReturn(ExitCode.success.code);
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
final result = await IOOverrides.runZoned(
|
||||
() async => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.success.code));
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
|
||||
verify(
|
||||
() => shorebirdProcess.run(
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:args/args.dart';
|
||||
import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
@@ -125,14 +123,10 @@ void main() {
|
||||
test('exits with code 70 when building appbundle fails', () async {
|
||||
when(() => buildProcessResult.exitCode).thenReturn(1);
|
||||
when(() => buildProcessResult.stderr).thenReturn('oops');
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
|
||||
final result = await IOOverrides.runZoned(
|
||||
() async => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.software.code));
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(
|
||||
() => shorebirdProcess.run(
|
||||
'flutter',
|
||||
@@ -144,13 +138,9 @@ void main() {
|
||||
|
||||
test('exits with code 0 when building appbundle succeeds', () async {
|
||||
when(() => buildProcessResult.exitCode).thenReturn(ExitCode.success.code);
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
final result = await IOOverrides.runZoned(
|
||||
() async => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.success.code));
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verify(
|
||||
() => shorebirdProcess.run(
|
||||
'flutter',
|
||||
@@ -176,13 +166,9 @@ ${lightCyan.wrap(p.join('build', 'app', 'outputs', 'bundle', 'release', 'app-rel
|
||||
when(() => argResults['flavor']).thenReturn(flavor);
|
||||
when(() => argResults['target']).thenReturn(target);
|
||||
when(() => buildProcessResult.exitCode).thenReturn(ExitCode.success.code);
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
final result = await IOOverrides.runZoned(
|
||||
() async => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.success.code));
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verify(
|
||||
() => shorebirdProcess.run(
|
||||
'flutter',
|
||||
@@ -247,12 +233,8 @@ ${lightCyan.wrap(p.join('build', 'app', 'outputs', 'bundle', '${flavor}Release',
|
||||
test('runs flutter pub get with system flutter after successful build',
|
||||
() async {
|
||||
when(() => buildProcessResult.exitCode).thenReturn(ExitCode.success.code);
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
|
||||
await IOOverrides.runZoned(
|
||||
() async => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
await runWithOverrides(command.run);
|
||||
|
||||
verify(
|
||||
() => shorebirdProcess.run(
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:args/args.dart';
|
||||
import 'package:mason_logger/mason_logger.dart';
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
@@ -123,14 +121,10 @@ void main() {
|
||||
test('exits with code 70 when building ipa fails', () async {
|
||||
when(() => buildProcessResult.exitCode).thenReturn(1);
|
||||
when(() => buildProcessResult.stderr).thenReturn('oops');
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
|
||||
final result = await IOOverrides.runZoned(
|
||||
() async => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.software.code));
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(
|
||||
() => shorebirdProcess.run(
|
||||
'flutter',
|
||||
@@ -146,13 +140,9 @@ void main() {
|
||||
|
||||
test('exits with code 0 when building ipa succeeds', () async {
|
||||
when(() => buildProcessResult.exitCode).thenReturn(ExitCode.success.code);
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
final result = await IOOverrides.runZoned(
|
||||
() async => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.success.code));
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
|
||||
verify(
|
||||
() => shorebirdProcess.run(
|
||||
@@ -183,12 +173,8 @@ ${lightCyan.wrap(p.join('build', 'ios', 'ipa', 'Runner.ipa'))}''',
|
||||
test('runs flutter pub get with system flutter after successful build',
|
||||
() async {
|
||||
when(() => buildProcessResult.exitCode).thenReturn(ExitCode.success.code);
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
|
||||
await IOOverrides.runZoned(
|
||||
() async => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
await runWithOverrides(command.run);
|
||||
|
||||
verify(
|
||||
() => shorebirdProcess.run(
|
||||
@@ -208,13 +194,9 @@ ${lightCyan.wrap(p.join('build', 'ios', 'ipa', 'Runner.ipa'))}''',
|
||||
when(() => argResults['flavor']).thenReturn(flavor);
|
||||
when(() => argResults['target']).thenReturn(target);
|
||||
when(() => buildProcessResult.exitCode).thenReturn(ExitCode.success.code);
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
final result = await IOOverrides.runZoned(
|
||||
() async => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.success.code));
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
|
||||
verify(
|
||||
() => shorebirdProcess.run(
|
||||
@@ -253,13 +235,9 @@ ${lightCyan.wrap(p.join('build', 'ios', 'ipa', 'Runner.ipa'))}''',
|
||||
'with --no-codesign', () async {
|
||||
when(() => argResults['codesign']).thenReturn(false);
|
||||
when(() => buildProcessResult.exitCode).thenReturn(ExitCode.success.code);
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
final result = await IOOverrides.runZoned(
|
||||
() async => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.success.code));
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
|
||||
verify(
|
||||
() => shorebirdProcess.run(
|
||||
|
||||
@@ -40,6 +40,7 @@ environment:
|
||||
late CodePushClientWrapper codePushClientWrapper;
|
||||
late File shorebirdYamlFile;
|
||||
late ShorebirdYaml shorebirdYaml;
|
||||
late Directory projectRoot;
|
||||
late File pubspecYamlFile;
|
||||
late Logger logger;
|
||||
late Platform platform;
|
||||
@@ -66,6 +67,10 @@ environment:
|
||||
);
|
||||
}
|
||||
|
||||
setUpAll(() {
|
||||
registerFallbackValue(MockDirectory());
|
||||
});
|
||||
|
||||
setUp(() {
|
||||
argResults = MockArgResults();
|
||||
doctor = MockDoctor();
|
||||
@@ -74,6 +79,7 @@ environment:
|
||||
shorebirdYaml = MockShorebirdYaml();
|
||||
shorebirdYamlFile = MockFile();
|
||||
pubspecYamlFile = MockFile();
|
||||
projectRoot = Directory.systemTemp.createTempSync();
|
||||
logger = MockLogger();
|
||||
platform = MockPlatform();
|
||||
progress = MockProgress();
|
||||
@@ -89,9 +95,12 @@ environment:
|
||||
).thenAnswer((_) async => {});
|
||||
when(() => doctor.allValidators).thenReturn([]);
|
||||
when(
|
||||
() => shorebirdEnv.getShorebirdYamlFile(),
|
||||
() => shorebirdEnv.getShorebirdYamlFile(cwd: any(named: 'cwd')),
|
||||
).thenReturn(shorebirdYamlFile);
|
||||
when(() => shorebirdEnv.getPubspecYamlFile()).thenReturn(pubspecYamlFile);
|
||||
when(
|
||||
() => shorebirdEnv.getPubspecYamlFile(cwd: any(named: 'cwd')),
|
||||
).thenReturn(pubspecYamlFile);
|
||||
when(() => shorebirdEnv.getFlutterProjectRoot()).thenReturn(projectRoot);
|
||||
when(
|
||||
() => pubspecYamlFile.readAsStringSync(),
|
||||
).thenReturn(pubspecYamlContent);
|
||||
@@ -148,7 +157,7 @@ environment:
|
||||
() => logger.err(
|
||||
'''
|
||||
Could not find a "pubspec.yaml".
|
||||
Please make sure you are running "shorebird init" from the root of your Flutter project.
|
||||
Please make sure you are running "shorebird init" from within your Flutter project.
|
||||
''',
|
||||
),
|
||||
).called(1);
|
||||
@@ -253,12 +262,8 @@ Please make sure you are running "shorebird init" from the root of your Flutter
|
||||
});
|
||||
|
||||
test('throws software error when unable to detect schemes', () async {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
Directory(p.join(tempDir.path, 'ios')).createSync(recursive: true);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
Directory(p.join(projectRoot.path, 'ios')).createSync(recursive: true);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(
|
||||
() => logger.err(
|
||||
@@ -269,11 +274,7 @@ Please make sure you are running "shorebird init" from the root of your Flutter
|
||||
});
|
||||
|
||||
test('creates shorebird for an android-only app', () async {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verify(
|
||||
() => shorebirdYamlFile.writeAsStringSync(
|
||||
@@ -284,13 +285,12 @@ Please make sure you are running "shorebird init" from the root of your Flutter
|
||||
});
|
||||
|
||||
test('creates shorebird for an app without flavors', () async {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
when(
|
||||
() => gradlew.productFlavors(any()),
|
||||
).thenThrow(MissingAndroidProjectException(tempDir.path));
|
||||
).thenThrow(MissingAndroidProjectException(projectRoot.path));
|
||||
File(
|
||||
p.join(
|
||||
tempDir.path,
|
||||
projectRoot.path,
|
||||
'ios',
|
||||
'Runner.xcodeproj',
|
||||
'xcshareddata',
|
||||
@@ -298,10 +298,7 @@ Please make sure you are running "shorebird init" from the root of your Flutter
|
||||
'Runner.xcscheme',
|
||||
),
|
||||
).createSync(recursive: true);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verify(
|
||||
() => shorebirdYamlFile.writeAsStringSync(
|
||||
@@ -322,12 +319,11 @@ Please make sure you are running "shorebird init" from the root of your Flutter
|
||||
final appName = invocation.namedArguments[#appName] as String?;
|
||||
return App(id: appIds[index++], displayName: appName ?? '-');
|
||||
});
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
when(
|
||||
() => gradlew.productFlavors(any()),
|
||||
).thenThrow(MissingAndroidProjectException(tempDir.path));
|
||||
).thenThrow(MissingAndroidProjectException(projectRoot.path));
|
||||
final schemesPath = p.join(
|
||||
tempDir.path,
|
||||
projectRoot.path,
|
||||
'ios',
|
||||
'Runner.xcodeproj',
|
||||
'xcshareddata',
|
||||
@@ -342,10 +338,7 @@ Please make sure you are running "shorebird init" from the root of your Flutter
|
||||
File(
|
||||
p.join(schemesPath, 'stable.xcscheme'),
|
||||
).createSync(recursive: true);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verify(() => progress.complete('2 product flavors detected:'))
|
||||
.called(1);
|
||||
|
||||
@@ -85,6 +85,7 @@ void main() {
|
||||
late Auth auth;
|
||||
late CodePushClientWrapper codePushClientWrapper;
|
||||
late Directory shorebirdRoot;
|
||||
late Directory projectRoot;
|
||||
late Directory flutterDirectory;
|
||||
late OperatingSystemInterface operatingSystemInterface;
|
||||
late PatchDiffChecker patchDiffChecker;
|
||||
@@ -122,11 +123,9 @@ void main() {
|
||||
);
|
||||
}
|
||||
|
||||
Directory setUpTempDir() => Directory.systemTemp.createTempSync();
|
||||
|
||||
void setUpTempArtifacts(Directory dir) {
|
||||
void setUpProjectRootArtifacts() {
|
||||
final aarDir = p.join(
|
||||
dir.path,
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'host',
|
||||
'outputs',
|
||||
@@ -170,6 +169,7 @@ void main() {
|
||||
auth = MockAuth();
|
||||
codePushClientWrapper = MockCodePushClientWrapper();
|
||||
shorebirdRoot = Directory.systemTemp.createTempSync();
|
||||
projectRoot = Directory.systemTemp.createTempSync();
|
||||
flutterDirectory = Directory(
|
||||
p.join(shorebirdRoot.path, 'bin', 'cache', 'flutter'),
|
||||
);
|
||||
@@ -191,6 +191,9 @@ void main() {
|
||||
.thenReturn('/path/to/flutter');
|
||||
when(() => platform.environment).thenReturn({});
|
||||
when(() => shorebirdEnv.shorebirdRoot).thenReturn(shorebirdRoot);
|
||||
when(
|
||||
() => shorebirdEnv.getShorebirdProjectRoot(),
|
||||
).thenReturn(projectRoot);
|
||||
when(() => shorebirdEnv.flutterDirectory).thenReturn(flutterDirectory);
|
||||
when(
|
||||
() => shorebirdEnv.androidPackageName,
|
||||
@@ -458,12 +461,8 @@ ${release.version}'''),
|
||||
),
|
||||
],
|
||||
);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.software.code);
|
||||
verify(
|
||||
() => logger.err('''
|
||||
@@ -490,12 +489,8 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
),
|
||||
],
|
||||
);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
});
|
||||
|
||||
@@ -509,12 +504,8 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
outputPath: any(named: 'outputPath'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
verify(() => progress.fail('$exception')).called(1);
|
||||
expect(exitCode, ExitCode.software.code);
|
||||
});
|
||||
@@ -524,13 +515,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
'when release flutter revision differs', () async {
|
||||
const otherRevision = 'other-revision';
|
||||
when(() => shorebirdEnv.flutterRevision).thenReturn(otherRevision);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verify(
|
||||
() => logger.progress(
|
||||
@@ -564,20 +551,16 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
environment: any(named: 'environment'),
|
||||
),
|
||||
).thenAnswer((_) async => flutterBuildProcessResult);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
await IOOverrides.runZoned(
|
||||
() => runWithOverrides(
|
||||
() => runScoped(
|
||||
() => command.run(),
|
||||
values: {
|
||||
processRef.overrideWith(
|
||||
() => ShorebirdProcess(processWrapper: processWrapper),
|
||||
),
|
||||
},
|
||||
),
|
||||
setUpProjectRootArtifacts();
|
||||
await runWithOverrides(
|
||||
() => runScoped(
|
||||
() => command.run(),
|
||||
values: {
|
||||
processRef.overrideWith(
|
||||
() => ShorebirdProcess(processWrapper: processWrapper),
|
||||
),
|
||||
},
|
||||
),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
verify(
|
||||
() => processWrapper.run(
|
||||
@@ -609,13 +592,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
revision: any(named: 'revision'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(
|
||||
() => logger.progress(
|
||||
@@ -649,13 +628,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
force: any(named: 'force'),
|
||||
),
|
||||
).thenThrow(UserCancelledException());
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verify(
|
||||
@@ -690,13 +665,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
),
|
||||
).thenThrow(UnpatchableChangeException());
|
||||
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(
|
||||
@@ -727,24 +698,16 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
patchArtifactPath: any(named: 'patchArtifactPath'),
|
||||
),
|
||||
).thenThrow(error);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
verify(() => progress.fail('$error')).called(1);
|
||||
expect(exitCode, ExitCode.software.code);
|
||||
});
|
||||
|
||||
test('does not create patch on --dry-run', () async {
|
||||
when(() => argResults['dry-run']).thenReturn(true);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verifyNever(
|
||||
() => codePushClientWrapper.publishPatch(
|
||||
@@ -760,25 +723,17 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
|
||||
test('aborts when user opts out', () async {
|
||||
when(() => logger.confirm(any())).thenReturn(false);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
verify(() => logger.info('Aborting.')).called(1);
|
||||
});
|
||||
|
||||
test('does not prompt on --force', () async {
|
||||
when(() => argResults['force']).thenReturn(true);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verifyNever(() => logger.confirm(any()));
|
||||
@@ -794,13 +749,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
});
|
||||
|
||||
test('succeeds when patch is successful', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
verify(
|
||||
@@ -846,13 +797,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
|
||||
test('runs flutter pub get with system flutter after successful build',
|
||||
() async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
await runWithOverrides(command.run);
|
||||
|
||||
verify(
|
||||
() => shorebirdProcess.run(
|
||||
@@ -866,13 +813,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
|
||||
test('does not prompt if running on CI', () async {
|
||||
when(() => shorebirdEnv.isRunningOnCI).thenReturn(true);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verifyNever(() => logger.confirm(any()));
|
||||
|
||||
@@ -97,6 +97,7 @@ flutter:
|
||||
late CodePushClientWrapper codePushClientWrapper;
|
||||
late Directory flutterDirectory;
|
||||
late Directory shorebirdRoot;
|
||||
late Directory projectRoot;
|
||||
late Doctor doctor;
|
||||
late Java java;
|
||||
late OperatingSystemInterface operatingSystemInterface;
|
||||
@@ -139,22 +140,20 @@ flutter:
|
||||
);
|
||||
}
|
||||
|
||||
Directory setUpTempDir() {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
void setUpProjectRoot() {
|
||||
File(
|
||||
p.join(tempDir.path, 'pubspec.yaml'),
|
||||
p.join(projectRoot.path, 'pubspec.yaml'),
|
||||
).writeAsStringSync(pubspecYamlContent);
|
||||
File(
|
||||
p.join(tempDir.path, 'shorebird.yaml'),
|
||||
p.join(projectRoot.path, 'shorebird.yaml'),
|
||||
).writeAsStringSync('app_id: $appId');
|
||||
return tempDir;
|
||||
}
|
||||
|
||||
void setUpTempArtifacts(Directory dir, {String? flavor}) {
|
||||
void setUpProjectRootArtifacts({String? flavor}) {
|
||||
for (final archMetadata
|
||||
in ShorebirdBuildMixin.allAndroidArchitectures.values) {
|
||||
final artifactPath = p.join(
|
||||
dir.path,
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'app',
|
||||
'intermediates',
|
||||
@@ -190,6 +189,7 @@ flutter:
|
||||
doctor = MockDoctor();
|
||||
java = MockJava();
|
||||
shorebirdRoot = Directory.systemTemp.createTempSync();
|
||||
projectRoot = Directory.systemTemp.createTempSync();
|
||||
flutterDirectory = Directory(
|
||||
p.join(shorebirdRoot.path, 'bin', 'cache', 'flutter'),
|
||||
);
|
||||
@@ -216,6 +216,9 @@ flutter:
|
||||
|
||||
when(() => shorebirdEnv.getShorebirdYaml()).thenReturn(shorebirdYaml);
|
||||
when(() => shorebirdEnv.shorebirdRoot).thenReturn(shorebirdRoot);
|
||||
when(
|
||||
() => shorebirdEnv.getShorebirdProjectRoot(),
|
||||
).thenReturn(projectRoot);
|
||||
when(() => shorebirdEnv.flutterDirectory).thenReturn(flutterDirectory);
|
||||
when(() => shorebirdEnv.flutterRevision).thenReturn(flutterRevision);
|
||||
when(() => shorebirdFlutter.useRevision(revision: any(named: 'revision')))
|
||||
@@ -395,11 +398,8 @@ flutter:
|
||||
'both --dry-run and --force are specified', () async {
|
||||
when(() => argResults['dry-run']).thenReturn(true);
|
||||
when(() => argResults['force']).thenReturn(true);
|
||||
final tempDir = setUpTempDir();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, equals(ExitCode.usage.code));
|
||||
});
|
||||
|
||||
@@ -407,11 +407,8 @@ flutter:
|
||||
when(() => flutterBuildProcessResult.exitCode).thenReturn(1);
|
||||
when(() => flutterBuildProcessResult.stderr).thenReturn('oops');
|
||||
|
||||
final tempDir = setUpTempDir();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
});
|
||||
@@ -436,12 +433,9 @@ flutter:
|
||||
updatedAt: DateTime(2023),
|
||||
),
|
||||
);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.software.code);
|
||||
verify(
|
||||
() => logger.err('''
|
||||
@@ -470,12 +464,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
),
|
||||
],
|
||||
);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
});
|
||||
|
||||
@@ -484,13 +475,10 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
() async {
|
||||
const otherRevision = 'other-revision';
|
||||
when(() => shorebirdEnv.flutterRevision).thenReturn(otherRevision);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
// Verify that we switch back to the original revision once we're done.
|
||||
@@ -523,13 +511,10 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
when(() => flutterBuildProcessResult.exitCode).thenReturn(1);
|
||||
when(() => flutterBuildProcessResult.stderr).thenReturn('oops');
|
||||
});
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
},
|
||||
@@ -541,12 +526,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
});
|
||||
|
||||
test('does not extract release version from app bundle', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
await runWithOverrides(command.run);
|
||||
verifyNever(() => bundletool.getVersionName(any()));
|
||||
verifyNever(() => bundletool.getVersionCode(any()));
|
||||
verifyNever(() => logger.progress('Detecting release version'));
|
||||
@@ -555,12 +537,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
|
||||
group('when release-version option is not provided', () {
|
||||
test('extracts release version from app bundle', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
await runWithOverrides(command.run);
|
||||
verify(() => bundletool.getVersionName(any())).called(1);
|
||||
verify(() => bundletool.getVersionCode(any())).called(1);
|
||||
verify(() => logger.progress('Detecting release version')).called(1);
|
||||
@@ -572,12 +551,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
'Failed to extract version name from app bundle: oops',
|
||||
);
|
||||
when(() => bundletool.getVersionName(any())).thenThrow(exception);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.software.code);
|
||||
verify(() => progress.fail('$exception')).called(1);
|
||||
});
|
||||
@@ -587,23 +563,17 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
'Failed to extract version code from app bundle: oops',
|
||||
);
|
||||
when(() => bundletool.getVersionCode(any())).thenThrow(exception);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.software.code);
|
||||
verify(() => progress.fail('$exception')).called(1);
|
||||
});
|
||||
|
||||
test('prints release version when detected', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verify(
|
||||
@@ -613,12 +583,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
|
||||
test('aborts when user opts out', () async {
|
||||
when(() => logger.confirm(any())).thenReturn(false);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
verify(() => logger.info('Aborting.')).called(1);
|
||||
});
|
||||
@@ -633,12 +600,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
outputPath: any(named: 'outputPath'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
verify(() => progress.fail('$exception')).called(1);
|
||||
expect(exitCode, ExitCode.software.code);
|
||||
});
|
||||
@@ -648,12 +612,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
'Failed to extract version name from app bundle: oops',
|
||||
);
|
||||
when(() => bundletool.getVersionName(any())).thenThrow(exception);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.software.code);
|
||||
verify(() => progress.fail('$exception')).called(1);
|
||||
});
|
||||
@@ -663,23 +624,17 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
'Failed to extract version code from app bundle: oops',
|
||||
);
|
||||
when(() => bundletool.getVersionCode(any())).thenThrow(exception);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.software.code);
|
||||
verify(() => progress.fail('$exception')).called(1);
|
||||
});
|
||||
|
||||
test('prints release version when detected', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verify(
|
||||
@@ -699,13 +654,10 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
force: any(named: 'force'),
|
||||
),
|
||||
).thenThrow(UserCancelledException());
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verify(
|
||||
@@ -740,13 +692,10 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
),
|
||||
).thenThrow(UnpatchableChangeException());
|
||||
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(
|
||||
@@ -777,24 +726,18 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
patchArtifactPath: any(named: 'patchArtifactPath'),
|
||||
),
|
||||
).thenThrow(error);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
verify(() => progress.fail('$error')).called(1);
|
||||
expect(exitCode, ExitCode.software.code);
|
||||
});
|
||||
|
||||
test('does not create patch on --dry-run', () async {
|
||||
when(() => argResults['dry-run']).thenReturn(true);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verifyNever(
|
||||
() => codePushClientWrapper.publishPatch(
|
||||
@@ -812,13 +755,10 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
when(() => argResults['force']).thenReturn(true);
|
||||
when(() => archiveDiffer.containsPotentiallyBreakingAssetDiffs(any()))
|
||||
.thenReturn(true);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verifyNever(() => logger.confirm(any()));
|
||||
@@ -834,12 +774,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
});
|
||||
|
||||
test('succeeds when patch is successful (production)', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
verify(
|
||||
() => logger.info(
|
||||
any(
|
||||
@@ -865,12 +802,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
|
||||
test('succeeds when patch is successful (staging)', () async {
|
||||
when(() => argResults['staging']).thenReturn(true);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
verify(
|
||||
() => logger.info(
|
||||
any(
|
||||
@@ -896,12 +830,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
|
||||
test('runs flutter pub get with system flutter after successful build',
|
||||
() async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
await runWithOverrides(command.run);
|
||||
|
||||
verify(
|
||||
() => shorebirdProcess.run(
|
||||
@@ -920,18 +851,15 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
const target = './lib/main_development.dart';
|
||||
when(() => argResults['flavor']).thenReturn(flavor);
|
||||
when(() => argResults['target']).thenReturn(target);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
File(
|
||||
p.join(tempDir.path, 'shorebird.yaml'),
|
||||
p.join(projectRoot.path, 'shorebird.yaml'),
|
||||
).writeAsStringSync('''
|
||||
app_id: productionAppId
|
||||
flavors:
|
||||
development: $appId''');
|
||||
setUpTempArtifacts(tempDir, flavor: flavor);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRootArtifacts(flavor: flavor);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
verify(
|
||||
() => codePushClientWrapper.publishPatch(
|
||||
appId: appId,
|
||||
@@ -946,13 +874,10 @@ flavors:
|
||||
|
||||
test('does not prompt if running on CI', () async {
|
||||
when(() => shorebirdEnv.isRunningOnCI).thenReturn(true);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verifyNever(() => logger.confirm(any()));
|
||||
|
||||
@@ -126,6 +126,7 @@ flutter:
|
||||
late CodePushClientWrapper codePushClientWrapper;
|
||||
late Directory flutterDirectory;
|
||||
late Directory shorebirdRoot;
|
||||
late Directory projectRoot;
|
||||
late File genSnapshotFile;
|
||||
late Doctor doctor;
|
||||
late IosArchiveDiffer archiveDiffer;
|
||||
@@ -164,17 +165,16 @@ flutter:
|
||||
);
|
||||
}
|
||||
|
||||
Directory setUpTempDir() {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
void setUpProjectRoot() {
|
||||
File(
|
||||
p.join(tempDir.path, 'pubspec.yaml'),
|
||||
p.join(projectRoot.path, 'pubspec.yaml'),
|
||||
).writeAsStringSync(pubspecYamlContent);
|
||||
File(
|
||||
p.join(tempDir.path, 'shorebird.yaml'),
|
||||
p.join(projectRoot.path, 'shorebird.yaml'),
|
||||
).writeAsStringSync('app_id: $appId');
|
||||
File(
|
||||
p.join(
|
||||
tempDir.path,
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'ios',
|
||||
'archive',
|
||||
@@ -184,15 +184,14 @@ flutter:
|
||||
)
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync(infoPlistContent);
|
||||
File(p.join(tempDir.path, ipaPath)).createSync(recursive: true);
|
||||
return tempDir;
|
||||
File(p.join(projectRoot.path, ipaPath)).createSync(recursive: true);
|
||||
}
|
||||
|
||||
void setUpTempArtifacts(Directory dir) {
|
||||
void setUpProjectRootArtifacts() {
|
||||
// Create a second app.dill for coverage of newestAppDill file.
|
||||
File(
|
||||
p.join(
|
||||
dir.path,
|
||||
projectRoot.path,
|
||||
'.dart_tool',
|
||||
'flutter_build',
|
||||
'subdir',
|
||||
@@ -200,11 +199,11 @@ flutter:
|
||||
),
|
||||
).createSync(recursive: true);
|
||||
File(
|
||||
p.join(dir.path, '.dart_tool', 'flutter_build', 'app.dill'),
|
||||
p.join(projectRoot.path, '.dart_tool', 'flutter_build', 'app.dill'),
|
||||
).createSync(recursive: true);
|
||||
File(
|
||||
p.join(projectRoot.path, 'build', elfAotSnapshotFileName),
|
||||
).createSync(recursive: true);
|
||||
File(p.join(dir.path, 'build', elfAotSnapshotFileName)).createSync(
|
||||
recursive: true,
|
||||
);
|
||||
}
|
||||
|
||||
setUpAll(() {
|
||||
@@ -224,6 +223,7 @@ flutter:
|
||||
codePushClientWrapper = MockCodePushClientWrapper();
|
||||
doctor = MockDoctor();
|
||||
shorebirdRoot = Directory.systemTemp.createTempSync();
|
||||
projectRoot = Directory.systemTemp.createTempSync();
|
||||
flutterDirectory = Directory(
|
||||
p.join(shorebirdRoot.path, 'bin', 'cache', 'flutter'),
|
||||
);
|
||||
@@ -299,6 +299,9 @@ flutter:
|
||||
when(() => platform.script).thenReturn(shorebirdRoot.uri);
|
||||
when(() => shorebirdEnv.getShorebirdYaml()).thenReturn(shorebirdYaml);
|
||||
when(() => shorebirdEnv.shorebirdRoot).thenReturn(shorebirdRoot);
|
||||
when(
|
||||
() => shorebirdEnv.getShorebirdProjectRoot(),
|
||||
).thenReturn(projectRoot);
|
||||
when(() => shorebirdEnv.flutterDirectory).thenReturn(flutterDirectory);
|
||||
when(() => shorebirdEnv.genSnapshotFile).thenReturn(genSnapshotFile);
|
||||
when(() => shorebirdEnv.flutterRevision).thenReturn(flutterRevision);
|
||||
@@ -390,11 +393,8 @@ flutter:
|
||||
'both --dry-run and --force are specified', () async {
|
||||
when(() => argResults['dry-run']).thenReturn(true);
|
||||
when(() => argResults['force']).thenReturn(true);
|
||||
final tempDir = setUpTempDir();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, equals(ExitCode.usage.code));
|
||||
});
|
||||
|
||||
@@ -402,11 +402,8 @@ flutter:
|
||||
when(() => flutterBuildProcessResult.exitCode).thenReturn(1);
|
||||
when(() => flutterBuildProcessResult.stderr).thenReturn('oops');
|
||||
|
||||
final tempDir = setUpTempDir();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
});
|
||||
@@ -430,11 +427,8 @@ error: exportArchive: Communication with Apple failed
|
||||
error: exportArchive: No signing certificate "iOS Distribution" found
|
||||
''');
|
||||
|
||||
final tempDir = setUpTempDir();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(
|
||||
@@ -451,28 +445,28 @@ error: exportArchive: No signing certificate "iOS Distribution" found
|
||||
|
||||
group('when build directory has non-default structure', () {
|
||||
test('exits with code 70 if xcarchive is not found', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
Directory(p.join(tempDir.path, 'build')).deleteSync(recursive: true);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
Directory(
|
||||
p.join(projectRoot.path, 'build'),
|
||||
).deleteSync(recursive: true);
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(
|
||||
() => logger
|
||||
.err(any(that: contains('Unable to find .xcarchive directory'))),
|
||||
() => logger.err(
|
||||
any(that: contains('Unable to find .xcarchive directory')),
|
||||
),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('prints error and exits with code 70 if Info.plist does not exist',
|
||||
() async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final plistPath = p.join(
|
||||
tempDir.path,
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'ios',
|
||||
'archive',
|
||||
@@ -481,22 +475,20 @@ error: exportArchive: No signing certificate "iOS Distribution" found
|
||||
);
|
||||
File(plistPath).deleteSync();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(() => logger.err('No Info.plist file found at $plistPath.'))
|
||||
.called(1);
|
||||
verify(
|
||||
() => logger.err('No Info.plist file found at $plistPath.'),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test('finds xcarchive that has been renamed from Runner', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
Directory(
|
||||
p.join(
|
||||
tempDir.path,
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'ios',
|
||||
'archive',
|
||||
@@ -504,7 +496,7 @@ error: exportArchive: No signing certificate "iOS Distribution" found
|
||||
),
|
||||
).renameSync(
|
||||
p.join(
|
||||
tempDir.path,
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'ios',
|
||||
'archive',
|
||||
@@ -512,10 +504,7 @@ error: exportArchive: No signing certificate "iOS Distribution" found
|
||||
),
|
||||
);
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
});
|
||||
@@ -541,12 +530,9 @@ error: exportArchive: No signing certificate "iOS Distribution" found
|
||||
updatedAt: DateTime(2023),
|
||||
),
|
||||
);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.software.code);
|
||||
verify(() => logger.err('No iOS release found for 1.2.3+1.')).called(1);
|
||||
});
|
||||
@@ -571,12 +557,9 @@ error: exportArchive: No signing certificate "iOS Distribution" found
|
||||
updatedAt: DateTime(2023),
|
||||
),
|
||||
);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.software.code);
|
||||
verify(
|
||||
() => logger.err('''
|
||||
@@ -607,12 +590,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
updatedAt: DateTime(2023),
|
||||
),
|
||||
);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
});
|
||||
|
||||
@@ -621,13 +601,10 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
() async {
|
||||
const otherRevision = 'other-revision';
|
||||
when(() => shorebirdEnv.flutterRevision).thenReturn(otherRevision);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
// Verify that we switch back to the original revision once we're done.
|
||||
@@ -661,13 +638,10 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
when(() => flutterBuildProcessResult.exitCode).thenReturn(1);
|
||||
when(() => flutterBuildProcessResult.stderr).thenReturn('oops');
|
||||
});
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
},
|
||||
@@ -677,17 +651,15 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
const customReleaseVersion = 'custom-release-version';
|
||||
|
||||
setUp(() {
|
||||
when(() => argResults['release-version'])
|
||||
.thenReturn(customReleaseVersion);
|
||||
when(
|
||||
() => argResults['release-version'],
|
||||
).thenReturn(customReleaseVersion);
|
||||
});
|
||||
|
||||
test('does not extract release version from archive', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
await runWithOverrides(command.run);
|
||||
|
||||
verify(
|
||||
() => codePushClientWrapper.getRelease(
|
||||
@@ -700,12 +672,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
|
||||
group('when release-version option is not provided', () {
|
||||
test('extracts release version from app bundle', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
await runWithOverrides(command.run);
|
||||
|
||||
verify(
|
||||
() => codePushClientWrapper.getRelease(
|
||||
@@ -718,11 +687,11 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
|
||||
test('exits with code 70 when release version cannot be determiend',
|
||||
() async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final file = File(
|
||||
p.join(
|
||||
tempDir.path,
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'ios',
|
||||
'archive',
|
||||
@@ -733,10 +702,7 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync(emptyPlistContent);
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(
|
||||
@@ -748,13 +714,10 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
});
|
||||
|
||||
test('prints release version when detected', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verify(() => logger.info('Detected release version 1.2.3+1')).called(1);
|
||||
@@ -762,12 +725,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
|
||||
test('aborts when user opts out', () async {
|
||||
when(() => logger.confirm(any())).thenReturn(false);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
verify(() => logger.info('Aborting.')).called(1);
|
||||
});
|
||||
@@ -776,12 +736,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
const error = 'oops something went wrong';
|
||||
when(() => aotBuildProcessResult.exitCode).thenReturn(1);
|
||||
when(() => aotBuildProcessResult.stderr).thenReturn(error);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
verify(
|
||||
() => progress.fail('Exception: Failed to create snapshot: $error'),
|
||||
).called(1);
|
||||
@@ -800,13 +757,10 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
force: any(named: 'force'),
|
||||
),
|
||||
).thenThrow(UserCancelledException());
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verify(
|
||||
@@ -840,13 +794,10 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
force: any(named: 'force'),
|
||||
),
|
||||
).thenThrow(UnpatchableChangeException());
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(
|
||||
@@ -870,12 +821,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
|
||||
test('does not create patch on --dry-run', () async {
|
||||
when(() => argResults['dry-run']).thenReturn(true);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verifyNever(
|
||||
() => codePushClientWrapper.createPatch(
|
||||
@@ -888,12 +836,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
|
||||
test('does not prompt on --force', () async {
|
||||
when(() => argResults['force']).thenReturn(true);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verifyNever(() => logger.confirm(any()));
|
||||
verify(
|
||||
@@ -908,12 +853,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
});
|
||||
|
||||
test('succeeds when patch is successful (production)', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
verify(
|
||||
() => logger.info(
|
||||
any(
|
||||
@@ -939,12 +881,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
|
||||
test('succeeds when patch is successful (staging)', () async {
|
||||
when(() => argResults['staging']).thenReturn(true);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
verify(
|
||||
() => logger.info(
|
||||
any(
|
||||
@@ -970,13 +909,10 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
|
||||
test('runs flutter pub get with system flutter after successful build',
|
||||
() async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
await runWithOverrides(command.run);
|
||||
|
||||
verify(
|
||||
() => shorebirdProcess.run(
|
||||
@@ -990,12 +926,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
|
||||
test('forwards codesign to flutter build', () async {
|
||||
when(() => argResults['codesign']).thenReturn(false);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
await runWithOverrides(command.run);
|
||||
|
||||
verify(
|
||||
() => shorebirdProcess.run(
|
||||
@@ -1017,13 +950,10 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
|
||||
test('does not provide export options when codesign is false', () async {
|
||||
when(() => argResults['codesign']).thenReturn(false);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
await runWithOverrides(command.run);
|
||||
|
||||
final capturedArgs = verify(
|
||||
() => shorebirdProcess.run(
|
||||
@@ -1047,18 +977,15 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
const target = './lib/main_development.dart';
|
||||
when(() => argResults['flavor']).thenReturn(flavor);
|
||||
when(() => argResults['target']).thenReturn(target);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
File(
|
||||
p.join(tempDir.path, 'shorebird.yaml'),
|
||||
p.join(projectRoot.path, 'shorebird.yaml'),
|
||||
).writeAsStringSync('''
|
||||
app_id: productionAppId
|
||||
flavors:
|
||||
development: $appId''');
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
verify(
|
||||
() => codePushClientWrapper.publishPatch(
|
||||
@@ -1072,31 +999,25 @@ flavors:
|
||||
});
|
||||
|
||||
test('succeeds when patch is successful using custom base_url', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
const baseUrl = 'https://example.com';
|
||||
File(
|
||||
p.join(tempDir.path, 'shorebird.yaml'),
|
||||
p.join(projectRoot.path, 'shorebird.yaml'),
|
||||
).writeAsStringSync(
|
||||
'''
|
||||
app_id: $appId
|
||||
base_url: $baseUrl''',
|
||||
);
|
||||
await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
await runWithOverrides(command.run);
|
||||
});
|
||||
|
||||
test('does not prompt if running on CI', () async {
|
||||
when(() => shorebirdEnv.isRunningOnCI).thenReturn(true);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verifyNever(() => logger.confirm(any()));
|
||||
|
||||
+69
-109
@@ -77,6 +77,7 @@ flutter:
|
||||
late ArgResults argResults;
|
||||
late CodePushClientWrapper codePushClientWrapper;
|
||||
late Directory shorebirdRoot;
|
||||
late Directory projectRoot;
|
||||
late Directory flutterDirectory;
|
||||
late File genSnapshotFile;
|
||||
late Doctor doctor;
|
||||
@@ -116,11 +117,11 @@ flutter:
|
||||
);
|
||||
}
|
||||
|
||||
void setUpTempArtifacts(Directory dir) {
|
||||
void setUpProjectRootArtifacts() {
|
||||
// Create a second app.dill for coverage of newestAppDill file.
|
||||
File(
|
||||
p.join(
|
||||
dir.path,
|
||||
projectRoot.path,
|
||||
'.dart_tool',
|
||||
'flutter_build',
|
||||
'subdir',
|
||||
@@ -128,14 +129,15 @@ flutter:
|
||||
),
|
||||
).createSync(recursive: true);
|
||||
File(
|
||||
p.join(dir.path, '.dart_tool', 'flutter_build', 'app.dill'),
|
||||
p.join(projectRoot.path, '.dart_tool', 'flutter_build', 'app.dill'),
|
||||
).createSync(recursive: true);
|
||||
File(p.join(dir.path, 'build', elfAotSnapshotFileName)).createSync(
|
||||
File(p.join(projectRoot.path, 'build', elfAotSnapshotFileName))
|
||||
.createSync(
|
||||
recursive: true,
|
||||
);
|
||||
Directory(
|
||||
p.join(
|
||||
dir.path,
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'ios',
|
||||
'framework',
|
||||
@@ -147,15 +149,13 @@ flutter:
|
||||
);
|
||||
}
|
||||
|
||||
Directory setUpTempDir() {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
void setUpProjectRoot() {
|
||||
File(
|
||||
p.join(tempDir.path, 'pubspec.yaml'),
|
||||
p.join(projectRoot.path, 'pubspec.yaml'),
|
||||
).writeAsStringSync(pubspecYamlContent);
|
||||
File(
|
||||
p.join(tempDir.path, 'shorebird.yaml'),
|
||||
p.join(projectRoot.path, 'shorebird.yaml'),
|
||||
).writeAsStringSync('app_id: $appId');
|
||||
return tempDir;
|
||||
}
|
||||
|
||||
setUpAll(() {
|
||||
@@ -174,6 +174,7 @@ flutter:
|
||||
patchDiffChecker = MockPatchDiffChecker();
|
||||
platform = MockPlatform();
|
||||
shorebirdRoot = Directory.systemTemp.createTempSync();
|
||||
projectRoot = Directory.systemTemp.createTempSync();
|
||||
flutterDirectory = Directory(
|
||||
p.join(shorebirdRoot.path, 'bin', 'cache', 'flutter'),
|
||||
);
|
||||
@@ -232,11 +233,15 @@ flutter:
|
||||
when(() => logger.level).thenReturn(Level.info);
|
||||
when(() => logger.progress(any())).thenReturn(progress);
|
||||
when(() => logger.confirm(any())).thenReturn(true);
|
||||
when(() => operatingSystemInterface.which('flutter'))
|
||||
.thenReturn('/path/to/flutter');
|
||||
when(
|
||||
() => operatingSystemInterface.which('flutter'),
|
||||
).thenReturn('/path/to/flutter');
|
||||
when(() => platform.operatingSystem).thenReturn(Platform.macOS);
|
||||
when(() => shorebirdEnv.getShorebirdYaml()).thenReturn(shorebirdYaml);
|
||||
when(() => shorebirdEnv.shorebirdRoot).thenReturn(shorebirdRoot);
|
||||
when(
|
||||
() => shorebirdEnv.getShorebirdProjectRoot(),
|
||||
).thenReturn(projectRoot);
|
||||
when(() => shorebirdEnv.flutterDirectory).thenReturn(flutterDirectory);
|
||||
when(() => shorebirdEnv.genSnapshotFile).thenReturn(genSnapshotFile);
|
||||
when(() => shorebirdEnv.flutterRevision).thenReturn(flutterRevision);
|
||||
@@ -425,12 +430,9 @@ ${release.version}'''),
|
||||
),
|
||||
],
|
||||
);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.software.code);
|
||||
verify(
|
||||
() => logger.err('''
|
||||
@@ -457,12 +459,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
),
|
||||
],
|
||||
);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
});
|
||||
|
||||
@@ -471,13 +470,10 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
'when release flutter revision differs', () async {
|
||||
const otherRevision = 'other-revision';
|
||||
when(() => shorebirdEnv.flutterRevision).thenReturn(otherRevision);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verify(
|
||||
() => logger.progress(
|
||||
@@ -511,20 +507,17 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
environment: any(named: 'environment'),
|
||||
),
|
||||
).thenAnswer((_) async => flutterBuildProcessResult);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
await IOOverrides.runZoned(
|
||||
() => runWithOverrides(
|
||||
() => runScoped(
|
||||
() => command.run(),
|
||||
values: {
|
||||
processRef.overrideWith(
|
||||
() => ShorebirdProcess(processWrapper: processWrapper),
|
||||
),
|
||||
},
|
||||
),
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
await runWithOverrides(
|
||||
() => runScoped(
|
||||
() => command.run(),
|
||||
values: {
|
||||
processRef.overrideWith(
|
||||
() => ShorebirdProcess(processWrapper: processWrapper),
|
||||
),
|
||||
},
|
||||
),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
verify(
|
||||
() => processWrapper.run(
|
||||
@@ -556,13 +549,10 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
revision: any(named: 'revision'),
|
||||
),
|
||||
).thenThrow(exception);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(
|
||||
() => logger.progress(
|
||||
@@ -579,12 +569,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
|
||||
test('aborts when user opts out', () async {
|
||||
when(() => logger.confirm(any())).thenReturn(false);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
verify(() => logger.info('Aborting.')).called(1);
|
||||
});
|
||||
@@ -593,12 +580,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
when(() => flutterBuildProcessResult.exitCode).thenReturn(1);
|
||||
when(() => flutterBuildProcessResult.stderr).thenReturn('oh no');
|
||||
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.software.code);
|
||||
verify(() => progress.fail('Failed to build: oh no')).called(1);
|
||||
});
|
||||
@@ -607,12 +591,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
const error = 'oops something went wrong';
|
||||
when(() => aotBuildProcessResult.exitCode).thenReturn(1);
|
||||
when(() => aotBuildProcessResult.stderr).thenReturn(error);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
verify(
|
||||
() => progress.fail('Exception: Failed to create snapshot: $error'),
|
||||
).called(1);
|
||||
@@ -631,13 +612,10 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
force: any(named: 'force'),
|
||||
),
|
||||
).thenThrow(UserCancelledException());
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verify(
|
||||
@@ -671,13 +649,10 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
force: any(named: 'force'),
|
||||
),
|
||||
).thenThrow(UnpatchableChangeException());
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(
|
||||
@@ -701,12 +676,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
|
||||
test('does not create patch on --dry-run', () async {
|
||||
when(() => argResults['dry-run']).thenReturn(true);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verifyNever(
|
||||
() => codePushClientWrapper.createPatch(
|
||||
@@ -719,12 +691,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
|
||||
test('does not prompt on --force', () async {
|
||||
when(() => argResults['force']).thenReturn(true);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verifyNever(() => logger.confirm(any()));
|
||||
verify(
|
||||
@@ -739,12 +708,9 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
});
|
||||
|
||||
test('succeeds when patch is successful', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
verify(
|
||||
() => logger.info(
|
||||
any(
|
||||
@@ -770,13 +736,10 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
|
||||
test('runs flutter pub get with system flutter after successful build',
|
||||
() async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
await runWithOverrides(command.run);
|
||||
|
||||
verify(
|
||||
() => shorebirdProcess.run(
|
||||
@@ -790,13 +753,10 @@ Please re-run the release command for this version or create a new release.'''),
|
||||
|
||||
test('does not prompt if running on CI', () async {
|
||||
when(() => shorebirdEnv.isRunningOnCI).thenReturn(true);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpTempArtifacts(tempDir);
|
||||
setUpProjectRoot();
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verifyNever(() => logger.confirm(any()));
|
||||
|
||||
@@ -59,6 +59,7 @@ void main() {
|
||||
late Auth auth;
|
||||
late CodePushClientWrapper codePushClientWrapper;
|
||||
late Directory shorebirdRoot;
|
||||
late Directory projectRoot;
|
||||
late Java java;
|
||||
late OperatingSystemInterface operatingSystemInterface;
|
||||
late Platform platform;
|
||||
@@ -89,10 +90,9 @@ void main() {
|
||||
);
|
||||
}
|
||||
|
||||
Directory setUpTempArtifacts() {
|
||||
final dir = Directory.systemTemp.createTempSync();
|
||||
void setUpProjectRootArtifacts() {
|
||||
final aarDir = p.join(
|
||||
dir.path,
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'host',
|
||||
'outputs',
|
||||
@@ -116,7 +116,6 @@ void main() {
|
||||
File(artifactPath).createSync(recursive: true);
|
||||
}
|
||||
File(aarPath).createSync(recursive: true);
|
||||
return dir;
|
||||
}
|
||||
|
||||
setUpAll(() {
|
||||
@@ -140,6 +139,7 @@ void main() {
|
||||
flutterPubGetProcessResult = MockProcessResult();
|
||||
shorebirdProcess = MockShorebirdProcess();
|
||||
shorebirdRoot = Directory.systemTemp.createTempSync();
|
||||
projectRoot = Directory.systemTemp.createTempSync();
|
||||
shorebirdEnv = MockShorebirdEnv();
|
||||
shorebirdValidator = MockShorebirdValidator();
|
||||
|
||||
@@ -155,6 +155,9 @@ void main() {
|
||||
|
||||
when(() => shorebirdEnv.getShorebirdYaml()).thenReturn(shorebirdYaml);
|
||||
when(() => shorebirdEnv.shorebirdRoot).thenReturn(shorebirdRoot);
|
||||
when(
|
||||
() => shorebirdEnv.getShorebirdProjectRoot(),
|
||||
).thenReturn(projectRoot);
|
||||
when(
|
||||
() => shorebirdEnv.androidPackageName,
|
||||
).thenReturn(androidPackageName);
|
||||
@@ -302,22 +305,16 @@ void main() {
|
||||
defaultValue: any(named: 'defaultValue'),
|
||||
),
|
||||
).thenAnswer((_) => '1.0.0');
|
||||
final tempDir = setUpTempArtifacts();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
verify(() => logger.info('Aborting.')).called(1);
|
||||
});
|
||||
|
||||
test('does not prompt for confirmation when --force is used', () async {
|
||||
when(() => argResults['force']).thenReturn(true);
|
||||
final tempDir = setUpTempArtifacts();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
verify(() => logger.success('\n✅ Published Release!')).called(1);
|
||||
verifyNever(
|
||||
@@ -326,11 +323,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('succeeds when release is successful', () async {
|
||||
final tempDir = setUpTempArtifacts();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
verify(() => logger.success('\n✅ Published Release!')).called(1);
|
||||
verify(
|
||||
@@ -386,23 +380,20 @@ void main() {
|
||||
});
|
||||
|
||||
test('copies aar library to a releases folder', () async {
|
||||
final tempDir = setUpTempArtifacts();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
expect(Directory(p.join(tempDir.path, 'release')).existsSync(), isTrue);
|
||||
expect(
|
||||
Directory(p.join(projectRoot.path, 'release')).existsSync(),
|
||||
isTrue,
|
||||
);
|
||||
});
|
||||
|
||||
test('runs flutter pub get with system flutter after successful build',
|
||||
() async {
|
||||
final tempDir = setUpTempArtifacts();
|
||||
setUpProjectRootArtifacts();
|
||||
|
||||
await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
await runWithOverrides(command.run);
|
||||
|
||||
verify(
|
||||
() => shorebirdProcess.run(
|
||||
@@ -422,11 +413,8 @@ void main() {
|
||||
releaseVersion: any(named: 'releaseVersion'),
|
||||
),
|
||||
).thenAnswer((_) async => release);
|
||||
final tempDir = setUpTempArtifacts();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRootArtifacts();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
verifyNever(
|
||||
() => codePushClientWrapper.createRelease(
|
||||
|
||||
@@ -62,6 +62,7 @@ void main() {
|
||||
late http.Client httpClient;
|
||||
late CodePushClientWrapper codePushClientWrapper;
|
||||
late Directory shorebirdRoot;
|
||||
late Directory projectRoot;
|
||||
late Doctor doctor;
|
||||
late Platform platform;
|
||||
late Auth auth;
|
||||
@@ -115,6 +116,7 @@ void main() {
|
||||
operatingSystemInterface = MockOperatingSystemInterface();
|
||||
platform = MockPlatform();
|
||||
shorebirdRoot = Directory.systemTemp.createTempSync();
|
||||
projectRoot = Directory.systemTemp.createTempSync();
|
||||
auth = MockAuth();
|
||||
cache = MockCache();
|
||||
java = MockJava();
|
||||
@@ -129,6 +131,9 @@ void main() {
|
||||
|
||||
when(() => shorebirdEnv.getShorebirdYaml()).thenReturn(shorebirdYaml);
|
||||
when(() => shorebirdEnv.shorebirdRoot).thenReturn(shorebirdRoot);
|
||||
when(
|
||||
() => shorebirdEnv.getShorebirdProjectRoot(),
|
||||
).thenReturn(projectRoot);
|
||||
when(() => shorebirdEnv.flutterRevision).thenReturn(flutterRevision);
|
||||
when(() => shorebirdEnv.isRunningOnCI).thenReturn(false);
|
||||
|
||||
@@ -195,6 +200,7 @@ void main() {
|
||||
() => codePushClientWrapper.createAndroidReleaseArtifacts(
|
||||
appId: any(named: 'appId'),
|
||||
releaseId: any(named: 'releaseId'),
|
||||
projectRoot: any(named: 'projectRoot'),
|
||||
aabPath: any(named: 'aabPath'),
|
||||
platform: any(named: 'platform'),
|
||||
architectures: any(named: 'architectures'),
|
||||
@@ -335,6 +341,7 @@ void main() {
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
verify(() => logger.success('\n✅ Published Release!')).called(1);
|
||||
final aabPath = p.join(
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
@@ -358,6 +365,7 @@ ${link(uri: Uri.parse('https://support.google.com/googleplay/android-developer/a
|
||||
appId: appId,
|
||||
releaseId: release.id,
|
||||
platform: releasePlatform,
|
||||
projectRoot: any(named: 'projectRoot'),
|
||||
aabPath: any(named: 'aabPath'),
|
||||
architectures: any(named: 'architectures'),
|
||||
),
|
||||
@@ -379,6 +387,7 @@ ${link(uri: Uri.parse('https://support.google.com/googleplay/android-developer/a
|
||||
verify(() => logger.success('\n✅ Published Release!')).called(1);
|
||||
// Verify info message does include apk instructions.
|
||||
final aabPath = p.join(
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
@@ -387,6 +396,7 @@ ${link(uri: Uri.parse('https://support.google.com/googleplay/android-developer/a
|
||||
'app-release.aab',
|
||||
);
|
||||
final apkPath = p.join(
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'app',
|
||||
'outputs',
|
||||
@@ -412,6 +422,7 @@ ${link(uri: Uri.parse('https://support.google.com/googleplay/android-developer/a
|
||||
appId: appId,
|
||||
releaseId: release.id,
|
||||
platform: releasePlatform,
|
||||
projectRoot: any(named: 'projectRoot'),
|
||||
aabPath: any(named: 'aabPath'),
|
||||
architectures: any(named: 'architectures'),
|
||||
),
|
||||
@@ -568,6 +579,7 @@ Either run `flutter pub get` manually, or follow the steps in ${link(uri: Uri.pa
|
||||
appId: appId,
|
||||
releaseId: release.id,
|
||||
platform: releasePlatform,
|
||||
projectRoot: any(named: 'projectRoot'),
|
||||
aabPath: any(named: 'aabPath'),
|
||||
architectures: any(named: 'architectures'),
|
||||
flavor: flavor,
|
||||
|
||||
@@ -107,6 +107,7 @@ flutter:
|
||||
late ArgResults argResults;
|
||||
late CodePushClientWrapper codePushClientWrapper;
|
||||
late Directory shorebirdRoot;
|
||||
late Directory projectRoot;
|
||||
late Doctor doctor;
|
||||
late Platform platform;
|
||||
late Auth auth;
|
||||
@@ -138,17 +139,16 @@ flutter:
|
||||
);
|
||||
}
|
||||
|
||||
Directory setUpTempDir() {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
void setUpProjectRoot() {
|
||||
File(
|
||||
p.join(tempDir.path, 'pubspec.yaml'),
|
||||
p.join(projectRoot.path, 'pubspec.yaml'),
|
||||
).writeAsStringSync(pubspecYamlContent);
|
||||
File(
|
||||
p.join(tempDir.path, 'shorebird.yaml'),
|
||||
p.join(projectRoot.path, 'shorebird.yaml'),
|
||||
).writeAsStringSync('app_id: $appId');
|
||||
File(
|
||||
p.join(
|
||||
tempDir.path,
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'ios',
|
||||
'archive',
|
||||
@@ -160,7 +160,7 @@ flutter:
|
||||
..writeAsStringSync(infoPlistContent);
|
||||
Directory(
|
||||
p.join(
|
||||
tempDir.path,
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'ios',
|
||||
'archive',
|
||||
@@ -170,8 +170,7 @@ flutter:
|
||||
'Runner.app',
|
||||
),
|
||||
).createSync(recursive: true);
|
||||
File(p.join(tempDir.path, ipaPath)).createSync(recursive: true);
|
||||
return tempDir;
|
||||
File(p.join(projectRoot.path, ipaPath)).createSync(recursive: true);
|
||||
}
|
||||
|
||||
setUpAll(() {
|
||||
@@ -187,6 +186,7 @@ flutter:
|
||||
doctor = MockDoctor();
|
||||
platform = MockPlatform();
|
||||
shorebirdRoot = Directory.systemTemp.createTempSync();
|
||||
projectRoot = Directory.systemTemp.createTempSync();
|
||||
auth = MockAuth();
|
||||
operatingSystemInterface = MockOperatingSystemInterface();
|
||||
progress = MockProgress();
|
||||
@@ -200,6 +200,9 @@ flutter:
|
||||
|
||||
when(() => shorebirdEnv.getShorebirdYaml()).thenReturn(shorebirdYaml);
|
||||
when(() => shorebirdEnv.shorebirdRoot).thenReturn(shorebirdRoot);
|
||||
when(
|
||||
() => shorebirdEnv.getShorebirdProjectRoot(),
|
||||
).thenReturn(projectRoot);
|
||||
when(() => shorebirdEnv.flutterRevision).thenReturn(flutterRevision);
|
||||
when(() => shorebirdEnv.isRunningOnCI).thenReturn(false);
|
||||
when(
|
||||
@@ -233,14 +236,16 @@ flutter:
|
||||
when(
|
||||
() => logger.prompt(any(), defaultValue: any(named: 'defaultValue')),
|
||||
).thenReturn(version);
|
||||
when(() => operatingSystemInterface.which('flutter'))
|
||||
.thenReturn('/path/to/flutter');
|
||||
when(
|
||||
() => operatingSystemInterface.which('flutter'),
|
||||
).thenReturn('/path/to/flutter');
|
||||
when(() => platform.operatingSystem).thenReturn(Platform.macOS);
|
||||
when(
|
||||
() => flutterBuildProcessResult.exitCode,
|
||||
).thenReturn(ExitCode.success.code);
|
||||
when(() => flutterPubGetProcessResult.exitCode)
|
||||
.thenReturn(ExitCode.success.code);
|
||||
when(
|
||||
() => flutterPubGetProcessResult.exitCode,
|
||||
).thenReturn(ExitCode.success.code);
|
||||
when(
|
||||
() => codePushClientWrapper.getApp(appId: any(named: 'appId')),
|
||||
).thenAnswer((_) async => appMetadata);
|
||||
@@ -330,11 +335,8 @@ flutter:
|
||||
});
|
||||
|
||||
test('prints instructions to manually codesign', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
await runWithOverrides(command.run);
|
||||
|
||||
verify(
|
||||
() => logger.info(
|
||||
@@ -344,11 +346,8 @@ flutter:
|
||||
});
|
||||
|
||||
test('builds without codesigning', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
await runWithOverrides(command.run);
|
||||
|
||||
verify(
|
||||
() => shorebirdProcess.run(
|
||||
@@ -371,10 +370,10 @@ flutter:
|
||||
group('when build directory has non-default structure', () {
|
||||
test('prints error and exits with code 70 if xcarchive does not exist',
|
||||
() async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
Directory(
|
||||
p.join(
|
||||
tempDir.path,
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'ios',
|
||||
'archive',
|
||||
@@ -382,23 +381,21 @@ flutter:
|
||||
),
|
||||
).deleteSync(recursive: true);
|
||||
|
||||
final result = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.software.code));
|
||||
verify(() => logger.err('Unable to find .xcarchive directory'))
|
||||
.called(1);
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(
|
||||
() => logger.err('Unable to find .xcarchive directory'),
|
||||
).called(1);
|
||||
});
|
||||
|
||||
test(
|
||||
'''prints error and exits with code 70 if .app directory does not exist''',
|
||||
() async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
Directory(
|
||||
p.join(
|
||||
tempDir.path,
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'ios',
|
||||
'archive',
|
||||
@@ -408,21 +405,18 @@ flutter:
|
||||
),
|
||||
).deleteSync(recursive: true);
|
||||
|
||||
final result = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.software.code));
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(() => logger.err('Unable to find .app directory')).called(1);
|
||||
});
|
||||
|
||||
test(
|
||||
'''finds .xcarchive and .app when they do not have the default "Runner" name''',
|
||||
() async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
final archivePath = p.join(
|
||||
tempDir.path,
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'ios',
|
||||
'archive',
|
||||
@@ -446,24 +440,19 @@ flutter:
|
||||
),
|
||||
);
|
||||
|
||||
final result = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.success.code));
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
});
|
||||
});
|
||||
|
||||
test('prints archive upload instructions on success', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
final result = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.success.code));
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
final archivePath = p.join(
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'ios',
|
||||
'archive',
|
||||
@@ -475,10 +464,10 @@ flutter:
|
||||
that: stringContainsInOrder(
|
||||
[
|
||||
'Your next step is to submit the archive',
|
||||
archivePath,
|
||||
p.relative(archivePath),
|
||||
'to the App Store using Xcode.',
|
||||
'You can open the archive in Xcode by running',
|
||||
'open $archivePath',
|
||||
'open ${p.relative(archivePath)}',
|
||||
'''Make sure to uncheck "Manage Version and Build Number", or else shorebird will not work.''',
|
||||
],
|
||||
),
|
||||
@@ -488,20 +477,19 @@ flutter:
|
||||
});
|
||||
|
||||
test('creates unsigned release artifacts', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
final result = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.success.code));
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
|
||||
verify(
|
||||
() => codePushClientWrapper.createIosReleaseArtifacts(
|
||||
appId: appId,
|
||||
releaseId: release.id,
|
||||
xcarchivePath:
|
||||
any(named: 'xcarchivePath', that: endsWith('.xcarchive')),
|
||||
xcarchivePath: any(
|
||||
named: 'xcarchivePath',
|
||||
that: endsWith('.xcarchive'),
|
||||
),
|
||||
runnerPath: any(named: 'runnerPath', that: endsWith('Runner.app')),
|
||||
isCodesigned: false,
|
||||
),
|
||||
@@ -512,18 +500,16 @@ flutter:
|
||||
group('when both export-method and export-options-plist are provided', () {
|
||||
setUp(() {
|
||||
when(() => argResults.wasParsed(exportMethodArgName)).thenReturn(true);
|
||||
when(() => argResults[exportOptionsPlistArgName])
|
||||
.thenReturn('/path/to/export.plist');
|
||||
when(
|
||||
() => argResults[exportOptionsPlistArgName],
|
||||
).thenReturn('/path/to/export.plist');
|
||||
});
|
||||
|
||||
test('logs error and exits with usage code', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
final result = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.usage.code));
|
||||
expect(exitCode, equals(ExitCode.usage.code));
|
||||
verify(
|
||||
() => logger.err(
|
||||
'Cannot specify both --export-method and --export-options-plist.',
|
||||
@@ -542,11 +528,8 @@ flutter:
|
||||
|
||||
test('generates an export options plist with that export method',
|
||||
() async {
|
||||
final tempDir = setUpTempDir();
|
||||
await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
await runWithOverrides(command.run);
|
||||
|
||||
final capturedArgs = verify(
|
||||
() => shorebirdProcess.run(
|
||||
@@ -578,13 +561,10 @@ flutter:
|
||||
});
|
||||
|
||||
test('exits with usage code', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
final result = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.usage.code));
|
||||
expect(exitCode, equals(ExitCode.usage.code));
|
||||
verify(
|
||||
() => logger.err(
|
||||
'Exception: Export options plist file /does/not/exist does not exist',
|
||||
@@ -604,18 +584,16 @@ flutter:
|
||||
''';
|
||||
|
||||
test('exits with usage code', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
final exportPlistFile = File(
|
||||
p.join(tempDir.path, 'export.plist'),
|
||||
p.join(projectRoot.path, 'export.plist'),
|
||||
)..writeAsStringSync(exportPlistContent);
|
||||
when(() => argResults[exportOptionsPlistArgName])
|
||||
.thenReturn(exportPlistFile.path);
|
||||
final result = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
when(
|
||||
() => argResults[exportOptionsPlistArgName],
|
||||
).thenReturn(exportPlistFile.path);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(result, equals(ExitCode.usage.code));
|
||||
expect(exitCode, equals(ExitCode.usage.code));
|
||||
verify(
|
||||
() => logger.err(
|
||||
'''Exception: Export options plist ${exportPlistFile.path} does not set manageAppVersionAndBuildNumber to false. This is required for shorebird to work.''',
|
||||
@@ -634,11 +612,8 @@ flutter:
|
||||
|
||||
test('generates an export options plist with app-store export method',
|
||||
() async {
|
||||
final tempDir = setUpTempDir();
|
||||
await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
await runWithOverrides(command.run);
|
||||
|
||||
final capturedArgs = verify(
|
||||
() => shorebirdProcess.run(
|
||||
@@ -667,11 +642,8 @@ flutter:
|
||||
when(() => flutterBuildProcessResult.exitCode).thenReturn(1);
|
||||
when(() => flutterBuildProcessResult.stderr).thenReturn('oops');
|
||||
|
||||
final tempDir = setUpTempDir();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(
|
||||
@@ -697,11 +669,8 @@ error: exportArchive: Communication with Apple failed
|
||||
error: exportArchive: No signing certificate "iOS Distribution" found
|
||||
''');
|
||||
|
||||
final tempDir = setUpTempDir();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(
|
||||
@@ -718,10 +687,10 @@ error: exportArchive: No signing certificate "iOS Distribution" found
|
||||
|
||||
test('exits with code 70 when release version cannot be determined',
|
||||
() async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
final file = File(
|
||||
p.join(
|
||||
tempDir.path,
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'ios',
|
||||
'archive',
|
||||
@@ -731,10 +700,7 @@ error: exportArchive: No signing certificate "iOS Distribution" found
|
||||
)
|
||||
..createSync(recursive: true)
|
||||
..writeAsStringSync(emptyPlistContent);
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(
|
||||
@@ -747,12 +713,9 @@ error: exportArchive: No signing certificate "iOS Distribution" found
|
||||
|
||||
test('aborts when user opts out', () async {
|
||||
when(() => logger.confirm(any())).thenReturn(false);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
verify(() => logger.info('Aborting.')).called(1);
|
||||
@@ -769,10 +732,10 @@ error: exportArchive: No signing certificate "iOS Distribution" found
|
||||
});
|
||||
|
||||
test('exits with code 70 if Info.plist does not exist', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
final infoPlistFile = File(
|
||||
p.join(
|
||||
tempDir.path,
|
||||
projectRoot.path,
|
||||
'build',
|
||||
'ios',
|
||||
'archive',
|
||||
@@ -781,10 +744,7 @@ error: exportArchive: No signing certificate "iOS Distribution" found
|
||||
),
|
||||
)..deleteSync(recursive: true);
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(
|
||||
@@ -793,28 +753,22 @@ error: exportArchive: No signing certificate "iOS Distribution" found
|
||||
});
|
||||
|
||||
test('exits with code 70 if build directory does not exist', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
Directory(p.join(tempDir.path, 'build')).deleteSync(recursive: true);
|
||||
setUpProjectRoot();
|
||||
Directory(p.join(projectRoot.path, 'build')).deleteSync(recursive: true);
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(() => logger.err('Unable to find .xcarchive directory')).called(1);
|
||||
});
|
||||
|
||||
test('exits with code 70 if ipa build directory does not exist', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
final ipaDirectory =
|
||||
Directory(p.join(tempDir.path, 'build', 'ios', 'ipa'))
|
||||
..deleteSync(recursive: true);
|
||||
setUpProjectRoot();
|
||||
final ipaDirectory = Directory(
|
||||
p.join(projectRoot.path, 'build', 'ios', 'ipa'),
|
||||
)..deleteSync(recursive: true);
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(
|
||||
@@ -832,13 +786,10 @@ error: exportArchive: No signing certificate "iOS Distribution" found
|
||||
});
|
||||
|
||||
test('exits with code 70 if ipa file does not exist', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
File(p.join(tempDir.path, ipaPath)).deleteSync(recursive: true);
|
||||
setUpProjectRoot();
|
||||
File(p.join(projectRoot.path, ipaPath)).deleteSync(recursive: true);
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(
|
||||
@@ -855,14 +806,12 @@ error: exportArchive: No signing certificate "iOS Distribution" found
|
||||
});
|
||||
|
||||
test('exits with code 70 if more than one ipa file is found', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
File(p.join(tempDir.path, 'build/ios/ipa/Runner2.ipa'))
|
||||
.createSync(recursive: true);
|
||||
setUpProjectRoot();
|
||||
File(
|
||||
p.join(projectRoot.path, 'build/ios/ipa/Runner2.ipa'),
|
||||
).createSync(recursive: true);
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(
|
||||
@@ -883,12 +832,9 @@ error: exportArchive: No signing certificate "iOS Distribution" found
|
||||
'when --release-version and --force are used', () async {
|
||||
when(() => argResults['force']).thenReturn(true);
|
||||
when(() => argResults['release-version']).thenReturn(version);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
verify(() => logger.success('\n✅ Published Release!')).called(1);
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
@@ -906,12 +852,9 @@ error: exportArchive: No signing certificate "iOS Distribution" found
|
||||
});
|
||||
|
||||
test('succeeds when release is successful', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
verify(() => logger.success('\n✅ Published Release!')).called(1);
|
||||
verify(
|
||||
@@ -949,12 +892,9 @@ error: exportArchive: No signing certificate "iOS Distribution" found
|
||||
|
||||
test('runs flutter pub get with system flutter after successful build',
|
||||
() async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
|
||||
await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
await runWithOverrides(command.run);
|
||||
|
||||
verify(
|
||||
() => shorebirdProcess.run(
|
||||
@@ -973,18 +913,15 @@ error: exportArchive: No signing certificate "iOS Distribution" found
|
||||
final target = p.join('lib', 'main_development.dart');
|
||||
when(() => argResults['flavor']).thenReturn(flavor);
|
||||
when(() => argResults['target']).thenReturn(target);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
File(
|
||||
p.join(tempDir.path, 'shorebird.yaml'),
|
||||
p.join(projectRoot.path, 'shorebird.yaml'),
|
||||
).writeAsStringSync('''
|
||||
app_id: productionAppId
|
||||
flavors:
|
||||
development: $appId''');
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
verify(() => logger.success('\n✅ Published Release!')).called(1);
|
||||
verify(
|
||||
@@ -1020,12 +957,9 @@ flavors:
|
||||
releaseVersion: any(named: 'releaseVersion'),
|
||||
),
|
||||
).thenAnswer((_) async => release);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
verifyNever(
|
||||
@@ -1058,12 +992,9 @@ flavors:
|
||||
|
||||
test('provides appropriate ExportOptions.plist to build ipa command',
|
||||
() async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
final capturedArgs = verify(
|
||||
@@ -1093,12 +1024,9 @@ flavors:
|
||||
|
||||
test('does not provide export options when codesign is false', () async {
|
||||
when(() => argResults['codesign']).thenReturn(false);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
|
||||
await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
await runWithOverrides(command.run);
|
||||
|
||||
final capturedArgs = verify(
|
||||
() => shorebirdProcess.run(
|
||||
@@ -1117,12 +1045,9 @@ flavors:
|
||||
|
||||
test('does not prompt if running on CI', () async {
|
||||
when(() => shorebirdEnv.isRunningOnCI).thenReturn(true);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.success.code));
|
||||
verifyNever(() => logger.confirm(any()));
|
||||
|
||||
+24
-37
@@ -63,6 +63,7 @@ flutter:
|
||||
late ArgResults argResults;
|
||||
late CodePushClientWrapper codePushClientWrapper;
|
||||
late Directory shorebirdRoot;
|
||||
late Directory projectRoot;
|
||||
late Doctor doctor;
|
||||
late Platform platform;
|
||||
late Auth auth;
|
||||
@@ -94,15 +95,13 @@ flutter:
|
||||
);
|
||||
}
|
||||
|
||||
Directory setUpTempDir() {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
void setUpProjectRoot() {
|
||||
File(
|
||||
p.join(tempDir.path, 'pubspec.yaml'),
|
||||
p.join(projectRoot.path, 'pubspec.yaml'),
|
||||
).writeAsStringSync(pubspecYamlContent);
|
||||
File(
|
||||
p.join(tempDir.path, 'shorebird.yaml'),
|
||||
p.join(projectRoot.path, 'shorebird.yaml'),
|
||||
).writeAsStringSync('app_id: $appId');
|
||||
return tempDir;
|
||||
}
|
||||
|
||||
setUpAll(() {
|
||||
@@ -119,6 +118,7 @@ flutter:
|
||||
doctor = MockDoctor();
|
||||
platform = MockPlatform();
|
||||
shorebirdRoot = Directory.systemTemp.createTempSync();
|
||||
projectRoot = Directory.systemTemp.createTempSync();
|
||||
auth = MockAuth();
|
||||
progress = MockProgress();
|
||||
logger = MockLogger();
|
||||
@@ -132,6 +132,9 @@ flutter:
|
||||
|
||||
when(() => shorebirdEnv.getShorebirdYaml()).thenReturn(shorebirdYaml);
|
||||
when(() => shorebirdEnv.shorebirdRoot).thenReturn(shorebirdRoot);
|
||||
when(
|
||||
() => shorebirdEnv.getShorebirdProjectRoot(),
|
||||
).thenReturn(projectRoot);
|
||||
when(() => shorebirdEnv.flutterRevision).thenReturn(flutterRevision);
|
||||
when(
|
||||
() => shorebirdProcess.run(
|
||||
@@ -247,11 +250,8 @@ flutter:
|
||||
when(() => flutterBuildProcessResult.exitCode).thenReturn(1);
|
||||
when(() => flutterBuildProcessResult.stderr).thenReturn('oops');
|
||||
|
||||
final tempDir = setUpTempDir();
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
setUpProjectRoot();
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, equals(ExitCode.software.code));
|
||||
verify(
|
||||
@@ -266,12 +266,9 @@ flutter:
|
||||
releaseVersion: any(named: 'releaseVersion'),
|
||||
),
|
||||
).thenAnswer((_) async => release);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
|
||||
await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
await runWithOverrides(command.run);
|
||||
|
||||
verify(
|
||||
() => codePushClientWrapper.ensureReleaseIsNotActive(
|
||||
@@ -283,12 +280,9 @@ flutter:
|
||||
|
||||
test('aborts when user opts out', () async {
|
||||
when(() => logger.confirm(any())).thenReturn(false);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
verify(() => logger.info('Aborting.')).called(1);
|
||||
@@ -296,8 +290,10 @@ flutter:
|
||||
() => codePushClientWrapper.createIosReleaseArtifacts(
|
||||
appId: appId,
|
||||
releaseId: release.id,
|
||||
xcarchivePath:
|
||||
any(named: 'xcarchivePath', that: endsWith('.xcarchive')),
|
||||
xcarchivePath: any(
|
||||
named: 'xcarchivePath',
|
||||
that: endsWith('.xcarchive'),
|
||||
),
|
||||
runnerPath: any(named: 'runnerPath', that: endsWith('Runner.app')),
|
||||
isCodesigned: any(named: 'isCodesigned'),
|
||||
),
|
||||
@@ -309,12 +305,9 @@ flutter:
|
||||
'when --release-version and --force are used', () async {
|
||||
when(() => argResults['force']).thenReturn(true);
|
||||
when(() => argResults['release-version']).thenReturn(version);
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
verify(() => logger.success('\n✅ Published Release!')).called(1);
|
||||
expect(exitCode, ExitCode.success.code);
|
||||
@@ -332,12 +325,9 @@ flutter:
|
||||
});
|
||||
|
||||
test('succeeds when release is successful', () async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
|
||||
final exitCode = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
verify(() => logger.success('\n✅ Published Release!')).called(1);
|
||||
verify(
|
||||
@@ -378,12 +368,9 @@ flutter:
|
||||
|
||||
test('runs flutter pub get with system flutter after successful build',
|
||||
() async {
|
||||
final tempDir = setUpTempDir();
|
||||
setUpProjectRoot();
|
||||
|
||||
await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
await runWithOverrides(command.run);
|
||||
|
||||
verify(
|
||||
() => shorebirdProcess.run(
|
||||
|
||||
@@ -114,13 +114,11 @@ Please use "shorebird preview" instead.'''),
|
||||
});
|
||||
|
||||
test('exits with code when running the app fails', () async {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
|
||||
final progress = MockProgress();
|
||||
when(() => logger.progress(any())).thenReturn(progress);
|
||||
|
||||
const error = 'oops something went wrong';
|
||||
const exitCode = 1;
|
||||
const expectedExitCode = 1;
|
||||
when(
|
||||
() => process.stdout,
|
||||
).thenAnswer((_) => const Stream.empty());
|
||||
@@ -128,20 +126,15 @@ Please use "shorebird preview" instead.'''),
|
||||
when(() => process.stderr).thenAnswer(
|
||||
(_) => Stream.value(utf8.encode(error)),
|
||||
);
|
||||
when(() => process.exitCode).thenAnswer((_) async => exitCode);
|
||||
when(() => process.exitCode).thenAnswer((_) async => expectedExitCode);
|
||||
|
||||
final result = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
await expectLater(result, equals(exitCode));
|
||||
await expectLater(exitCode, equals(expectedExitCode));
|
||||
verify(() => logger.err(error)).called(1);
|
||||
});
|
||||
|
||||
test('exits with code 0 when running the app succeeds', () async {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
|
||||
final progress = MockProgress();
|
||||
when(() => logger.progress(any())).thenReturn(progress);
|
||||
|
||||
@@ -155,19 +148,14 @@ Please use "shorebird preview" instead.'''),
|
||||
() => process.exitCode,
|
||||
).thenAnswer((_) async => ExitCode.success.code);
|
||||
|
||||
final result = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
await expectLater(result, equals(ExitCode.success.code));
|
||||
await expectLater(exitCode, equals(ExitCode.success.code));
|
||||
verify(() => logger.info(output)).called(1);
|
||||
verify(() => ioSink.addStream(any())).called(1);
|
||||
});
|
||||
|
||||
test('passes additional args when specified', () async {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
|
||||
final progress = MockProgress();
|
||||
when(() => logger.progress(any())).thenReturn(progress);
|
||||
|
||||
@@ -187,10 +175,7 @@ Please use "shorebird preview" instead.'''),
|
||||
() => process.exitCode,
|
||||
).thenAnswer((_) async => ExitCode.success.code);
|
||||
|
||||
final result = await IOOverrides.runZoned(
|
||||
() => runWithOverrides(command.run),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
final exitCode = await runWithOverrides(command.run);
|
||||
|
||||
final args = verify(
|
||||
() => shorebirdProcess.start(
|
||||
@@ -212,7 +197,7 @@ Please use "shorebird preview" instead.'''),
|
||||
]),
|
||||
);
|
||||
|
||||
await expectLater(result, equals(ExitCode.success.code));
|
||||
await expectLater(exitCode, equals(ExitCode.success.code));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -60,6 +60,8 @@ class MockCodePushClientWrapper extends Mock implements CodePushClientWrapper {}
|
||||
|
||||
class MockDevicectl extends Mock implements Devicectl {}
|
||||
|
||||
class MockDirectory extends Mock implements Directory {}
|
||||
|
||||
class MockDoctor extends Mock implements Doctor {}
|
||||
|
||||
class MockFile extends Mock implements File {}
|
||||
|
||||
@@ -45,6 +45,103 @@ void main() {
|
||||
when(() => platform.script).thenReturn(platformScript);
|
||||
});
|
||||
|
||||
group('getShorebirdYamlFile', () {
|
||||
test('returns correct file', () {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
expect(
|
||||
runWithOverrides(
|
||||
() => shorebirdEnv.getShorebirdYamlFile(cwd: tempDir).path,
|
||||
),
|
||||
equals(p.join(tempDir.path, 'shorebird.yaml')),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('getFlutterProjectRoot', () {
|
||||
test('returns null when no Flutter project exists', () {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
expect(
|
||||
IOOverrides.runZoned(
|
||||
() => runWithOverrides(() => shorebirdEnv.getFlutterProjectRoot()),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
),
|
||||
isNull,
|
||||
);
|
||||
});
|
||||
|
||||
test('returns correct directory when Flutter project exists (root)', () {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
File(p.join(tempDir.path, 'pubspec.yaml')).createSync(recursive: true);
|
||||
final projectRoot = IOOverrides.runZoned(
|
||||
() => runWithOverrides(
|
||||
() => shorebirdEnv.getFlutterProjectRoot(),
|
||||
),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
expect(projectRoot!.path, equals(tempDir.path));
|
||||
});
|
||||
|
||||
test('returns correct directory when Flutter project exists (nested)',
|
||||
() {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
final nestedDir = Directory(p.join(tempDir.path, 'nested'));
|
||||
File(p.join(tempDir.path, 'pubspec.yaml')).createSync(recursive: true);
|
||||
final projectRoot = IOOverrides.runZoned(
|
||||
() => runWithOverrides(
|
||||
() => shorebirdEnv.getFlutterProjectRoot(),
|
||||
),
|
||||
getCurrentDirectory: () => nestedDir,
|
||||
);
|
||||
expect(projectRoot!.path, equals(tempDir.path));
|
||||
});
|
||||
});
|
||||
|
||||
group('getShorebirdProjectRoot', () {
|
||||
test('returns null when no Shorebird project exists', () {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
expect(
|
||||
IOOverrides.runZoned(
|
||||
() => runWithOverrides(
|
||||
() => shorebirdEnv.getShorebirdProjectRoot(),
|
||||
),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
),
|
||||
isNull,
|
||||
);
|
||||
});
|
||||
|
||||
test('returns correct directory when Shorebird project exists (root)',
|
||||
() {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
File(
|
||||
p.join(tempDir.path, 'shorebird.yaml'),
|
||||
).createSync(recursive: true);
|
||||
final projectRoot = IOOverrides.runZoned(
|
||||
() => runWithOverrides(
|
||||
() => shorebirdEnv.getShorebirdProjectRoot(),
|
||||
),
|
||||
getCurrentDirectory: () => tempDir,
|
||||
);
|
||||
expect(projectRoot!.path, equals(tempDir.path));
|
||||
});
|
||||
|
||||
test('returns correct directory when Flutter project exists (nested)',
|
||||
() {
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
final nestedDir = Directory(p.join(tempDir.path, 'nested'));
|
||||
File(
|
||||
p.join(tempDir.path, 'shorebird.yaml'),
|
||||
).createSync(recursive: true);
|
||||
final projectRoot = IOOverrides.runZoned(
|
||||
() => runWithOverrides(
|
||||
() => shorebirdEnv.getShorebirdProjectRoot(),
|
||||
),
|
||||
getCurrentDirectory: () => nestedDir,
|
||||
);
|
||||
expect(projectRoot!.path, equals(tempDir.path));
|
||||
});
|
||||
});
|
||||
|
||||
group('flutterBinaryFile', () {
|
||||
test('returns correct path', () {
|
||||
expect(
|
||||
@@ -89,15 +186,10 @@ void main() {
|
||||
|
||||
group('getPubspecYamlFile', () {
|
||||
test('returns correct file', () {
|
||||
final tempDir = Directory('temp');
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
expect(
|
||||
IOOverrides.runZoned(
|
||||
() {
|
||||
return runWithOverrides(
|
||||
() => shorebirdEnv.getPubspecYamlFile().path,
|
||||
);
|
||||
},
|
||||
getCurrentDirectory: () => tempDir,
|
||||
runWithOverrides(
|
||||
() => shorebirdEnv.getPubspecYamlFile(cwd: tempDir).path,
|
||||
),
|
||||
equals(p.join(tempDir.path, 'pubspec.yaml')),
|
||||
);
|
||||
@@ -106,7 +198,7 @@ void main() {
|
||||
|
||||
group('getPubspecYaml', () {
|
||||
test('returns null when pubspec.yaml does not exist', () {
|
||||
final tempDir = Directory('temp');
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
expect(
|
||||
IOOverrides.runZoned(
|
||||
() => runWithOverrides(() => shorebirdEnv.getPubspecYaml()),
|
||||
@@ -133,7 +225,7 @@ void main() {
|
||||
|
||||
group('hasPubspecYaml', () {
|
||||
test('returns false when pubspec.yaml does not exist', () {
|
||||
final tempDir = Directory('temp');
|
||||
final tempDir = Directory.systemTemp.createTempSync();
|
||||
expect(
|
||||
IOOverrides.runZoned(
|
||||
() => runWithOverrides(() => shorebirdEnv.hasPubspecYaml),
|
||||
|
||||
+63
-45
@@ -1,9 +1,14 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:mocktail/mocktail.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:scoped/scoped.dart';
|
||||
import 'package:shorebird_cli/src/shorebird_env.dart';
|
||||
import 'package:shorebird_cli/src/validators/validators.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import '../mocks.dart';
|
||||
|
||||
void main() {
|
||||
const manifestWithInternetPermission = '''
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
@@ -33,40 +38,53 @@ void main() {
|
||||
''';
|
||||
|
||||
group(AndroidInternetPermissionValidator, () {
|
||||
Directory createTempDir() => Directory.systemTemp.createTempSync();
|
||||
late Directory projectRoot;
|
||||
late ShorebirdEnv shorebirdEnv;
|
||||
|
||||
void writeManifestToPath(String manifestContents, String path) {
|
||||
Directory(path).createSync(recursive: true);
|
||||
File(p.join(path, 'AndroidManifest.xml'))
|
||||
.writeAsStringSync(manifestContents);
|
||||
File(
|
||||
p.join(path, 'AndroidManifest.xml'),
|
||||
).writeAsStringSync(manifestContents);
|
||||
}
|
||||
|
||||
R runWithOverrides<R>(R Function() body) {
|
||||
return runScoped(
|
||||
body,
|
||||
values: {
|
||||
shorebirdEnvRef.overrideWith(() => shorebirdEnv),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
setUp(() {
|
||||
projectRoot = Directory.systemTemp.createTempSync();
|
||||
shorebirdEnv = MockShorebirdEnv();
|
||||
|
||||
when(() => shorebirdEnv.getFlutterProjectRoot()).thenReturn(projectRoot);
|
||||
});
|
||||
|
||||
test('has a non-empty description', () {
|
||||
expect(AndroidInternetPermissionValidator().description, isNotEmpty);
|
||||
});
|
||||
|
||||
group('canRunInContext', () {
|
||||
test('returns false if no android src directory exists', () {
|
||||
final tempDirectory = createTempDir();
|
||||
|
||||
final result = IOOverrides.runZoned(
|
||||
final result = runWithOverrides(
|
||||
() => AndroidInternetPermissionValidator().canRunInCurrentContext(),
|
||||
getCurrentDirectory: () => tempDirectory,
|
||||
);
|
||||
|
||||
expect(result, isFalse);
|
||||
});
|
||||
|
||||
test('returns true if an android src directory exists', () {
|
||||
final tempDirectory = createTempDir();
|
||||
writeManifestToPath(
|
||||
manifestWithInternetPermission,
|
||||
p.join(tempDirectory.path, 'android', 'app', 'src', 'main'),
|
||||
p.join(projectRoot.path, 'android', 'app', 'src', 'main'),
|
||||
);
|
||||
|
||||
final result = IOOverrides.runZoned(
|
||||
final result = runWithOverrides(
|
||||
() => AndroidInternetPermissionValidator().canRunInCurrentContext(),
|
||||
getCurrentDirectory: () => tempDirectory,
|
||||
);
|
||||
|
||||
expect(result, isTrue);
|
||||
@@ -76,15 +94,13 @@ void main() {
|
||||
test(
|
||||
'''returns successful result if the main AndroidManifest.xml file has the INTERNET permission''',
|
||||
() async {
|
||||
final tempDirectory = createTempDir();
|
||||
writeManifestToPath(
|
||||
manifestWithInternetPermission,
|
||||
p.join(tempDirectory.path, 'android', 'app', 'src', 'main'),
|
||||
p.join(projectRoot.path, 'android', 'app', 'src', 'main'),
|
||||
);
|
||||
|
||||
final results = await IOOverrides.runZoned(
|
||||
final results = await runWithOverrides(
|
||||
AndroidInternetPermissionValidator().validate,
|
||||
getCurrentDirectory: () => tempDirectory,
|
||||
);
|
||||
|
||||
expect(results.map((res) => res.severity), isEmpty);
|
||||
@@ -93,13 +109,12 @@ void main() {
|
||||
|
||||
test('returns an error if AndroidManifest.xml file does not exist',
|
||||
() async {
|
||||
final tempDirectory = createTempDir();
|
||||
Directory(p.join(tempDirectory.path, 'android', 'app', 'src', 'main'))
|
||||
.createSync(recursive: true);
|
||||
Directory(
|
||||
p.join(projectRoot.path, 'android', 'app', 'src', 'main'),
|
||||
).createSync(recursive: true);
|
||||
|
||||
final results = await IOOverrides.runZoned(
|
||||
final results = await runWithOverrides(
|
||||
AndroidInternetPermissionValidator().validate,
|
||||
getCurrentDirectory: () => tempDirectory,
|
||||
);
|
||||
|
||||
expect(results, hasLength(1));
|
||||
@@ -113,18 +128,21 @@ void main() {
|
||||
|
||||
group('when the INTERNET permission is commented out', () {
|
||||
test('returns error', () async {
|
||||
final tempDirectory = createTempDir();
|
||||
final manifestPath =
|
||||
p.join(tempDirectory.path, 'android', 'app', 'src', 'main');
|
||||
final manifestPath = p.join(
|
||||
projectRoot.path,
|
||||
'android',
|
||||
'app',
|
||||
'src',
|
||||
'main',
|
||||
);
|
||||
|
||||
writeManifestToPath(
|
||||
manifestWithCommentedOutInternetPermission,
|
||||
manifestPath,
|
||||
);
|
||||
|
||||
final results = await IOOverrides.runZoned(
|
||||
final results = await runWithOverrides(
|
||||
AndroidInternetPermissionValidator().validate,
|
||||
getCurrentDirectory: () => tempDirectory,
|
||||
);
|
||||
|
||||
expect(results, hasLength(1));
|
||||
@@ -143,15 +161,18 @@ void main() {
|
||||
|
||||
group('when the INTERNET permission is missing', () {
|
||||
test('returns error', () async {
|
||||
final tempDirectory = createTempDir();
|
||||
final manifestPath =
|
||||
p.join(tempDirectory.path, 'android', 'app', 'src', 'main');
|
||||
final manifestPath = p.join(
|
||||
projectRoot.path,
|
||||
'android',
|
||||
'app',
|
||||
'src',
|
||||
'main',
|
||||
);
|
||||
|
||||
writeManifestToPath(manifestWithNoPermissions, manifestPath);
|
||||
|
||||
final results = await IOOverrides.runZoned(
|
||||
final results = await runWithOverrides(
|
||||
AndroidInternetPermissionValidator().validate,
|
||||
getCurrentDirectory: () => tempDirectory,
|
||||
);
|
||||
|
||||
expect(results, hasLength(1));
|
||||
@@ -170,18 +191,21 @@ void main() {
|
||||
|
||||
group('when manifest has non-INTERNET permissions', () {
|
||||
test('returns error', () async {
|
||||
final tempDirectory = createTempDir();
|
||||
final manifestPath =
|
||||
p.join(tempDirectory.path, 'android', 'app', 'src', 'main');
|
||||
final manifestPath = p.join(
|
||||
projectRoot.path,
|
||||
'android',
|
||||
'app',
|
||||
'src',
|
||||
'main',
|
||||
);
|
||||
|
||||
writeManifestToPath(
|
||||
manifestWithNonInternetPermissions,
|
||||
manifestPath,
|
||||
);
|
||||
|
||||
final results = await IOOverrides.runZoned(
|
||||
final results = await runWithOverrides(
|
||||
AndroidInternetPermissionValidator().validate,
|
||||
getCurrentDirectory: () => tempDirectory,
|
||||
);
|
||||
|
||||
expect(results, hasLength(1));
|
||||
@@ -200,27 +224,21 @@ void main() {
|
||||
|
||||
group('fix', () {
|
||||
test('adds permission to manifest file', () async {
|
||||
final tempDirectory = createTempDir();
|
||||
writeManifestToPath(
|
||||
manifestWithNonInternetPermissions,
|
||||
p.join(tempDirectory.path, 'android', 'app', 'src', 'main'),
|
||||
p.join(projectRoot.path, 'android', 'app', 'src', 'main'),
|
||||
);
|
||||
|
||||
var results = await IOOverrides.runZoned(
|
||||
var results = await runWithOverrides(
|
||||
AndroidInternetPermissionValidator().validate,
|
||||
getCurrentDirectory: () => tempDirectory,
|
||||
);
|
||||
expect(results, hasLength(1));
|
||||
expect(results.first.fix, isNotNull);
|
||||
|
||||
await IOOverrides.runZoned(
|
||||
() => results.first.fix!(),
|
||||
getCurrentDirectory: () => tempDirectory,
|
||||
);
|
||||
await runWithOverrides(() => results.first.fix!());
|
||||
|
||||
results = await IOOverrides.runZoned(
|
||||
results = await runWithOverrides(
|
||||
AndroidInternetPermissionValidator().validate,
|
||||
getCurrentDirectory: () => tempDirectory,
|
||||
);
|
||||
expect(results, isEmpty);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user