Commit 79747f49 authored by Mikkel Nygaard Ravn's avatar Mikkel Nygaard Ravn Committed by GitHub

Improve Gradle error output in Flutter commands (#11703)

parent 8c2c5022
...@@ -15,30 +15,73 @@ void main() { ...@@ -15,30 +15,73 @@ void main() {
final Directory tmp = await Directory.systemTemp.createTemp('gradle'); final Directory tmp = await Directory.systemTemp.createTemp('gradle');
final FlutterProject project = await FlutterProject.create(tmp, 'hello'); final FlutterProject project = await FlutterProject.create(tmp, 'hello');
section('gradlew assembleDebug'); try {
await project.runGradleTask('assembleDebug'); section('gradlew assembleDebug');
await project.runGradleTask('assembleDebug');
section('gradlew assembleProfile');
await project.runGradleTask('assembleProfile'); section('gradlew assembleProfile');
await project.runGradleTask('assembleProfile');
section('gradlew assembleRelease');
await project.runGradleTask('assembleRelease'); section('gradlew assembleRelease');
await project.runGradleTask('assembleRelease');
section('gradlew assembleLocal (custom debug build)');
await project.addCustomBuildType('local', initWith: 'debug'); section('gradlew assembleLocal (custom debug build)');
await project.runGradleTask('assembleLocal'); await project.addCustomBuildType('local', initWith: 'debug');
await project.runGradleTask('assembleLocal');
section('gradlew assembleBeta (custom release build)');
await project.addCustomBuildType('beta', initWith: 'release'); section('gradlew assembleBeta (custom release build)');
await project.runGradleTask('assembleBeta'); await project.addCustomBuildType('beta', initWith: 'release');
await project.runGradleTask('assembleBeta');
section('gradlew assembleFreeDebug (product flavor)');
await project.addProductFlavor('free');
await project.runGradleTask('assembleFreeDebug');
await project.introduceError();
section('gradlew on build script with error');
{
final ProcessResult result = await project.resultOfGradleTask('assembleRelease');
if (result.exitCode == 0)
return _failure('Gradle did not exit with error as expected', result);
final String output = result.stdout + '\n' + result.stderr;
if (output.contains('GradleException') || output.contains('Failed to notify') || output.contains('at org.gradle'))
return _failure('Gradle output should not contain stacktrace', result);
if (!output.contains('Build failed') || !output.contains('builTypes'))
return _failure('Gradle output should contain a readable error message', result);
}
section('flutter build apk on build script with error');
{
final ProcessResult result = await project.resultOfFlutterCommand('build', <String>['apk']);
if (result.exitCode == 0)
return _failure('flutter build apk should fail when Gradle does', result);
final String output = result.stdout + '\n' + result.stderr;
if (!output.contains('Build failed') || !output.contains('builTypes'))
return _failure('flutter build apk output should contain a readable Gradle error message', result);
if (_hasMultipleOccurrences(output, 'builTypes'))
return _failure('flutter build apk should not invoke Gradle repeatedly on error', result);
}
return new TaskResult.success(null);
} catch(e) {
return new TaskResult.failure(e.toString());
} finally {
project.parent.deleteSync(recursive: true);
}
});
}
section('gradlew assembleFreeDebug (product flavor)'); TaskResult _failure(String message, ProcessResult result) {
await project.addProductFlavor('free'); print('Unexpected process result:');
await project.runGradleTask('assembleFreeDebug'); print('Exit code: ${result.exitCode}');
print('Std out :\n${result.stdout}');
print('Std err :\n${result.stderr}');
return new TaskResult.failure(message);
}
await project.parent.delete(recursive: true); bool _hasMultipleOccurrences(String text, Pattern pattern) {
return new TaskResult.success(null); return text.indexOf(pattern) != text.lastIndexOf(pattern);
});
} }
class FlutterProject { class FlutterProject {
...@@ -90,18 +133,38 @@ android { ...@@ -90,18 +133,38 @@ android {
'''); ''');
} }
Future<Null> runGradleTask(String task) async { Future<Null> introduceError() async {
final ProcessResult result = await Process.run( final File buildScript = new File(
'./gradlew', path.join(androidPath, 'app', 'build.gradle'),
<String>['-q', 'app:$task'],
workingDirectory: androidPath,
); );
await buildScript.writeAsString((await buildScript.readAsString()).replaceAll('buildTypes', 'builTypes'));
}
Future<Null> runGradleTask(String task) async {
final ProcessResult result = await resultOfGradleTask(task);
if (result.exitCode != 0) { if (result.exitCode != 0) {
print('stdout:'); print('stdout:');
print(result.stdout); print(result.stdout);
print('stderr:'); print('stderr:');
print(result.stderr); print(result.stderr);
} }
assert(result.exitCode == 0); if (result.exitCode != 0)
throw 'Gradle exited with error';
}
Future<ProcessResult> resultOfGradleTask(String task) {
return Process.run(
'./gradlew',
<String>['app:$task'],
workingDirectory: androidPath,
);
}
Future<ProcessResult> resultOfFlutterCommand(String command, List<String> options) {
return Process.run(
path.join(flutterDirectory.path, 'bin', 'flutter'),
<String>[command]..addAll(options),
workingDirectory: rootPath,
);
} }
} }
...@@ -157,6 +157,9 @@ class FlutterPlugin implements Plugin<Project> { ...@@ -157,6 +157,9 @@ class FlutterPlugin implements Plugin<Project> {
} }
private void addFlutterJarProvidedDependency(Project project) { private void addFlutterJarProvidedDependency(Project project) {
if (project.state.failure) {
return
}
project.dependencies { project.dependencies {
if (flutterJar != null) { if (flutterJar != null) {
provided project.files(flutterJar) provided project.files(flutterJar)
...@@ -204,6 +207,9 @@ class FlutterPlugin implements Plugin<Project> { ...@@ -204,6 +207,9 @@ class FlutterPlugin implements Plugin<Project> {
} }
private void addFlutterTask(Project project) { private void addFlutterTask(Project project) {
if (project.state.failure) {
return
}
if (project.flutter.source == null) { if (project.flutter.source == null) {
throw new GradleException("Must provide Flutter source directory") throw new GradleException("Must provide Flutter source directory")
} }
......
...@@ -97,7 +97,12 @@ Future<GradleProject> _readGradleProject() async { ...@@ -97,7 +97,12 @@ Future<GradleProject> _readGradleProject() async {
status.stop(); status.stop();
return project; return project;
} catch (e) { } catch (e) {
printError('Error running gradle: $e'); if (flutterPluginVersion == FlutterPluginVersion.managed) {
printError('Error running Gradle:\n$e\n');
throwToolExit(
'Please review your Gradle project setup in the android/ folder.',
);
}
} }
// Fall back to the default // Fall back to the default
return new GradleProject(<String>['debug', 'profile', 'release'], <String>[], gradleAppOutDirV1); return new GradleProject(<String>['debug', 'profile', 'release'], <String>[], gradleAppOutDirV1);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment