Unverified Commit 70456f5b authored by Elias Yishak's avatar Elias Yishak Committed by GitHub

Unified analytics events migration for `BuildEvent` (#137562)

Related to tracker issue:
- https://github.com/flutter/flutter/issues/128251
parent 01b88540
......@@ -7,6 +7,7 @@ import 'dart:math';
import 'package:crypto/crypto.dart';
import 'package:meta/meta.dart';
import 'package:process/process.dart';
import 'package:unified_analytics/unified_analytics.dart';
import 'package:xml/xml.dart';
import '../artifacts.dart';
......@@ -149,6 +150,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
required FileSystem fileSystem,
required Artifacts artifacts,
required Usage usage,
required Analytics analytics,
required GradleUtils gradleUtils,
required Platform platform,
required AndroidStudio? androidStudio,
......@@ -157,6 +159,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
_fileSystem = fileSystem,
_artifacts = artifacts,
_usage = usage,
_analytics = analytics,
_gradleUtils = gradleUtils,
_androidStudio = androidStudio,
_fileSystemUtils = FileSystemUtils(fileSystem: fileSystem, platform: platform),
......@@ -168,6 +171,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
final FileSystem _fileSystem;
final Artifacts _artifacts;
final Usage _usage;
final Analytics _analytics;
final GradleUtils _gradleUtils;
final FileSystemUtils _fileSystemUtils;
final AndroidStudio? _androidStudio;
......@@ -300,7 +304,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
@visibleForTesting int? maxRetries,
}) async {
if (!project.android.isSupportedVersion) {
_exitWithUnsupportedProjectMessage(_usage, _logger.terminal);
_exitWithUnsupportedProjectMessage(_usage, _logger.terminal, analytics: _analytics);
}
final List<ProjectMigrator> migrators = <ProjectMigrator>[
......@@ -318,8 +322,11 @@ class AndroidGradleBuilder implements AndroidBuilder {
final bool usesAndroidX = isAppUsingAndroidX(project.android.hostAppGradleRoot);
if (usesAndroidX) {
BuildEvent('app-using-android-x', type: 'gradle', flutterUsage: _usage).send();
_analytics.send(Event.flutterBuildInfo(label: 'app-using-android-x', buildType: 'gradle'));
} else if (!usesAndroidX) {
BuildEvent('app-not-using-android-x', type: 'gradle', flutterUsage: _usage).send();
_analytics.send(Event.flutterBuildInfo(label: 'app-not-using-android-x', buildType: 'gradle'));
_logger.printStatus("${_logger.terminal.warningMark} Your app isn't using AndroidX.", emphasis: true);
_logger.printStatus(
'To avoid potential build failures, you can quickly migrate your app '
......@@ -488,6 +495,8 @@ class AndroidGradleBuilder implements AndroidBuilder {
if (exitCode != 0) {
if (detectedGradleError == null) {
BuildEvent('gradle-unknown-failure', type: 'gradle', flutterUsage: _usage).send();
_analytics.send(Event.flutterBuildInfo(label: 'gradle-unknown-failure', buildType: 'gradle'));
throwToolExit(
'Gradle task $assembleTask failed with exit code $exitCode',
exitCode: exitCode,
......@@ -520,13 +529,19 @@ class AndroidGradleBuilder implements AndroidBuilder {
configOnly: configOnly,
);
final String successEventLabel = 'gradle-${detectedGradleError!.eventLabel}-success';
BuildEvent(successEventLabel, type: 'gradle', flutterUsage: _usage).send();
_analytics.send(Event.flutterBuildInfo(label: successEventLabel, buildType: 'gradle'));
return;
case GradleBuildStatus.exit:
// Continue and throw tool exit.
}
}
BuildEvent('gradle-${detectedGradleError?.eventLabel}-failure', type: 'gradle', flutterUsage: _usage).send();
final String usageLabel = 'gradle-${detectedGradleError?.eventLabel}-failure';
BuildEvent(usageLabel, type: 'gradle', flutterUsage: _usage).send();
_analytics.send(Event.flutterBuildInfo(label: usageLabel, buildType: 'gradle'));
throwToolExit(
'Gradle task $assembleTask failed with exit code $exitCode',
exitCode: exitCode,
......@@ -534,7 +549,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
}
if (isBuildingBundle) {
final File bundleFile = findBundleFile(project, buildInfo, _logger, _usage);
final File bundleFile = findBundleFile(project, buildInfo, _logger, _usage, _analytics);
final String appSize = (buildInfo.mode == BuildMode.debug)
? '' // Don't display the size when building a debug variant.
: ' (${getSizeAsMB(bundleFile.lengthSync())})';
......@@ -551,7 +566,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
}
// Gradle produced APKs.
final Iterable<String> apkFilesPaths = project.isModule
? findApkFilesModule(project, androidBuildInfo, _logger, _usage)
? findApkFilesModule(project, androidBuildInfo, _logger, _usage, _analytics)
: listApkPaths(androidBuildInfo);
final Directory apkDirectory = getApkDirectory(project);
......@@ -563,6 +578,7 @@ class AndroidGradleBuilder implements AndroidBuilder {
fileExtension: '.apk',
logger: _logger,
usage: _usage,
analytics: _analytics,
);
}
......@@ -886,8 +902,14 @@ String _calculateSha(File file) {
return _hex(sha1.convert(bytes).bytes);
}
void _exitWithUnsupportedProjectMessage(Usage usage, Terminal terminal) {
void _exitWithUnsupportedProjectMessage(Usage usage, Terminal terminal, {required Analytics analytics}) {
BuildEvent('unsupported-project', type: 'gradle', eventError: 'gradle-plugin', flutterUsage: usage).send();
analytics.send(Event.flutterBuildInfo(
label: 'unsupported-project',
buildType: 'gradle',
error: 'gradle-plugin',
));
throwToolExit(
'${terminal.warningMark} Your app is using an unsupported Gradle project. '
'To fix this problem, create a new project by running `flutter create -t app <app-directory>` '
......@@ -913,6 +935,7 @@ Iterable<String> findApkFilesModule(
AndroidBuildInfo androidBuildInfo,
Logger logger,
Usage usage,
Analytics analytics,
) {
final Iterable<String> apkFileNames = _apkFilesFor(androidBuildInfo);
final Directory apkDirectory = getApkDirectory(project);
......@@ -948,6 +971,7 @@ Iterable<String> findApkFilesModule(
fileExtension: '.apk',
logger: logger,
usage: usage,
analytics: analytics,
);
}
return apks.map((File file) => file.path);
......@@ -986,7 +1010,7 @@ Iterable<String> listApkPaths(
}
@visibleForTesting
File findBundleFile(FlutterProject project, BuildInfo buildInfo, Logger logger, Usage usage) {
File findBundleFile(FlutterProject project, BuildInfo buildInfo, Logger logger, Usage usage, Analytics analytics) {
final List<File> fileCandidates = <File>[
getBundleDirectory(project)
.childDirectory(camelCase(buildInfo.modeName))
......@@ -1043,6 +1067,7 @@ File findBundleFile(FlutterProject project, BuildInfo buildInfo, Logger logger,
fileExtension: '.aab',
logger: logger,
usage: usage,
analytics: analytics,
);
}
......@@ -1052,17 +1077,25 @@ Never _exitWithExpectedFileNotFound({
required String fileExtension,
required Logger logger,
required Usage usage,
required Analytics analytics,
}) {
final String androidGradlePluginVersion =
getGradleVersionForAndroidPlugin(project.android.hostAppGradleRoot, logger);
final String gradleBuildSettings = 'androidGradlePluginVersion: $androidGradlePluginVersion, '
'fileExtension: $fileExtension';
BuildEvent('gradle-expected-file-not-found',
type: 'gradle',
settings:
'androidGradlePluginVersion: $androidGradlePluginVersion, '
'fileExtension: $fileExtension',
settings: gradleBuildSettings,
flutterUsage: usage,
).send();
analytics.send(Event.flutterBuildInfo(
label: 'gradle-expected-file-not-found',
buildType: 'gradle',
settings: gradleBuildSettings,
));
throwToolExit(
'Gradle build failed to produce an $fileExtension file. '
"It's likely that this file was generated under ${project.android.buildDirectory.path}, "
......
......@@ -4,6 +4,7 @@
import 'package:meta/meta.dart';
import 'package:process/process.dart';
import 'package:unified_analytics/unified_analytics.dart';
import '../base/common.dart';
import '../base/file_system.dart';
......@@ -741,6 +742,11 @@ void exitWithNoSdkMessage() {
eventError: 'android-sdk-not-found',
flutterUsage: globals.flutterUsage)
.send();
globals.analytics.send(Event.flutterBuildInfo(
label: 'unsupported-project',
buildType: 'gradle',
error: 'android-sdk-not-found',
));
throwToolExit('${globals.logger.terminal.warningMark} No Android SDK found. '
'Try setting the ANDROID_HOME environment variable.');
}
......
......@@ -7,6 +7,7 @@ import 'dart:typed_data';
import 'package:crypto/crypto.dart';
import 'package:file/file.dart';
import 'package:meta/meta.dart';
import 'package:unified_analytics/unified_analytics.dart';
import '../base/analyze_size.dart';
import '../base/common.dart';
......@@ -669,7 +670,7 @@ abstract class _BuildIOSSubCommand extends BuildSubCommand {
xcodeBuildResult = result;
if (!result.success) {
await diagnoseXcodeBuildFailure(result, globals.flutterUsage, globals.logger);
await diagnoseXcodeBuildFailure(result, globals.flutterUsage, globals.logger, globals.analytics);
final String presentParticiple = xcodeBuildAction == XcodeBuildAction.build ? 'building' : 'archiving';
throwToolExit('Encountered error while $presentParticiple for $logTarget.');
}
......@@ -739,13 +740,19 @@ abstract class _BuildIOSSubCommand extends BuildSubCommand {
final bool? impellerEnabled = globals.plistParser.getValueFromFile<bool>(
plistPath, PlistParser.kFLTEnableImpellerKey,
);
BuildEvent(
impellerEnabled == false
final String buildLabel = impellerEnabled == false
? 'plist-impeller-disabled'
: 'plist-impeller-enabled',
: 'plist-impeller-enabled';
BuildEvent(
buildLabel,
type: 'ios',
flutterUsage: globals.flutterUsage,
).send();
globals.analytics.send(Event.flutterBuildInfo(
label: buildLabel,
buildType: 'ios',
));
return FlutterCommandResult.success();
}
......
......@@ -195,6 +195,7 @@ class BuildWebCommand extends BuildSubCommand {
fileSystem: globals.fs,
flutterVersion: globals.flutterVersion,
usage: globals.flutterUsage,
analytics: globals.analytics,
);
await webBuilder.buildWeb(
flutterProject,
......
......@@ -101,6 +101,7 @@ Future<T> runInContext<T>(
fileSystem: globals.fs,
artifacts: globals.artifacts!,
usage: globals.flutterUsage,
analytics: globals.analytics,
gradleUtils: globals.gradleUtils!,
platform: globals.platform,
androidStudio: globals.androidStudio,
......@@ -387,6 +388,7 @@ Future<T> runInContext<T>(
platform: globals.platform,
fileSystem: globals.fs,
usage: globals.flutterUsage,
analytics: globals.analytics,
),
},
);
......
......@@ -505,7 +505,7 @@ class IOSDevice extends Device {
);
if (!buildResult.success) {
_logger.printError('Could not build the precompiled application for the device.');
await diagnoseXcodeBuildFailure(buildResult, globals.flutterUsage, _logger);
await diagnoseXcodeBuildFailure(buildResult, globals.flutterUsage, _logger, globals.analytics);
_logger.printError('');
return LaunchResult.failed();
}
......
......@@ -6,6 +6,7 @@ import 'dart:async';
import 'package:meta/meta.dart';
import 'package:process/process.dart';
import 'package:unified_analytics/unified_analytics.dart';
import '../artifacts.dart';
import '../base/file_system.dart';
......@@ -581,17 +582,35 @@ return result.exitCode != 0 &&
result.stdout.contains(kConcurrentRunFailureMessage2);
}
Future<void> diagnoseXcodeBuildFailure(XcodeBuildResult result, Usage flutterUsage, Logger logger) async {
Future<void> diagnoseXcodeBuildFailure(
XcodeBuildResult result,
Usage flutterUsage,
Logger logger,
Analytics analytics,
) async {
final XcodeBuildExecution? xcodeBuildExecution = result.xcodeBuildExecution;
if (xcodeBuildExecution != null
&& xcodeBuildExecution.environmentType == EnvironmentType.physical
&& (result.stdout?.toUpperCase().contains('BITCODE') ?? false)) {
BuildEvent('xcode-bitcode-failure',
type: 'ios',
command: xcodeBuildExecution.buildCommands.toString(),
settings: xcodeBuildExecution.buildSettings.toString(),
const String label = 'xcode-bitcode-failure';
const String buildType = 'ios';
final String command = xcodeBuildExecution.buildCommands.toString();
final String settings = xcodeBuildExecution.buildSettings.toString();
BuildEvent(
label,
type: buildType,
command: command,
settings: settings,
flutterUsage: flutterUsage,
).send();
analytics.send(Event.flutterBuildInfo(
label: label,
buildType: buildType,
command: command,
settings: settings,
));
}
// Handle errors.
......
......@@ -567,7 +567,7 @@ class IOSSimulator extends Device {
deviceID: id,
);
if (!buildResult.success) {
await diagnoseXcodeBuildFailure(buildResult, globals.flutterUsage, globals.logger);
await diagnoseXcodeBuildFailure(buildResult, globals.flutterUsage, globals.logger, globals.analytics);
throwToolExit('Could not build the application for the simulator.');
}
......
......@@ -5,6 +5,7 @@
import 'package:file/memory.dart';
import 'package:meta/meta.dart';
import 'package:process/process.dart';
import 'package:unified_analytics/unified_analytics.dart';
import '../base/common.dart';
import '../base/file_system.dart';
......@@ -30,6 +31,7 @@ class XcodeProjectInterpreter {
required Logger logger,
required FileSystem fileSystem,
required Usage usage,
required Analytics analytics,
}) {
return XcodeProjectInterpreter._(
platform: platform,
......@@ -37,6 +39,7 @@ class XcodeProjectInterpreter {
logger: logger,
fileSystem: fileSystem,
usage: usage,
analytics: analytics,
);
}
......@@ -46,6 +49,7 @@ class XcodeProjectInterpreter {
required Logger logger,
required FileSystem fileSystem,
required Usage usage,
required Analytics analytics,
Version? version,
String? build,
}) : _platform = platform,
......@@ -61,7 +65,8 @@ class XcodeProjectInterpreter {
_version = version,
_build = build,
_versionText = version?.toString(),
_usage = usage;
_usage = usage,
_analytics = analytics;
/// Create an [XcodeProjectInterpreter] for testing.
///
......@@ -73,6 +78,7 @@ class XcodeProjectInterpreter {
required ProcessManager processManager,
Version? version = const Version.withText(1000, 0, 0, '1000.0.0'),
String? build = '13C100',
Analytics? analytics,
}) {
final Platform platform = FakePlatform(
operatingSystem: 'macos',
......@@ -86,6 +92,7 @@ class XcodeProjectInterpreter {
logger: BufferLogger.test(),
version: version,
build: build,
analytics: analytics ?? NoOpAnalytics(),
);
}
......@@ -95,6 +102,7 @@ class XcodeProjectInterpreter {
final OperatingSystemUtils _operatingSystemUtils;
final Logger _logger;
final Usage _usage;
final Analytics _analytics;
static final RegExp _versionRegex = RegExp(r'Xcode ([0-9.]+).*Build version (\w+)');
void _updateVersion() {
......@@ -235,6 +243,11 @@ class XcodeProjectInterpreter {
command: showBuildSettingsCommand.join(' '),
flutterUsage: _usage,
).send();
_analytics.send(Event.flutterBuildInfo(
label: 'xcode-show-build-settings-timeout',
buildType: 'ios',
command: showBuildSettingsCommand.join(' '),
));
}
_logger.printTrace('Unexpected failure to get Xcode build settings: $error.');
return const <String, String>{};
......@@ -290,6 +303,11 @@ class XcodeProjectInterpreter {
command: showBuildSettingsCommand.join(' '),
flutterUsage: _usage,
).send();
_analytics.send(Event.flutterBuildInfo(
label: 'xcode-show-build-settings-timeout',
buildType: 'ios',
command: showBuildSettingsCommand.join(' '),
));
}
_logger.printTrace('Unexpected failure to get Pod Xcode project build settings: $error.');
return null;
......
......@@ -322,6 +322,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
fileSystem: _fileSystem,
flutterVersion: globals.flutterVersion,
usage: globals.flutterUsage,
analytics: globals.analytics,
);
await webBuilder.buildWeb(
flutterProject,
......@@ -400,6 +401,7 @@ Please provide a valid TCP port (an integer between 0 and 65535, inclusive).
fileSystem: _fileSystem,
flutterVersion: globals.flutterVersion,
usage: globals.flutterUsage,
analytics: globals.analytics,
);
await webBuilder.buildWeb(
flutterProject,
......
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
import 'package:meta/meta.dart';
import 'package:unified_analytics/unified_analytics.dart';
import 'package:xml/xml.dart';
import 'package:yaml/yaml.dart';
......@@ -761,8 +762,19 @@ The detected reason was:
''');
if (deprecationBehavior == DeprecationBehavior.ignore) {
BuildEvent('deprecated-v1-android-embedding-ignored', type: 'gradle', flutterUsage: globals.flutterUsage).send();
globals.analytics.send(
Event.flutterBuildInfo(
label: 'deprecated-v1-android-embedding-ignored',
buildType: 'gradle',
));
} else { // DeprecationBehavior.exit
BuildEvent('deprecated-v1-android-embedding-failed', type: 'gradle', flutterUsage: globals.flutterUsage).send();
globals.analytics.send(
Event.flutterBuildInfo(
label: 'deprecated-v1-android-embedding-failed',
buildType: 'gradle',
));
throwToolExit(
'Build failed due to use of deprecated Android v1 embedding.',
exitCode: 1,
......
......@@ -3,6 +3,7 @@
// found in the LICENSE file.
import 'package:process/process.dart';
import 'package:unified_analytics/unified_analytics.dart';
import '../artifacts.dart';
import '../base/common.dart';
......@@ -34,12 +35,14 @@ class WebBuilder {
required ProcessManager processManager,
required BuildSystem buildSystem,
required Usage usage,
required Analytics analytics,
required FlutterVersion flutterVersion,
required FileSystem fileSystem,
}) : _logger = logger,
_processManager = processManager,
_buildSystem = buildSystem,
_flutterUsage = usage,
_analytics = analytics,
_flutterVersion = flutterVersion,
_fileSystem = fileSystem;
......@@ -47,6 +50,7 @@ class WebBuilder {
final ProcessManager _processManager;
final BuildSystem _buildSystem;
final Usage _flutterUsage;
final Analytics _analytics;
final FlutterVersion _flutterVersion;
final FileSystem _fileSystem;
......@@ -127,15 +131,23 @@ class WebBuilder {
} finally {
status.stop();
}
final String buildSettingsString = _buildEventAnalyticsSettings(
config: compilerConfig,
buildInfo: buildInfo,
);
BuildEvent(
'web-compile',
type: 'web',
settings: _buildEventAnalyticsSettings(
config: compilerConfig,
buildInfo: buildInfo,
),
settings: buildSettingsString,
flutterUsage: _flutterUsage,
).send();
_analytics.send(Event.flutterBuildInfo(
label: 'web-compile',
buildType: 'web',
settings: buildSettingsString,
));
_flutterUsage.sendTiming(
'build',
......
......@@ -24,10 +24,12 @@ import 'package:flutter_tools/src/ios/xcodeproj.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:test/fake.dart';
import 'package:unified_analytics/unified_analytics.dart';
import '../../general.shard/ios/xcresult_test_data.dart';
import '../../src/common.dart';
import '../../src/context.dart';
import '../../src/fakes.dart';
import '../../src/test_build_system.dart';
import '../../src/test_flutter_command_runner.dart';
......@@ -70,6 +72,7 @@ final Platform notMacosPlatform = FakePlatform(
void main() {
late FileSystem fileSystem;
late TestUsage usage;
late FakeAnalytics fakeAnalytics;
late BufferLogger logger;
late FakeProcessManager processManager;
late ProcessUtils processUtils;
......@@ -83,6 +86,10 @@ void main() {
fileSystem = MemoryFileSystem.test();
artifacts = Artifacts.test(fileSystem: fileSystem);
usage = TestUsage();
fakeAnalytics = getInitializedFakeAnalyticsInstance(
fs: fileSystem,
fakeFlutterVersion: FakeFlutterVersion(),
);
logger = BufferLogger.test();
processManager = FakeProcessManager.empty();
processUtils = ProcessUtils(
......@@ -587,6 +594,13 @@ void main() {
parameters:CustomDimensions(),
),
));
expect(fakeAnalytics.sentEvents, contains(
Event.flutterBuildInfo(
label: 'plist-impeller-enabled',
buildType: 'ios',
),
));
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
......@@ -607,6 +621,7 @@ void main() {
),
Usage: () => usage,
XcodeProjectInterpreter: () => FakeXcodeProjectInterpreterWithBuildSettings(),
Analytics: () => fakeAnalytics,
});
testUsingContext('Sends an analytics event when Impeller is disabled', () async {
......@@ -642,6 +657,13 @@ void main() {
parameters:CustomDimensions(),
),
));
expect(fakeAnalytics.sentEvents, contains(
Event.flutterBuildInfo(
label: 'plist-impeller-disabled',
buildType: 'ios',
),
));
}, overrides: <Type, Generator>{
FileSystem: () => fileSystem,
ProcessManager: () => FakeProcessManager.list(<FakeCommand>[
......@@ -673,6 +695,7 @@ void main() {
plutilCommand, plutilCommand, plutilCommand,
]),
),
Analytics: () => fakeAnalytics,
});
});
......
......@@ -23,6 +23,7 @@ import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:test/fake.dart';
import 'package:unified_analytics/unified_analytics.dart';
import '../../src/common.dart';
import '../../src/context.dart';
......@@ -33,6 +34,7 @@ void main() {
group('gradle build', () {
late BufferLogger logger;
late TestUsage testUsage;
late FakeAnalytics fakeAnalytics;
late FileSystem fileSystem;
late FakeProcessManager processManager;
......@@ -42,6 +44,11 @@ void main() {
testUsage = TestUsage();
fileSystem = MemoryFileSystem.test();
Cache.flutterRoot = '';
fakeAnalytics = getInitializedFakeAnalyticsInstance(
fs: fileSystem,
fakeFlutterVersion: FakeFlutterVersion(),
);
});
testUsingContext('Can immediately tool exit on recognized exit code/stderr', () async {
......@@ -52,6 +59,7 @@ void main() {
fileSystem: fileSystem,
artifacts: Artifacts.test(),
usage: testUsage,
analytics: fakeAnalytics,
gradleUtils: FakeGradleUtils(),
platform: FakePlatform(),
androidStudio: FakeAndroidStudio(),
......@@ -133,6 +141,15 @@ void main() {
parameters: CustomDimensions(),
),
));
expect(testUsage.events, hasLength(2));
expect(
fakeAnalytics.sentEvents,
unorderedEquals(<Event>[
Event.flutterBuildInfo(label: 'app-not-using-android-x', buildType: 'gradle'),
Event.flutterBuildInfo(label: 'gradle-random-event-label-failure', buildType: 'gradle'),
]),
);
}, overrides: <Type, Generator>{
AndroidStudio: () => FakeAndroidStudio(),
});
......@@ -145,6 +162,7 @@ void main() {
fileSystem: fileSystem,
artifacts: Artifacts.test(),
usage: testUsage,
analytics: fakeAnalytics,
gradleUtils: FakeGradleUtils(),
platform: FakePlatform(),
androidStudio: FakeAndroidStudio(),
......@@ -213,6 +231,7 @@ void main() {
fileSystem: fileSystem,
artifacts: Artifacts.test(),
usage: testUsage,
analytics: fakeAnalytics,
gradleUtils: FakeGradleUtils(),
platform: FakePlatform(),
androidStudio: FakeAndroidStudio(),
......@@ -307,6 +326,15 @@ void main() {
parameters: CustomDimensions(),
),
));
expect(testUsage.events, hasLength(4));
expect(fakeAnalytics.sentEvents, hasLength(4));
expect(fakeAnalytics.sentEvents, contains(
Event.flutterBuildInfo(
label: 'gradle-random-event-label-failure',
buildType: 'gradle',
),
));
}, overrides: <Type, Generator>{
AndroidStudio: () => FakeAndroidStudio(),
});
......@@ -319,6 +347,7 @@ void main() {
fileSystem: fileSystem,
artifacts: Artifacts.test(),
usage: testUsage,
analytics: fakeAnalytics,
gradleUtils: FakeGradleUtils(),
platform: FakePlatform(),
androidStudio: FakeAndroidStudio(),
......@@ -400,6 +429,16 @@ void main() {
parameters: CustomDimensions(),
),
));
expect(testUsage.events, hasLength(2));
expect(fakeAnalytics.sentEvents, hasLength(2));
expect(fakeAnalytics.sentEvents, contains(
Event.flutterBuildInfo(
label: 'gradle-random-event-label-failure',
buildType: 'gradle',
),
));
}, overrides: <Type, Generator>{
AndroidStudio: () => FakeAndroidStudio(),
});
......@@ -412,6 +451,7 @@ void main() {
fileSystem: fileSystem,
artifacts: Artifacts.test(),
usage: testUsage,
analytics: fakeAnalytics,
gradleUtils: FakeGradleUtils(),
platform: FakePlatform(),
androidStudio: FakeAndroidStudio(),
......@@ -477,6 +517,7 @@ void main() {
fileSystem: fileSystem,
artifacts: Artifacts.test(),
usage: testUsage,
analytics: fakeAnalytics,
gradleUtils: FakeGradleUtils(),
platform: FakePlatform(),
androidStudio: FakeAndroidStudio(),
......@@ -581,6 +622,7 @@ void main() {
fileSystem: fileSystem,
artifacts: Artifacts.test(),
usage: testUsage,
analytics: fakeAnalytics,
gradleUtils: FakeGradleUtils(),
platform: FakePlatform(
environment: <String, String>{
......@@ -683,6 +725,7 @@ void main() {
fileSystem: fileSystem,
artifacts: Artifacts.test(),
usage: testUsage,
analytics: fakeAnalytics,
gradleUtils: FakeGradleUtils(),
platform: FakePlatform(),
androidStudio: FakeAndroidStudio(),
......@@ -811,6 +854,7 @@ android {
fileSystem: fileSystem,
artifacts: Artifacts.test(),
usage: testUsage,
analytics: fakeAnalytics,
gradleUtils: FakeGradleUtils(),
platform: FakePlatform(),
androidStudio: FakeAndroidStudio(),
......@@ -846,6 +890,7 @@ BuildVariant: paidProfile
fileSystem: fileSystem,
artifacts: Artifacts.test(),
usage: testUsage,
analytics: fakeAnalytics,
gradleUtils: FakeGradleUtils(),
platform: FakePlatform(),
androidStudio: FakeAndroidStudio(),
......@@ -877,6 +922,7 @@ Gradle Crashed
fileSystem: fileSystem,
artifacts: Artifacts.test(),
usage: testUsage,
analytics: fakeAnalytics,
gradleUtils: FakeGradleUtils(),
platform: FakePlatform(),
androidStudio: FakeAndroidStudio(),
......@@ -904,6 +950,7 @@ Gradle Crashed
fileSystem: fileSystem,
artifacts: Artifacts.test(),
usage: testUsage,
analytics: fakeAnalytics,
gradleUtils: FakeGradleUtils(),
platform: FakePlatform(),
androidStudio: FakeAndroidStudio(),
......@@ -970,6 +1017,7 @@ Gradle Crashed
fileSystem: fileSystem,
artifacts: Artifacts.test(),
usage: testUsage,
analytics: fakeAnalytics,
gradleUtils: FakeGradleUtils(),
platform: FakePlatform(),
androidStudio: FakeAndroidStudio(),
......@@ -1029,6 +1077,7 @@ Gradle Crashed
fileSystem: fileSystem,
artifacts: Artifacts.test(),
usage: testUsage,
analytics: fakeAnalytics,
gradleUtils: FakeGradleUtils(),
platform: FakePlatform(),
androidStudio: FakeAndroidStudio(),
......@@ -1089,6 +1138,7 @@ Gradle Crashed
fileSystem: fileSystem,
artifacts: Artifacts.testLocalEngine(localEngine: 'out/android_arm', localEngineHost: 'out/host_release'),
usage: testUsage,
analytics: fakeAnalytics,
gradleUtils: FakeGradleUtils(),
platform: FakePlatform(),
androidStudio: FakeAndroidStudio(),
......@@ -1169,6 +1219,7 @@ Gradle Crashed
fileSystem: fileSystem,
artifacts: Artifacts.testLocalEngine(localEngine: 'out/android_arm64', localEngineHost: 'out/host_release'),
usage: testUsage,
analytics: fakeAnalytics,
gradleUtils: FakeGradleUtils(),
platform: FakePlatform(),
androidStudio: FakeAndroidStudio(),
......@@ -1249,6 +1300,7 @@ Gradle Crashed
fileSystem: fileSystem,
artifacts: Artifacts.testLocalEngine(localEngine: 'out/android_x86', localEngineHost: 'out/host_release'),
usage: testUsage,
analytics: fakeAnalytics,
gradleUtils: FakeGradleUtils(),
platform: FakePlatform(),
androidStudio: FakeAndroidStudio(),
......@@ -1329,6 +1381,7 @@ Gradle Crashed
fileSystem: fileSystem,
artifacts: Artifacts.testLocalEngine(localEngine: 'out/android_x64', localEngineHost: 'out/host_release'),
usage: testUsage,
analytics: fakeAnalytics,
gradleUtils: FakeGradleUtils(),
platform: FakePlatform(),
androidStudio: FakeAndroidStudio(),
......@@ -1410,6 +1463,7 @@ Gradle Crashed
fileSystem: fileSystem,
artifacts: Artifacts.test(),
usage: testUsage,
analytics: fakeAnalytics,
gradleUtils: FakeGradleUtils(),
platform: FakePlatform(),
androidStudio: FakeAndroidStudio(),
......@@ -1471,6 +1525,7 @@ Gradle Crashed
fileSystem: fileSystem,
artifacts: Artifacts.testLocalEngine(localEngine: 'out/android_arm', localEngineHost: 'out/host_release'),
usage: testUsage,
analytics: fakeAnalytics,
gradleUtils: FakeGradleUtils(),
platform: FakePlatform(),
androidStudio: FakeAndroidStudio(),
......@@ -1560,6 +1615,7 @@ Gradle Crashed
fileSystem: fileSystem,
artifacts: Artifacts.testLocalEngine(localEngine: 'out/android_arm64', localEngineHost: 'out/host_release'),
usage: testUsage,
analytics: fakeAnalytics,
gradleUtils: FakeGradleUtils(),
platform: FakePlatform(),
androidStudio: FakeAndroidStudio(),
......@@ -1649,6 +1705,7 @@ Gradle Crashed
fileSystem: fileSystem,
artifacts: Artifacts.testLocalEngine(localEngine: 'out/android_x86', localEngineHost: 'out/host_release'),
usage: testUsage,
analytics: fakeAnalytics,
gradleUtils: FakeGradleUtils(),
platform: FakePlatform(),
androidStudio: FakeAndroidStudio(),
......@@ -1738,6 +1795,7 @@ Gradle Crashed
fileSystem: fileSystem,
artifacts: Artifacts.testLocalEngine(localEngine: 'out/android_x64', localEngineHost: 'out/host_release'),
usage: testUsage,
analytics: fakeAnalytics,
gradleUtils: FakeGradleUtils(),
platform: FakePlatform(),
androidStudio: FakeAndroidStudio(),
......
......@@ -9,14 +9,21 @@ import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:unified_analytics/unified_analytics.dart';
import '../../src/common.dart';
import '../../src/fakes.dart';
void main() {
late FileSystem fileSystem;
late FakeAnalytics fakeAnalytics;
setUp(() {
fileSystem = MemoryFileSystem.test();
fakeAnalytics = getInitializedFakeAnalyticsInstance(
fs: fileSystem,
fakeFlutterVersion: FakeFlutterVersion(),
);
});
testWithoutContext('Finds app bundle when flavor contains multiple dimensions in release mode', () {
......@@ -26,6 +33,7 @@ void main() {
const BuildInfo(BuildMode.release, 'fooBar', treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -39,6 +47,7 @@ void main() {
const BuildInfo(BuildMode.release, 'foo_bar', treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -52,6 +61,7 @@ void main() {
const BuildInfo(BuildMode.release, 'foo_Bar', treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -65,6 +75,7 @@ void main() {
const BuildInfo(BuildMode.release, 'foo', treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -78,6 +89,7 @@ void main() {
const BuildInfo(BuildMode.release, 'fooA', treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -91,6 +103,7 @@ void main() {
const BuildInfo(BuildMode.release, null, treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -104,6 +117,7 @@ void main() {
const BuildInfo(BuildMode.debug, 'fooBar', treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -117,6 +131,7 @@ void main() {
const BuildInfo(BuildMode.debug, 'foo_bar', treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -130,6 +145,7 @@ void main() {
const BuildInfo(BuildMode.debug, 'foo_Bar', treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -143,6 +159,7 @@ void main() {
const BuildInfo(BuildMode.debug, 'foo', treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -156,6 +173,7 @@ void main() {
const BuildInfo(BuildMode.debug, 'fooA', treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -169,6 +187,7 @@ void main() {
BuildInfo.debug,
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -182,6 +201,7 @@ void main() {
const BuildInfo(BuildMode.profile, 'fooBar', treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -195,6 +215,7 @@ void main() {
const BuildInfo(BuildMode.profile, 'foo_bar', treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -208,6 +229,7 @@ void main() {
const BuildInfo(BuildMode.profile, 'foo_Bar', treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -221,6 +243,7 @@ void main() {
const BuildInfo(BuildMode.profile, 'foo', treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -234,6 +257,7 @@ void main() {
const BuildInfo(BuildMode.profile, 'fooA', treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -247,6 +271,7 @@ void main() {
const BuildInfo(BuildMode.profile, null, treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -260,6 +285,7 @@ void main() {
const BuildInfo(BuildMode.release, null, treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -273,6 +299,7 @@ void main() {
const BuildInfo(BuildMode.profile, null, treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -286,6 +313,7 @@ void main() {
BuildInfo.debug,
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -299,6 +327,7 @@ void main() {
const BuildInfo(BuildMode.release, 'foo_bar', treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -312,6 +341,7 @@ void main() {
const BuildInfo(BuildMode.release, 'foo_Bar', treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -325,6 +355,7 @@ void main() {
const BuildInfo(BuildMode.profile, 'foo_bar', treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -338,6 +369,7 @@ void main() {
const BuildInfo(BuildMode.debug, 'foo_Bar', treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -352,6 +384,7 @@ void main() {
const BuildInfo(BuildMode.release, 'Foo_Bar', treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -366,6 +399,7 @@ void main() {
const BuildInfo(BuildMode.debug, 'Foo_Bar', treeShakeIcons: false),
BufferLogger.test(),
TestUsage(),
fakeAnalytics,
);
expect(bundle, isNotNull);
......@@ -382,6 +416,7 @@ void main() {
const BuildInfo(BuildMode.debug, 'foo_bar', treeShakeIcons: false),
BufferLogger.test(),
testUsage,
fakeAnalytics,
);
},
throwsToolExit(
......@@ -400,6 +435,17 @@ void main() {
}),
),
));
expect(fakeAnalytics.sentEvents, hasLength(1));
expect(
fakeAnalytics.sentEvents,
contains(
Event.flutterBuildInfo(
label: 'gradle-expected-file-not-found',
buildType: 'gradle',
settings: 'androidGradlePluginVersion: 7.5, fileExtension: .aab',
),
),
);
});
}
......
......@@ -17,6 +17,7 @@ import 'package:flutter_tools/src/ios/xcresult.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:test/fake.dart';
import 'package:unified_analytics/unified_analytics.dart';
import '../../src/common.dart';
import '../../src/fake_process_manager.dart';
......@@ -133,12 +134,19 @@ void main() {
group('Diagnose Xcode build failure', () {
late Map<String, String> buildSettings;
late TestUsage testUsage;
late FakeAnalytics fakeAnalytics;
setUp(() {
buildSettings = <String, String>{
'PRODUCT_BUNDLE_IDENTIFIER': 'test.app',
};
testUsage = TestUsage();
final MemoryFileSystem fs = MemoryFileSystem.test();
fakeAnalytics = getInitializedFakeAnalyticsInstance(
fs: fs,
fakeFlutterVersion: FakeFlutterVersion(),
);
});
testWithoutContext('Sends analytics when bitcode fails', () async {
......@@ -154,7 +162,7 @@ void main() {
),
);
await diagnoseXcodeBuildFailure(buildResult, testUsage, logger);
await diagnoseXcodeBuildFailure(buildResult, testUsage, logger, fakeAnalytics);
expect(testUsage.events, contains(
TestUsageEvent(
'build',
......@@ -166,6 +174,15 @@ void main() {
),
),
));
expect(
fakeAnalytics.sentEvents,
contains(Event.flutterBuildInfo(
label: 'xcode-bitcode-failure',
buildType: 'ios',
command: '[xcrun, cc, blah]',
settings: '{PRODUCT_BUNDLE_IDENTIFIER: test.app}'
)),
);
});
testWithoutContext('fallback to stdout: No provisioning profile shows message', () async {
......@@ -238,7 +255,7 @@ Error launching application on iPhone.''',
),
);
await diagnoseXcodeBuildFailure(buildResult, testUsage, logger);
await diagnoseXcodeBuildFailure(buildResult, testUsage, logger, fakeAnalytics);
expect(
logger.errorText,
contains(noProvisioningProfileInstruction),
......@@ -276,7 +293,7 @@ Error launching application on iPhone.''',
),
);
await diagnoseXcodeBuildFailure(buildResult, testUsage, logger);
await diagnoseXcodeBuildFailure(buildResult, testUsage, logger, fakeAnalytics);
expect(
logger.errorText,
contains(missingPlatformInstructions('iOS 17.0')),
......@@ -316,7 +333,7 @@ Could not build the precompiled application for the device.''',
),
);
await diagnoseXcodeBuildFailure(buildResult, testUsage, logger);
await diagnoseXcodeBuildFailure(buildResult, testUsage, logger, fakeAnalytics);
expect(
logger.errorText,
contains('Building a deployable iOS app requires a selected Development Team with a \nProvisioning Profile.'),
......@@ -359,7 +376,7 @@ Could not build the precompiled application for the device.''',
])
);
await diagnoseXcodeBuildFailure(buildResult, testUsage, logger);
await diagnoseXcodeBuildFailure(buildResult, testUsage, logger, fakeAnalytics);
expect(logger.errorText, contains('Error (Xcode): Target aot_assembly_release failed'));
expect(logger.errorText, isNot(contains('Building a deployable iOS app requires a selected Development Team')));
});
......
......@@ -14,6 +14,7 @@ import 'package:flutter_tools/src/ios/xcode_build_settings.dart';
import 'package:flutter_tools/src/ios/xcodeproj.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:unified_analytics/unified_analytics.dart';
import '../../src/common.dart';
import '../../src/context.dart';
......@@ -72,6 +73,7 @@ void main() {
platform: platform,
processManager: fakeProcessManager,
usage: TestUsage(),
analytics: NoOpAnalytics(),
);
});
......@@ -184,6 +186,7 @@ void main() {
platform: platform,
processManager: fakeProcessManager,
usage: TestUsage(),
analytics: NoOpAnalytics(),
);
fileSystem.file(xcodebuild).deleteSync();
......@@ -510,6 +513,7 @@ void main() {
platform: platform,
processManager: fakeProcessManager,
usage: TestUsage(),
analytics: NoOpAnalytics(),
);
expect(await xcodeProjectInterpreter.getInfo(workingDirectory), isNotNull);
......@@ -536,6 +540,7 @@ void main() {
platform: platform,
processManager: fakeProcessManager,
usage: TestUsage(),
analytics: NoOpAnalytics(),
);
expect(() => xcodeProjectInterpreter.getInfo(workingDirectory), throwsToolExit(message: stderr));
......@@ -562,6 +567,7 @@ void main() {
platform: platform,
processManager: fakeProcessManager,
usage: TestUsage(),
analytics: NoOpAnalytics(),
);
expect(() => xcodeProjectInterpreter.getInfo(workingDirectory), throwsToolExit(message: stderr));
......
......@@ -9,9 +9,9 @@ import 'package:flutter_tools/src/build_system/build_system.dart';
import 'package:flutter_tools/src/build_system/targets/web.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:flutter_tools/src/version.dart';
import 'package:flutter_tools/src/web/compile.dart';
import 'package:flutter_tools/src/web/file_generators/flutter_service_worker_js.dart';
import 'package:unified_analytics/unified_analytics.dart';
import '../../src/common.dart';
import '../../src/context.dart';
......@@ -21,8 +21,9 @@ import '../../src/test_build_system.dart';
void main() {
late MemoryFileSystem fileSystem;
late TestUsage testUsage;
late FakeAnalytics fakeAnalytics;
late BufferLogger logger;
late FlutterVersion flutterVersion;
late FakeFlutterVersion flutterVersion;
late FlutterProject flutterProject;
setUp(() {
......@@ -30,6 +31,10 @@ void main() {
testUsage = TestUsage();
logger = BufferLogger.test();
flutterVersion = FakeFlutterVersion(frameworkVersion: '1.0.0', engineRevision: '9.8.7');
fakeAnalytics = getInitializedFakeAnalyticsInstance(
fs: fileSystem,
fakeFlutterVersion: flutterVersion,
);
flutterProject = FlutterProject.fromDirectoryTest(fileSystem.currentDirectory);
fileSystem.file('.packages').createSync();
......@@ -65,6 +70,7 @@ void main() {
usage: testUsage,
flutterVersion: flutterVersion,
fileSystem: fileSystem,
analytics: fakeAnalytics,
);
await webBuilder.buildWeb(
flutterProject,
......@@ -103,6 +109,17 @@ void main() {
),
);
expect(
fakeAnalytics.sentEvents,
unorderedEquals(<Event>[
Event.flutterBuildInfo(
label: 'web-compile',
buildType: 'web',
settings: 'RunWasmOpt: none; WasmOmitTypeChecks: false; wasm-compile: true; web-renderer: auto;',
),
]),
);
// Sends timing event.
final TestTimingEvent timingEvent = testUsage.timings.single;
expect(timingEvent.category, 'build');
......@@ -128,6 +145,7 @@ void main() {
usage: testUsage,
flutterVersion: flutterVersion,
fileSystem: fileSystem,
analytics: fakeAnalytics,
);
await expectLater(
() async => webBuilder.buildWeb(
......
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