Unverified Commit d688b52a authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[flutter_tools] post process the gradle log output (#71499)

parent 7c14f6c8
......@@ -23,6 +23,7 @@ import '../globals.dart' as globals;
import '../project.dart';
import '../reporting/reporting.dart';
import 'gradle_errors.dart';
import 'gradle_log_processor.dart';
import 'gradle_utils.dart';
/// The directory where the APK artifact is generated.
......@@ -360,31 +361,7 @@ Future<void> buildGradleApp({
}
command.add(assembleTask);
GradleHandledError detectedGradleError;
String detectedGradleErrorLine;
String consumeLog(String line) {
// This message was removed from first-party plugins,
// but older plugin versions still display this message.
if (androidXPluginWarningRegex.hasMatch(line)) {
// Don't pipe.
return null;
}
if (detectedGradleError != null) {
// Pipe stdout/stderr from Gradle.
return line;
}
for (final GradleHandledError gradleError in localGradleErrors) {
if (gradleError.test(line)) {
detectedGradleErrorLine = line;
detectedGradleError = gradleError;
// The first error match wins.
break;
}
}
// Pipe stdout/stderr from Gradle.
return line;
}
final GradleLogProcessor gradleLogProcessor = GradleLogProcessor(localGradleErrors, globals.logger.isVerbose);
final Stopwatch sw = Stopwatch()..start();
int exitCode = 1;
try {
......@@ -393,13 +370,14 @@ Future<void> buildGradleApp({
workingDirectory: project.android.hostAppGradleRoot.path,
allowReentrantFlutter: true,
environment: gradleEnvironment,
mapFunction: consumeLog,
mapFunction: gradleLogProcessor.consumeLog,
);
} on ProcessException catch (exception) {
consumeLog(exception.toString());
gradleLogProcessor.atFailureFooter = false;
gradleLogProcessor.consumeLog(exception.toString());
// Rethrow the exception if the error isn't handled by any of the
// `localGradleErrors`.
if (detectedGradleError == null) {
if (gradleLogProcessor.detectedGradleError == null) {
rethrow;
}
} finally {
......@@ -409,22 +387,22 @@ Future<void> buildGradleApp({
globals.flutterUsage.sendTiming('build', 'gradle', sw.elapsed);
if (exitCode != 0) {
if (detectedGradleError == null) {
if (gradleLogProcessor.detectedGradleError == null) {
BuildEvent('gradle-unknown-failure', flutterUsage: globals.flutterUsage).send();
throwToolExit(
'Gradle task $assembleTask failed with exit code $exitCode',
exitCode: exitCode,
);
} else {
final GradleBuildStatus status = await detectedGradleError.handler(
line: detectedGradleErrorLine,
final GradleBuildStatus status = await gradleLogProcessor.detectedGradleError.handler(
line: gradleLogProcessor.detectedGradleErrorLine,
project: project,
usesAndroidX: usesAndroidX,
shouldBuildPluginAsAar: shouldBuildPluginAsAar,
);
if (retries >= 1) {
final String successEventLabel = 'gradle-${detectedGradleError.eventLabel}-success';
final String successEventLabel = 'gradle-${gradleLogProcessor.detectedGradleError.eventLabel}-success';
switch (status) {
case GradleBuildStatus.retry:
await buildGradleApp(
......@@ -454,7 +432,7 @@ Future<void> buildGradleApp({
// noop.
}
}
BuildEvent('gradle-${detectedGradleError.eventLabel}-failure', flutterUsage: globals.flutterUsage).send();
BuildEvent('gradle-${gradleLogProcessor.detectedGradleError.eventLabel}-failure', flutterUsage: globals.flutterUsage).send();
throwToolExit(
'Gradle task $assembleTask failed with exit code $exitCode',
exitCode: exitCode,
......
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'gradle_errors.dart';
/// Process log output from gradle, removing irrelevant output and capturing
/// exception information.
class GradleLogProcessor {
GradleLogProcessor(this.localGradleErrors, this.verbose);
final List<GradleHandledError> localGradleErrors;
final bool verbose;
GradleHandledError detectedGradleError;
String detectedGradleErrorLine;
bool atFailureFooter = false;
String consumeLog(String line) {
// All gradle failures lead to a fairly long footer which contains mostly
// irrelevant information for a flutter build, along with misleading advice to
// run with --stacktrace (which does not exist for the flutter CLI). remove this.
if (!verbose && (line.startsWith('FAILURE: Build failed with an exception.') || atFailureFooter)) {
atFailureFooter = true;
return null;
}
// This message was removed from first-party plugins,
// but older plugin versions still display this message.
if (androidXPluginWarningRegex.hasMatch(line)) {
// Don't pipe.
return null;
}
if (detectedGradleError != null) {
// Pipe stdout/stderr from Gradle.
return line;
}
for (final GradleHandledError gradleError in localGradleErrors) {
if (gradleError.test(line)) {
detectedGradleErrorLine = line;
detectedGradleError = gradleError;
// The first error match wins.
break;
}
}
// Pipe stdout/stderr from Gradle.
return line;
}
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter_tools/src/android/gradle_errors.dart';
import 'package:flutter_tools/src/android/gradle_log_processor.dart';
import '../../src/common.dart';
final List<String> gradleErrorOutputLines = r'''
Some other stuff.
FAILURE: Build failed with an exception.
* Where:
Script '/Users/mit/dev/flutter/packages/flutter_tools/gradle/flutter.gradle' line: 900
* What went wrong:
Execution failed for task ':app:compileFlutterBuildRelease'.
> Process 'command '/Users/mit/dev/flutter/bin/flutter'' finished with non-zero exit value 1
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
* Get more help at https://help.gradle.org
BUILD FAILED in 24s
'''.split('\n');
void main() {
testWithoutContext('Does not print failure footer in non-verbose mode', () async {
final GradleLogProcessor gradleLogProcessor = GradleLogProcessor(<GradleHandledError>[], false);
expect(gradleErrorOutputLines.map(gradleLogProcessor.consumeLog).where((String line) => line != null), <String>['Some other stuff.']);
expect(gradleLogProcessor.atFailureFooter, true);
});
testWithoutContext('Does print failure footer in verbose mode', () async {
final GradleLogProcessor gradleLogProcessor = GradleLogProcessor(<GradleHandledError>[], true);
expect(gradleErrorOutputLines.map(gradleLogProcessor.consumeLog).where((String line) => line != null), gradleErrorOutputLines);
expect(gradleLogProcessor.atFailureFooter, false);
});
}
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