Unverified Commit e5c286e0 authored by Victoria Ashworth's avatar Victoria Ashworth Committed by GitHub

Upload DerivedData logs in CI (#142643)

When the Dart VM is not found within 10 minutes in CI on CoreDevices (iOS 17+), stop the app and upload the logs from DerivedData. The app has to be stopped first since the logs are not put in DerivedData until it's stopped.

Also, rearranged some logic to have CoreDevice have its own function for Dart VM url discovery.

Debugging for https://github.com/flutter/flutter/issues/142448.
parent 899f4234
......@@ -469,6 +469,7 @@ List<String> _flutterCommandArgs(String command, List<String> options) {
final String? localEngineHost = localEngineHostFromEnv;
final String? localEngineSrcPath = localEngineSrcPathFromEnv;
final String? localWebSdk = localWebSdkFromEnv;
final bool pubOrPackagesCommand = command.startsWith('packages') || command.startsWith('pub');
return <String>[
command,
if (deviceOperatingSystem == DeviceOperatingSystem.ios && supportedDeviceTimeoutCommands.contains(command))
......@@ -489,7 +490,9 @@ List<String> _flutterCommandArgs(String command, List<String> options) {
// Use CI flag when running devicelab tests, except for `packages`/`pub` commands.
// `packages`/`pub` commands effectively runs the `pub` tool, which does not have
// the same allowed args.
if (!command.startsWith('packages') && !command.startsWith('pub')) '--ci',
if (!pubOrPackagesCommand) '--ci',
if (!pubOrPackagesCommand && hostAgent.dumpDirectory != null)
'--debug-logs-dir=${hostAgent.dumpDirectory!.path}'
];
}
......
......@@ -525,6 +525,7 @@ known, it can be explicitly provided to attach via the command-line, e.g.
devToolsServerAddress: devToolsServerAddress,
serveObservatory: serveObservatory,
usingCISystem: usingCISystem,
debugLogsDirectoryPath: debugLogsDirectoryPath,
);
return buildInfo.isDebug
......
......@@ -264,6 +264,7 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
enableDartProfiling: enableDartProfiling,
enableEmbedderApi: enableEmbedderApi,
usingCISystem: usingCISystem,
debugLogsDirectoryPath: debugLogsDirectoryPath,
);
} else {
return DebuggingOptions.enabled(
......@@ -319,6 +320,7 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
enableDartProfiling: enableDartProfiling,
enableEmbedderApi: enableEmbedderApi,
usingCISystem: usingCISystem,
debugLogsDirectoryPath: debugLogsDirectoryPath,
);
}
}
......
......@@ -364,6 +364,7 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
nullAssertions: boolArg(FlutterOptions.kNullAssertions),
usingCISystem: usingCISystem,
enableImpeller: ImpellerStatus.fromBool(argResults!['enable-impeller'] as bool?),
debugLogsDirectoryPath: debugLogsDirectoryPath,
);
String? testAssetDirectory;
......
......@@ -963,6 +963,7 @@ class DebuggingOptions {
this.enableDartProfiling = true,
this.enableEmbedderApi = false,
this.usingCISystem = false,
this.debugLogsDirectoryPath,
}) : debuggingEnabled = true;
DebuggingOptions.disabled(this.buildInfo, {
......@@ -988,6 +989,7 @@ class DebuggingOptions {
this.enableDartProfiling = true,
this.enableEmbedderApi = false,
this.usingCISystem = false,
this.debugLogsDirectoryPath,
}) : debuggingEnabled = false,
useTestFonts = false,
startPaused = false,
......@@ -1069,6 +1071,7 @@ class DebuggingOptions {
required this.enableDartProfiling,
required this.enableEmbedderApi,
required this.usingCISystem,
required this.debugLogsDirectoryPath,
});
final bool debuggingEnabled;
......@@ -1112,6 +1115,7 @@ class DebuggingOptions {
final bool enableDartProfiling;
final bool enableEmbedderApi;
final bool usingCISystem;
final String? debugLogsDirectoryPath;
/// Whether the tool should try to uninstall a previously installed version of the app.
///
......@@ -1258,6 +1262,7 @@ class DebuggingOptions {
'enableDartProfiling': enableDartProfiling,
'enableEmbedderApi': enableEmbedderApi,
'usingCISystem': usingCISystem,
'debugLogsDirectoryPath': debugLogsDirectoryPath,
};
static DebuggingOptions fromJson(Map<String, Object?> json, BuildInfo buildInfo) =>
......@@ -1313,6 +1318,7 @@ class DebuggingOptions {
enableDartProfiling: (json['enableDartProfiling'] as bool?) ?? true,
enableEmbedderApi: (json['enableEmbedderApi'] as bool?) ?? false,
usingCISystem: (json['usingCISystem'] as bool?) ?? false,
debugLogsDirectoryPath: json['debugLogsDirectoryPath'] as String?,
);
}
......
......@@ -377,6 +377,8 @@ abstract class FlutterCommand extends Command<void> {
/// Whether flutter is being run from our CI.
bool get usingCISystem => boolArg(FlutterGlobalOptions.kContinuousIntegrationFlag, global: true);
String? get debugLogsDirectoryPath => stringArg(FlutterGlobalOptions.kDebugLogsDirectoryFlag, global: true);
/// The value of the `--filesystem-scheme` argument.
///
/// This can be overridden by some of its subclasses.
......
......@@ -44,6 +44,7 @@ abstract final class FlutterGlobalOptions {
static const String kVersionFlag = 'version';
static const String kWrapColumnOption = 'wrap-column';
static const String kWrapFlag = 'wrap';
static const String kDebugLogsDirectoryFlag = 'debug-logs-dir';
}
class FlutterCommandRunner extends CommandRunner<void> {
......@@ -164,6 +165,11 @@ class FlutterCommandRunner extends CommandRunner<void> {
help: 'Enable a set of CI-specific test debug settings.',
hide: !verboseHelp,
);
argParser.addOption(
FlutterGlobalOptions.kDebugLogsDirectoryFlag,
help: 'Path to a directory where logs for debugging may be added.',
hide: !verboseHelp,
);
}
@override
......
......@@ -427,6 +427,7 @@ void main() {
'--skia-deterministic-rendering',
'--enable-embedder-api',
'--ci',
'--debug-logs-dir=path/to/logs'
]), throwsToolExit());
final DebuggingOptions options = await command.createDebuggingOptions(false);
......@@ -444,6 +445,7 @@ void main() {
expect(options.enableSoftwareRendering, true);
expect(options.skiaDeterministicRendering, true);
expect(options.usingCISystem, true);
expect(options.debugLogsDirectoryPath, 'path/to/logs');
}, overrides: <Type, Generator>{
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
FileSystem: () => MemoryFileSystem.test(),
......
......@@ -1262,6 +1262,7 @@ void main() {
'--skia-deterministic-rendering',
'--enable-embedder-api',
'--ci',
'--debug-logs-dir=path/to/logs'
]), throwsToolExit());
final DebuggingOptions options = await command.createDebuggingOptions(false);
......@@ -1281,6 +1282,7 @@ void main() {
expect(options.enableSoftwareRendering, true);
expect(options.skiaDeterministicRendering, true);
expect(options.usingCISystem, true);
expect(options.debugLogsDirectoryPath, 'path/to/logs');
}, overrides: <Type, Generator>{
Cache: () => Cache.test(processManager: FakeProcessManager.any()),
FileSystem: () => MemoryFileSystem.test(),
......
......@@ -966,6 +966,78 @@ void main() {
MDnsVmServiceDiscovery: () => mdnsDiscovery,
});
});
testUsingContext('IOSDevice.startApp fails to find Dart VM in CI', () async {
final FileSystem fileSystem = MemoryFileSystem.test();
final FakeProcessManager processManager = FakeProcessManager.empty();
const String pathToFlutterLogs = '/path/to/flutter/logs';
const String pathToHome = '/path/to/home';
final Directory temporaryXcodeProjectDirectory = fileSystem.systemTempDirectory.childDirectory('flutter_empty_xcode.rand0');
final Directory bundleLocation = fileSystem.currentDirectory;
final IOSDevice device = setUpIOSDevice(
processManager: processManager,
fileSystem: fileSystem,
isCoreDevice: true,
coreDeviceControl: FakeIOSCoreDeviceControl(),
xcodeDebug: FakeXcodeDebug(
expectedProject: XcodeDebugProject(
scheme: 'Runner',
xcodeWorkspace: temporaryXcodeProjectDirectory.childDirectory('Runner.xcworkspace'),
xcodeProject: temporaryXcodeProjectDirectory.childDirectory('Runner.xcodeproj'),
hostAppProjectName: 'Runner',
),
expectedDeviceId: '123',
expectedLaunchArguments: <String>['--enable-dart-profiling'],
expectedBundlePath: bundleLocation.path,
),
platform: FakePlatform(
operatingSystem: 'macos',
environment: <String, String>{
'HOME': pathToHome,
},
),
);
final IOSApp iosApp = PrebuiltIOSApp(
projectBundleId: 'app',
bundleName: 'Runner',
uncompressedBundle: bundleLocation,
applicationPackage: bundleLocation,
);
final FakeDeviceLogReader deviceLogReader = FakeDeviceLogReader();
device.portForwarder = const NoOpDevicePortForwarder();
device.setLogReader(iosApp, deviceLogReader);
const String projectLogsPath = 'Runner-project1/Logs/Launch/Runner.xcresults';
fileSystem.directory('$pathToHome/Library/Developer/Xcode/DerivedData/$projectLogsPath').createSync(recursive: true);
final Completer<void> completer = Completer<void>();
await FakeAsync().run((FakeAsync time) {
final Future<LaunchResult> futureLaunchResult = device.startApp(iosApp,
prebuiltApplication: true,
debuggingOptions: DebuggingOptions.enabled(
BuildInfo.debug,
usingCISystem: true,
debugLogsDirectoryPath: pathToFlutterLogs,
),
platformArgs: <String, dynamic>{},
);
futureLaunchResult.then((LaunchResult launchResult) {
expect(launchResult.started, false);
expect(launchResult.hasVmService, false);
expect(fileSystem.directory('$pathToFlutterLogs/DerivedDataLogs/$projectLogsPath').existsSync(), true);
completer.complete();
});
time.elapse(const Duration(minutes: 15));
time.flushMicrotasks();
return completer.future;
});
}, overrides: <Type, Generator>{
MDnsVmServiceDiscovery: () => FakeMDnsVmServiceDiscovery(returnsNull: true),
});
});
});
}
......@@ -980,9 +1052,10 @@ IOSDevice setUpIOSDevice({
bool isCoreDevice = false,
IOSCoreDeviceControl? coreDeviceControl,
FakeXcodeDebug? xcodeDebug,
FakePlatform? platform,
}) {
final Artifacts artifacts = Artifacts.test();
final FakePlatform macPlatform = FakePlatform(
final FakePlatform macPlatform = platform ?? FakePlatform(
operatingSystem: 'macos',
environment: <String, String>{},
);
......
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