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) { ...@@ -469,6 +469,7 @@ List<String> _flutterCommandArgs(String command, List<String> options) {
final String? localEngineHost = localEngineHostFromEnv; final String? localEngineHost = localEngineHostFromEnv;
final String? localEngineSrcPath = localEngineSrcPathFromEnv; final String? localEngineSrcPath = localEngineSrcPathFromEnv;
final String? localWebSdk = localWebSdkFromEnv; final String? localWebSdk = localWebSdkFromEnv;
final bool pubOrPackagesCommand = command.startsWith('packages') || command.startsWith('pub');
return <String>[ return <String>[
command, command,
if (deviceOperatingSystem == DeviceOperatingSystem.ios && supportedDeviceTimeoutCommands.contains(command)) if (deviceOperatingSystem == DeviceOperatingSystem.ios && supportedDeviceTimeoutCommands.contains(command))
...@@ -489,7 +490,9 @@ List<String> _flutterCommandArgs(String command, List<String> options) { ...@@ -489,7 +490,9 @@ List<String> _flutterCommandArgs(String command, List<String> options) {
// Use CI flag when running devicelab tests, except for `packages`/`pub` commands. // Use CI flag when running devicelab tests, except for `packages`/`pub` commands.
// `packages`/`pub` commands effectively runs the `pub` tool, which does not have // `packages`/`pub` commands effectively runs the `pub` tool, which does not have
// the same allowed args. // 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. ...@@ -525,6 +525,7 @@ known, it can be explicitly provided to attach via the command-line, e.g.
devToolsServerAddress: devToolsServerAddress, devToolsServerAddress: devToolsServerAddress,
serveObservatory: serveObservatory, serveObservatory: serveObservatory,
usingCISystem: usingCISystem, usingCISystem: usingCISystem,
debugLogsDirectoryPath: debugLogsDirectoryPath,
); );
return buildInfo.isDebug return buildInfo.isDebug
......
...@@ -264,6 +264,7 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment ...@@ -264,6 +264,7 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
enableDartProfiling: enableDartProfiling, enableDartProfiling: enableDartProfiling,
enableEmbedderApi: enableEmbedderApi, enableEmbedderApi: enableEmbedderApi,
usingCISystem: usingCISystem, usingCISystem: usingCISystem,
debugLogsDirectoryPath: debugLogsDirectoryPath,
); );
} else { } else {
return DebuggingOptions.enabled( return DebuggingOptions.enabled(
...@@ -319,6 +320,7 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment ...@@ -319,6 +320,7 @@ abstract class RunCommandBase extends FlutterCommand with DeviceBasedDevelopment
enableDartProfiling: enableDartProfiling, enableDartProfiling: enableDartProfiling,
enableEmbedderApi: enableEmbedderApi, enableEmbedderApi: enableEmbedderApi,
usingCISystem: usingCISystem, usingCISystem: usingCISystem,
debugLogsDirectoryPath: debugLogsDirectoryPath,
); );
} }
} }
......
...@@ -364,6 +364,7 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts { ...@@ -364,6 +364,7 @@ class TestCommand extends FlutterCommand with DeviceBasedDevelopmentArtifacts {
nullAssertions: boolArg(FlutterOptions.kNullAssertions), nullAssertions: boolArg(FlutterOptions.kNullAssertions),
usingCISystem: usingCISystem, usingCISystem: usingCISystem,
enableImpeller: ImpellerStatus.fromBool(argResults!['enable-impeller'] as bool?), enableImpeller: ImpellerStatus.fromBool(argResults!['enable-impeller'] as bool?),
debugLogsDirectoryPath: debugLogsDirectoryPath,
); );
String? testAssetDirectory; String? testAssetDirectory;
......
...@@ -963,6 +963,7 @@ class DebuggingOptions { ...@@ -963,6 +963,7 @@ class DebuggingOptions {
this.enableDartProfiling = true, this.enableDartProfiling = true,
this.enableEmbedderApi = false, this.enableEmbedderApi = false,
this.usingCISystem = false, this.usingCISystem = false,
this.debugLogsDirectoryPath,
}) : debuggingEnabled = true; }) : debuggingEnabled = true;
DebuggingOptions.disabled(this.buildInfo, { DebuggingOptions.disabled(this.buildInfo, {
...@@ -988,6 +989,7 @@ class DebuggingOptions { ...@@ -988,6 +989,7 @@ class DebuggingOptions {
this.enableDartProfiling = true, this.enableDartProfiling = true,
this.enableEmbedderApi = false, this.enableEmbedderApi = false,
this.usingCISystem = false, this.usingCISystem = false,
this.debugLogsDirectoryPath,
}) : debuggingEnabled = false, }) : debuggingEnabled = false,
useTestFonts = false, useTestFonts = false,
startPaused = false, startPaused = false,
...@@ -1069,6 +1071,7 @@ class DebuggingOptions { ...@@ -1069,6 +1071,7 @@ class DebuggingOptions {
required this.enableDartProfiling, required this.enableDartProfiling,
required this.enableEmbedderApi, required this.enableEmbedderApi,
required this.usingCISystem, required this.usingCISystem,
required this.debugLogsDirectoryPath,
}); });
final bool debuggingEnabled; final bool debuggingEnabled;
...@@ -1112,6 +1115,7 @@ class DebuggingOptions { ...@@ -1112,6 +1115,7 @@ class DebuggingOptions {
final bool enableDartProfiling; final bool enableDartProfiling;
final bool enableEmbedderApi; final bool enableEmbedderApi;
final bool usingCISystem; final bool usingCISystem;
final String? debugLogsDirectoryPath;
/// Whether the tool should try to uninstall a previously installed version of the app. /// Whether the tool should try to uninstall a previously installed version of the app.
/// ///
...@@ -1258,6 +1262,7 @@ class DebuggingOptions { ...@@ -1258,6 +1262,7 @@ class DebuggingOptions {
'enableDartProfiling': enableDartProfiling, 'enableDartProfiling': enableDartProfiling,
'enableEmbedderApi': enableEmbedderApi, 'enableEmbedderApi': enableEmbedderApi,
'usingCISystem': usingCISystem, 'usingCISystem': usingCISystem,
'debugLogsDirectoryPath': debugLogsDirectoryPath,
}; };
static DebuggingOptions fromJson(Map<String, Object?> json, BuildInfo buildInfo) => static DebuggingOptions fromJson(Map<String, Object?> json, BuildInfo buildInfo) =>
...@@ -1313,6 +1318,7 @@ class DebuggingOptions { ...@@ -1313,6 +1318,7 @@ class DebuggingOptions {
enableDartProfiling: (json['enableDartProfiling'] as bool?) ?? true, enableDartProfiling: (json['enableDartProfiling'] as bool?) ?? true,
enableEmbedderApi: (json['enableEmbedderApi'] as bool?) ?? false, enableEmbedderApi: (json['enableEmbedderApi'] as bool?) ?? false,
usingCISystem: (json['usingCISystem'] as bool?) ?? false, usingCISystem: (json['usingCISystem'] as bool?) ?? false,
debugLogsDirectoryPath: json['debugLogsDirectoryPath'] as String?,
); );
} }
......
...@@ -377,6 +377,8 @@ abstract class FlutterCommand extends Command<void> { ...@@ -377,6 +377,8 @@ abstract class FlutterCommand extends Command<void> {
/// Whether flutter is being run from our CI. /// Whether flutter is being run from our CI.
bool get usingCISystem => boolArg(FlutterGlobalOptions.kContinuousIntegrationFlag, global: true); bool get usingCISystem => boolArg(FlutterGlobalOptions.kContinuousIntegrationFlag, global: true);
String? get debugLogsDirectoryPath => stringArg(FlutterGlobalOptions.kDebugLogsDirectoryFlag, global: true);
/// The value of the `--filesystem-scheme` argument. /// The value of the `--filesystem-scheme` argument.
/// ///
/// This can be overridden by some of its subclasses. /// This can be overridden by some of its subclasses.
......
...@@ -44,6 +44,7 @@ abstract final class FlutterGlobalOptions { ...@@ -44,6 +44,7 @@ abstract final class FlutterGlobalOptions {
static const String kVersionFlag = 'version'; static const String kVersionFlag = 'version';
static const String kWrapColumnOption = 'wrap-column'; static const String kWrapColumnOption = 'wrap-column';
static const String kWrapFlag = 'wrap'; static const String kWrapFlag = 'wrap';
static const String kDebugLogsDirectoryFlag = 'debug-logs-dir';
} }
class FlutterCommandRunner extends CommandRunner<void> { class FlutterCommandRunner extends CommandRunner<void> {
...@@ -164,6 +165,11 @@ class FlutterCommandRunner extends CommandRunner<void> { ...@@ -164,6 +165,11 @@ class FlutterCommandRunner extends CommandRunner<void> {
help: 'Enable a set of CI-specific test debug settings.', help: 'Enable a set of CI-specific test debug settings.',
hide: !verboseHelp, hide: !verboseHelp,
); );
argParser.addOption(
FlutterGlobalOptions.kDebugLogsDirectoryFlag,
help: 'Path to a directory where logs for debugging may be added.',
hide: !verboseHelp,
);
} }
@override @override
......
...@@ -427,6 +427,7 @@ void main() { ...@@ -427,6 +427,7 @@ void main() {
'--skia-deterministic-rendering', '--skia-deterministic-rendering',
'--enable-embedder-api', '--enable-embedder-api',
'--ci', '--ci',
'--debug-logs-dir=path/to/logs'
]), throwsToolExit()); ]), throwsToolExit());
final DebuggingOptions options = await command.createDebuggingOptions(false); final DebuggingOptions options = await command.createDebuggingOptions(false);
...@@ -444,6 +445,7 @@ void main() { ...@@ -444,6 +445,7 @@ void main() {
expect(options.enableSoftwareRendering, true); expect(options.enableSoftwareRendering, true);
expect(options.skiaDeterministicRendering, true); expect(options.skiaDeterministicRendering, true);
expect(options.usingCISystem, true); expect(options.usingCISystem, true);
expect(options.debugLogsDirectoryPath, 'path/to/logs');
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
Cache: () => Cache.test(processManager: FakeProcessManager.any()), Cache: () => Cache.test(processManager: FakeProcessManager.any()),
FileSystem: () => MemoryFileSystem.test(), FileSystem: () => MemoryFileSystem.test(),
......
...@@ -1262,6 +1262,7 @@ void main() { ...@@ -1262,6 +1262,7 @@ void main() {
'--skia-deterministic-rendering', '--skia-deterministic-rendering',
'--enable-embedder-api', '--enable-embedder-api',
'--ci', '--ci',
'--debug-logs-dir=path/to/logs'
]), throwsToolExit()); ]), throwsToolExit());
final DebuggingOptions options = await command.createDebuggingOptions(false); final DebuggingOptions options = await command.createDebuggingOptions(false);
...@@ -1281,6 +1282,7 @@ void main() { ...@@ -1281,6 +1282,7 @@ void main() {
expect(options.enableSoftwareRendering, true); expect(options.enableSoftwareRendering, true);
expect(options.skiaDeterministicRendering, true); expect(options.skiaDeterministicRendering, true);
expect(options.usingCISystem, true); expect(options.usingCISystem, true);
expect(options.debugLogsDirectoryPath, 'path/to/logs');
}, overrides: <Type, Generator>{ }, overrides: <Type, Generator>{
Cache: () => Cache.test(processManager: FakeProcessManager.any()), Cache: () => Cache.test(processManager: FakeProcessManager.any()),
FileSystem: () => MemoryFileSystem.test(), FileSystem: () => MemoryFileSystem.test(),
......
...@@ -966,6 +966,78 @@ void main() { ...@@ -966,6 +966,78 @@ void main() {
MDnsVmServiceDiscovery: () => mdnsDiscovery, 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({ ...@@ -980,9 +1052,10 @@ IOSDevice setUpIOSDevice({
bool isCoreDevice = false, bool isCoreDevice = false,
IOSCoreDeviceControl? coreDeviceControl, IOSCoreDeviceControl? coreDeviceControl,
FakeXcodeDebug? xcodeDebug, FakeXcodeDebug? xcodeDebug,
FakePlatform? platform,
}) { }) {
final Artifacts artifacts = Artifacts.test(); final Artifacts artifacts = Artifacts.test();
final FakePlatform macPlatform = FakePlatform( final FakePlatform macPlatform = platform ?? FakePlatform(
operatingSystem: 'macos', operatingSystem: 'macos',
environment: <String, String>{}, 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