Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ci] Upload screenshots, logs, and Xcode test results for drive and integration_test runs #7430

Merged
merged 8 commits into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions script/tool/lib/src/common/core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// found in the LICENSE file.

import 'package:file/file.dart';
import 'package:platform/platform.dart';
import 'package:pub_semver/pub_semver.dart';

/// The signature for a print handler for commands that allow overriding the
Expand Down Expand Up @@ -127,3 +128,13 @@ const int exitCommandFoundErrors = 1;

/// A exit code for [ToolExit] for a failure to run due to invalid arguments.
const int exitInvalidArguments = 2;

/// The directory to which to write logs and other artifacts, if set in CI.
Directory? ciLogsDirectory(Platform platform, FileSystem fileSystem) {
final String? logsDirectoryPath = platform.environment['FLUTTER_LOGS_DIR'];
Directory? logsDirectory;
if (logsDirectoryPath != null) {
logsDirectory = fileSystem.directory(logsDirectoryPath);
}
return logsDirectory;
}
95 changes: 71 additions & 24 deletions script/tool/lib/src/common/xcode.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import 'dart:convert';
import 'dart:io' as io;

import 'package:file/file.dart';
import 'package:platform/platform.dart';

import 'core.dart';
import 'output_utils.dart';
import 'process_runner.dart';

Expand All @@ -33,36 +35,81 @@ class Xcode {
/// Runs an `xcodebuild` in [directory] with the given parameters.
Future<int> runXcodeBuild(
Directory exampleDirectory,
String platform, {
String targetPlatform, {
List<String> actions = const <String>['build'],
required String workspace,
required String scheme,
String? configuration,
List<String> extraFlags = const <String>[],
}) {
File? disabledSandboxEntitlementFile;
if (actions.contains('test') && platform.toLowerCase() == 'macos') {
disabledSandboxEntitlementFile = _createDisabledSandboxEntitlementFile(
exampleDirectory.childDirectory(platform.toLowerCase()),
configuration ?? 'Debug',
);
}
final List<String> args = <String>[
_xcodeBuildCommand,
...actions,
...<String>['-workspace', workspace],
...<String>['-scheme', scheme],
if (configuration != null) ...<String>['-configuration', configuration],
...extraFlags,
if (disabledSandboxEntitlementFile != null)
'CODE_SIGN_ENTITLEMENTS=${disabledSandboxEntitlementFile.path}',
];
final String completeTestCommand = '$_xcRunCommand ${args.join(' ')}';
if (log) {
print(completeTestCommand);
required Platform hostPlatform,
}) async {
final FileSystem fileSystem = exampleDirectory.fileSystem;
String? resultBundlePath;
final Directory? logsDirectory = ciLogsDirectory(hostPlatform, fileSystem);
Directory? resultBundleTemp;
try {
if (logsDirectory != null) {
resultBundleTemp =
fileSystem.systemTempDirectory.createTempSync('flutter_xcresult.');
resultBundlePath = resultBundleTemp.childDirectory('result').path;
}
File? disabledSandboxEntitlementFile;
if (actions.contains('test') && targetPlatform.toLowerCase() == 'macos') {
disabledSandboxEntitlementFile = _createDisabledSandboxEntitlementFile(
exampleDirectory.childDirectory(targetPlatform.toLowerCase()),
configuration ?? 'Debug',
);
}
final List<String> args = <String>[
_xcodeBuildCommand,
...actions,
...<String>['-workspace', workspace],
...<String>['-scheme', scheme],
if (resultBundlePath != null) ...<String>[
'-resultBundlePath',
resultBundlePath
],
if (configuration != null) ...<String>['-configuration', configuration],
...extraFlags,
if (disabledSandboxEntitlementFile != null)
'CODE_SIGN_ENTITLEMENTS=${disabledSandboxEntitlementFile.path}',
];
final String completeTestCommand = '$_xcRunCommand ${args.join(' ')}';
if (log) {
print(completeTestCommand);
}
final int resultExit = await processRunner
.runAndStream(_xcRunCommand, args, workingDir: exampleDirectory);

if (resultExit != 0 && resultBundleTemp != null) {
final Directory xcresultBundle =
resultBundleTemp.childDirectory('result.xcresult');
if (logsDirectory != null) {
if (xcresultBundle.existsSync()) {
// Zip the test results to the artifacts directory for upload.
final File zipPath = logsDirectory.childFile(
'xcodebuild-${DateTime.now().toLocal().toIso8601String()}.zip');
await processRunner.run(
'zip',
<String>[
'-r',
'-9',
'-q',
zipPath.path,
xcresultBundle.basename,
],
workingDir: resultBundleTemp,
);
} else {
print(
'xcresult bundle ${xcresultBundle.path} does not exist, skipping upload');
}
}
}
return resultExit;
} finally {
resultBundleTemp?.deleteSync(recursive: true);
}
jmagman marked this conversation as resolved.
Show resolved Hide resolved
return processRunner.runAndStream(_xcRunCommand, args,
workingDir: exampleDirectory);
}

/// Returns true if [project], which should be an .xcodeproj directory,
Expand Down
19 changes: 17 additions & 2 deletions script/tool/lib/src/drive_examples_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,12 @@ class DriveExamplesCommand extends PackageLoopingCommand {
}
for (final File driver in drivers) {
final List<File> failingTargets = await _driveTests(
example, driver, testTargets,
deviceFlags: deviceFlags);
example,
driver,
testTargets,
deviceFlags: deviceFlags,
exampleName: exampleName,
);
for (final File failingTarget in failingTargets) {
errors.add(
getRelativePosixPath(failingTarget, from: package.directory));
Expand Down Expand Up @@ -376,10 +380,16 @@ class DriveExamplesCommand extends PackageLoopingCommand {
File driver,
List<File> targets, {
required List<String> deviceFlags,
required String exampleName,
}) async {
final List<File> failures = <File>[];

final String enableExperiment = getStringArg(kEnableExperiment);
final String screenshotBasename =
'${exampleName.replaceAll(platform.pathSeparator, '_')}-drive';
final Directory? screenshotDirectory =
ciLogsDirectory(platform, driver.fileSystem)
?.childDirectory(screenshotBasename);

for (final File target in targets) {
final int exitCode = await processRunner.runAndStream(
Expand All @@ -389,6 +399,8 @@ class DriveExamplesCommand extends PackageLoopingCommand {
...deviceFlags,
if (enableExperiment.isNotEmpty)
'--enable-experiment=$enableExperiment',
if (screenshotDirectory != null)
'--screenshot=${screenshotDirectory.path}',
'--driver',
getRelativePosixPath(driver, from: example.directory),
'--target',
Expand Down Expand Up @@ -416,6 +428,8 @@ class DriveExamplesCommand extends PackageLoopingCommand {
required List<File> testFiles,
}) async {
final String enableExperiment = getStringArg(kEnableExperiment);
final Directory? logsDirectory =
ciLogsDirectory(platform, testFiles.first.fileSystem);

// Workaround for https://github.com/flutter/flutter/issues/135673
// Once that is fixed on stable, this logic can be removed and the command
Expand All @@ -438,6 +452,7 @@ class DriveExamplesCommand extends PackageLoopingCommand {
...deviceFlags,
if (enableExperiment.isNotEmpty)
'--enable-experiment=$enableExperiment',
if (logsDirectory != null) '--debug-logs-dir=${logsDirectory.path}',
target,
],
workingDir: example.directory);
Expand Down
16 changes: 9 additions & 7 deletions script/tool/lib/src/native_test_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ this command.
/// usually at "example/{ios,macos}/Runner.xcworkspace".
Future<_PlatformResult> _runXcodeTests(
RepositoryPackage plugin,
String platform,
String targetPlatform,
_TestMode mode, {
List<String> extraFlags = const <String>[],
}) async {
Expand All @@ -456,7 +456,7 @@ this command.
final String? targetToCheck =
testTarget ?? (mode.unit ? unitTestTarget : null);
final Directory xcodeProject = example.directory
.childDirectory(platform.toLowerCase())
.childDirectory(targetPlatform.toLowerCase())
.childDirectory('Runner.xcodeproj');
if (targetToCheck != null) {
final bool? hasTarget =
Expand All @@ -473,16 +473,17 @@ this command.
}
}

_printRunningExampleTestsMessage(example, platform);
_printRunningExampleTestsMessage(example, targetPlatform);
final int exitCode = await _xcode.runXcodeBuild(
example.directory,
platform,
targetPlatform,
// Clean before testing to remove cached swiftmodules from previous
// runs, which can cause conflicts.
actions: <String>['clean', 'test'],
workspace: '${platform.toLowerCase()}/Runner.xcworkspace',
workspace: '${targetPlatform.toLowerCase()}/Runner.xcworkspace',
scheme: 'Runner',
configuration: 'Debug',
hostPlatform: platform,
extraFlags: <String>[
if (testTarget != null) '-only-testing:$testTarget',
...extraFlags,
Expand All @@ -494,9 +495,10 @@ this command.
const int xcodebuildNoTestExitCode = 66;
switch (exitCode) {
case xcodebuildNoTestExitCode:
_printNoExampleTestsMessage(example, platform);
_printNoExampleTestsMessage(example, targetPlatform);
case 0:
printSuccess('Successfully ran $platform xctest for $exampleName');
printSuccess(
'Successfully ran $targetPlatform xctest for $exampleName');
// If this is the first test, assume success until something fails.
if (overallResult == RunState.skipped) {
overallResult = RunState.succeeded;
Expand Down
15 changes: 8 additions & 7 deletions script/tool/lib/src/xcode_analyze_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -97,36 +97,37 @@ class XcodeAnalyzeCommand extends PackageLoopingCommand {
multiplePlatformsRequested ? failures : <String>[]);
}

/// Analyzes [plugin] for [platform], returning true if it passed analysis.
/// Analyzes [plugin] for [targetPlatform], returning true if it passed analysis.
Future<bool> _analyzePlugin(
RepositoryPackage plugin,
String platform, {
String targetPlatform, {
List<String> extraFlags = const <String>[],
}) async {
bool passing = true;
for (final RepositoryPackage example in plugin.getExamples()) {
// Running tests and static analyzer.
final String examplePath = getRelativePosixPath(example.directory,
from: plugin.directory.parent);
print('Running $platform tests and analyzer for $examplePath...');
print('Running $targetPlatform tests and analyzer for $examplePath...');
final int exitCode = await _xcode.runXcodeBuild(
example.directory,
platform,
targetPlatform,
// Clean before analyzing to remove cached swiftmodules from previous
// runs, which can cause conflicts.
actions: <String>['clean', 'analyze'],
workspace: '${platform.toLowerCase()}/Runner.xcworkspace',
workspace: '${targetPlatform.toLowerCase()}/Runner.xcworkspace',
scheme: 'Runner',
configuration: 'Debug',
hostPlatform: platform,
extraFlags: <String>[
...extraFlags,
'GCC_TREAT_WARNINGS_AS_ERRORS=YES',
],
);
if (exitCode == 0) {
printSuccess('$examplePath ($platform) passed analysis.');
printSuccess('$examplePath ($targetPlatform) passed analysis.');
} else {
printError('$examplePath ($platform) failed analysis.');
printError('$examplePath ($targetPlatform) failed analysis.');
passing = false;
}
}
Expand Down
4 changes: 4 additions & 0 deletions script/tool/test/common/xcode_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ void main() {
'ios',
workspace: 'A.xcworkspace',
scheme: 'AScheme',
hostPlatform: MockPlatform(),
);

expect(exitCode, 0);
Expand Down Expand Up @@ -193,6 +194,7 @@ void main() {
workspace: 'A.xcworkspace',
scheme: 'AScheme',
configuration: 'Debug',
hostPlatform: MockPlatform(),
extraFlags: <String>['-a', '-b', 'c=d']);

expect(exitCode, 0);
Expand Down Expand Up @@ -230,6 +232,7 @@ void main() {
'ios',
workspace: 'A.xcworkspace',
scheme: 'AScheme',
hostPlatform: MockPlatform(),
);

expect(exitCode, 1);
Expand Down Expand Up @@ -264,6 +267,7 @@ void main() {
'macos',
workspace: 'A.xcworkspace',
scheme: 'AScheme',
hostPlatform: MockPlatform(),
actions: <String>['test'],
);

Expand Down
Loading