forked from firka/flutter
Rename some classes in the engine_build_configs package (flutter/engine#51016)
- BuildConfig -> BuilderConfig - GlobalBuild -> Build
This commit is contained in:
@@ -28,7 +28,9 @@ void main(List<String> args) async {
|
||||
|
||||
// Find and parse the engine build configs.
|
||||
final io.Directory buildConfigsDir = io.Directory(p.join(
|
||||
engine.flutterDir.path, 'ci', 'builders',
|
||||
engine.flutterDir.path,
|
||||
'ci',
|
||||
'builders',
|
||||
));
|
||||
final BuildConfigLoader loader = BuildConfigLoader(
|
||||
buildConfigsDir: buildConfigsDir,
|
||||
@@ -36,7 +38,7 @@ void main(List<String> args) async {
|
||||
|
||||
// Treat it as an error if no build configs were found. The caller likely
|
||||
// expected to find some.
|
||||
final Map<String, BuildConfig> configs = loader.configs;
|
||||
final Map<String, BuilderConfig> configs = loader.configs;
|
||||
if (configs.isEmpty) {
|
||||
io.stderr.writeln(
|
||||
'Error: No build configs found under ${buildConfigsDir.path}',
|
||||
|
||||
@@ -6,47 +6,45 @@ import 'package:engine_build_configs/engine_build_configs.dart';
|
||||
|
||||
import 'environment.dart';
|
||||
|
||||
/// A function that returns true or false when given a [BuildConfig] and its
|
||||
/// A function that returns true or false when given a [BuilderConfig] and its
|
||||
/// name.
|
||||
typedef ConfigFilter = bool Function(String name, BuildConfig config);
|
||||
typedef ConfigFilter = bool Function(String name, BuilderConfig config);
|
||||
|
||||
/// A function that returns true or false when given a [BuildConfig] name
|
||||
/// and a [GlobalBuild].
|
||||
typedef BuildFilter = bool Function(String configName, GlobalBuild build);
|
||||
/// A function that returns true or false when given a [BuilderConfig] name
|
||||
/// and a [Build].
|
||||
typedef BuildFilter = bool Function(String configName, Build build);
|
||||
|
||||
/// Returns a filtered copy of [input] filtering out configs where test
|
||||
/// returns false.
|
||||
Map<String, BuildConfig> filterBuildConfigs(
|
||||
Map<String, BuildConfig> input, ConfigFilter test) {
|
||||
return <String, BuildConfig>{
|
||||
for (final MapEntry<String, BuildConfig> entry in input.entries)
|
||||
Map<String, BuilderConfig> filterBuilderConfigs(
|
||||
Map<String, BuilderConfig> input, ConfigFilter test) {
|
||||
return <String, BuilderConfig>{
|
||||
for (final MapEntry<String, BuilderConfig> entry in input.entries)
|
||||
if (test(entry.key, entry.value)) entry.key: entry.value,
|
||||
};
|
||||
}
|
||||
|
||||
/// Returns a copy of [input] filtering out configs that are not runnable
|
||||
/// on the current platform.
|
||||
Map<String, BuildConfig> runnableBuildConfigs(
|
||||
Environment env, Map<String, BuildConfig> input) {
|
||||
return filterBuildConfigs(input, (String name, BuildConfig config) {
|
||||
Map<String, BuilderConfig> runnableBuilderConfigs(
|
||||
Environment env, Map<String, BuilderConfig> input) {
|
||||
return filterBuilderConfigs(input, (String name, BuilderConfig config) {
|
||||
return config.canRunOn(env.platform);
|
||||
});
|
||||
}
|
||||
|
||||
/// Returns a List of [GlobalBuild] that match test.
|
||||
List<GlobalBuild> filterBuilds(
|
||||
Map<String, BuildConfig> input, BuildFilter test) {
|
||||
return <GlobalBuild>[
|
||||
for (final MapEntry<String, BuildConfig> entry in input.entries)
|
||||
for (final GlobalBuild build in entry.value.builds)
|
||||
/// Returns a List of [Build] that match test.
|
||||
List<Build> filterBuilds(Map<String, BuilderConfig> input, BuildFilter test) {
|
||||
return <Build>[
|
||||
for (final MapEntry<String, BuilderConfig> entry in input.entries)
|
||||
for (final Build build in entry.value.builds)
|
||||
if (test(entry.key, build)) build,
|
||||
];
|
||||
}
|
||||
|
||||
/// Returns a list of runnable builds.
|
||||
List<GlobalBuild> runnableBuilds(
|
||||
Environment env, Map<String, BuildConfig> input) {
|
||||
return filterBuilds(input, (String configName, GlobalBuild build) {
|
||||
List<Build> runnableBuilds(Environment env, Map<String, BuilderConfig> input) {
|
||||
return filterBuilds(input, (String configName, Build build) {
|
||||
return build.canRunOn(env.platform);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -9,17 +9,12 @@ import '../logger.dart';
|
||||
import 'command.dart';
|
||||
import 'flags.dart';
|
||||
|
||||
// TODO(johnmccutchan): Should BuildConfig be BuilderConfig and GlobalBuild be BuildConfig?
|
||||
// TODO(johnmccutchan): List all available build targets and allow the user
|
||||
// to specify which one(s) we should build on the cli.
|
||||
// TODO(johnmccutchan): Can we show a progress indicator like 'running gn...'?
|
||||
|
||||
/// The root 'build' command.
|
||||
final class BuildCommand extends CommandBase {
|
||||
/// Constructs the 'build' command.
|
||||
BuildCommand({
|
||||
required super.environment,
|
||||
required Map<String, BuildConfig> configs,
|
||||
required Map<String, BuilderConfig> configs,
|
||||
}) {
|
||||
builds = runnableBuilds(environment, configs);
|
||||
// Add options here that are common to all queries.
|
||||
@@ -29,18 +24,18 @@ final class BuildCommand extends CommandBase {
|
||||
defaultsTo: 'host_debug',
|
||||
help: 'Specify the build config to use',
|
||||
allowed: <String>[
|
||||
for (final GlobalBuild config in runnableBuilds(environment, configs))
|
||||
for (final Build config in runnableBuilds(environment, configs))
|
||||
config.name,
|
||||
],
|
||||
allowedHelp: <String, String>{
|
||||
for (final GlobalBuild config in runnableBuilds(environment, configs))
|
||||
for (final Build config in runnableBuilds(environment, configs))
|
||||
config.name: config.gn.join(' '),
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/// List of compatible builds.
|
||||
late final List<GlobalBuild> builds;
|
||||
late final List<Build> builds;
|
||||
|
||||
@override
|
||||
String get name => 'build';
|
||||
@@ -51,14 +46,13 @@ final class BuildCommand extends CommandBase {
|
||||
@override
|
||||
Future<int> run() async {
|
||||
final String configName = argResults![configFlag] as String;
|
||||
final GlobalBuild? build = builds
|
||||
.where((GlobalBuild build) => build.name == configName)
|
||||
.firstOrNull;
|
||||
final Build? build =
|
||||
builds.where((Build build) => build.name == configName).firstOrNull;
|
||||
if (build == null) {
|
||||
environment.logger.error('Could not find config $configName');
|
||||
return 1;
|
||||
}
|
||||
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
|
||||
final BuildRunner buildRunner = BuildRunner(
|
||||
platform: environment.platform,
|
||||
processRunner: environment.processRunner,
|
||||
abi: environment.abi,
|
||||
@@ -78,16 +72,18 @@ final class BuildCommand extends CommandBase {
|
||||
spinner = null;
|
||||
environment.logger.clearLine();
|
||||
environment.logger.status(event);
|
||||
case RunnerProgress(done: false): {
|
||||
spinner?.finish();
|
||||
spinner = null;
|
||||
final String percent = '${event.percent.toStringAsFixed(1)}%';
|
||||
final String fraction = '(${event.completed}/${event.total})';
|
||||
final String prefix = '[${event.name}] $percent $fraction ';
|
||||
final String what = event.what;
|
||||
environment.logger.clearLine();
|
||||
environment.logger.status('$prefix$what', newline: false, fit: true);
|
||||
}
|
||||
case RunnerProgress(done: false):
|
||||
{
|
||||
spinner?.finish();
|
||||
spinner = null;
|
||||
final String percent = '${event.percent.toStringAsFixed(1)}%';
|
||||
final String fraction = '(${event.completed}/${event.total})';
|
||||
final String prefix = '[${event.name}] $percent $fraction ';
|
||||
final String what = event.what;
|
||||
environment.logger.clearLine();
|
||||
environment.logger
|
||||
.status('$prefix$what', newline: false, fit: true);
|
||||
}
|
||||
default:
|
||||
spinner?.finish();
|
||||
spinner = null;
|
||||
|
||||
@@ -41,7 +41,7 @@ final class ToolCommandRunner extends CommandRunner<int> {
|
||||
final Environment environment;
|
||||
|
||||
/// Build configurations loaded from the engine from under ci/builders.
|
||||
final Map<String, BuildConfig> configs;
|
||||
final Map<String, BuilderConfig> configs;
|
||||
|
||||
@override
|
||||
Future<int> run(Iterable<String> args) async {
|
||||
|
||||
@@ -27,12 +27,12 @@ final class QueryCommand extends CommandBase {
|
||||
abbr: 'b',
|
||||
help: 'Restrict the query to a single builder.',
|
||||
allowed: <String>[
|
||||
for (final MapEntry<String, BuildConfig> entry in configs.entries)
|
||||
for (final MapEntry<String, BuilderConfig> entry in configs.entries)
|
||||
if (entry.value.canRunOn(environment.platform)) entry.key,
|
||||
],
|
||||
allowedHelp: <String, String>{
|
||||
// TODO(zanderso): Add human readable descriptions to the json files.
|
||||
for (final MapEntry<String, BuildConfig> entry in configs.entries)
|
||||
for (final MapEntry<String, BuilderConfig> entry in configs.entries)
|
||||
if (entry.value.canRunOn(environment.platform))
|
||||
entry.key: entry.value.path,
|
||||
},
|
||||
@@ -51,7 +51,7 @@ final class QueryCommand extends CommandBase {
|
||||
}
|
||||
|
||||
/// Build configurations loaded from the engine from under ci/builders.
|
||||
final Map<String, BuildConfig> configs;
|
||||
final Map<String, BuilderConfig> configs;
|
||||
|
||||
@override
|
||||
String get name => 'query';
|
||||
@@ -70,7 +70,7 @@ final class QueryBuildersCommand extends CommandBase {
|
||||
});
|
||||
|
||||
/// Build configurations loaded from the engine from under ci/builders.
|
||||
final Map<String, BuildConfig> configs;
|
||||
final Map<String, BuilderConfig> configs;
|
||||
|
||||
@override
|
||||
String get name => 'builders';
|
||||
@@ -97,13 +97,13 @@ final class QueryBuildersCommand extends CommandBase {
|
||||
continue;
|
||||
}
|
||||
|
||||
final BuildConfig config = configs[key]!;
|
||||
final BuilderConfig config = configs[key]!;
|
||||
if (!config.canRunOn(environment.platform) && !all) {
|
||||
continue;
|
||||
}
|
||||
|
||||
environment.logger.status('"$key" builder:');
|
||||
for (final GlobalBuild build in config.builds) {
|
||||
for (final Build build in config.builds) {
|
||||
if (!build.canRunOn(environment.platform) && !all) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -29,25 +29,25 @@ void main() {
|
||||
return;
|
||||
}
|
||||
|
||||
final BuildConfig linuxTestConfig = BuildConfig.fromJson(
|
||||
final BuilderConfig linuxTestConfig = BuilderConfig.fromJson(
|
||||
path: 'ci/builders/linux_test_config.json',
|
||||
map: convert.jsonDecode(fixtures.testConfig('Linux'))
|
||||
as Map<String, Object?>,
|
||||
);
|
||||
|
||||
final BuildConfig macTestConfig = BuildConfig.fromJson(
|
||||
final BuilderConfig macTestConfig = BuilderConfig.fromJson(
|
||||
path: 'ci/builders/mac_test_config.json',
|
||||
map: convert.jsonDecode(fixtures.testConfig('Mac-12'))
|
||||
as Map<String, Object?>,
|
||||
);
|
||||
|
||||
final BuildConfig winTestConfig = BuildConfig.fromJson(
|
||||
final BuilderConfig winTestConfig = BuilderConfig.fromJson(
|
||||
path: 'ci/builders/win_test_config.json',
|
||||
map: convert.jsonDecode(fixtures.testConfig('Windows-11'))
|
||||
as Map<String, Object?>,
|
||||
);
|
||||
|
||||
final Map<String, BuildConfig> configs = <String, BuildConfig>{
|
||||
final Map<String, BuilderConfig> configs = <String, BuilderConfig>{
|
||||
'linux_test_config': linuxTestConfig,
|
||||
'linux_test_config2': linuxTestConfig,
|
||||
'mac_test_config': macTestConfig,
|
||||
@@ -79,7 +79,7 @@ void main() {
|
||||
test('can find host runnable build', () async {
|
||||
final Logger logger = Logger.test();
|
||||
final (Environment env, _) = linuxEnv(logger);
|
||||
final List<GlobalBuild> result = runnableBuilds(env, configs);
|
||||
final List<Build> result = runnableBuilds(env, configs);
|
||||
expect(result.length, equals(2));
|
||||
expect(result[0].name, equals('build_name'));
|
||||
});
|
||||
|
||||
@@ -54,7 +54,7 @@ void main() {
|
||||
final Environment env = linuxEnv(logger, manager);
|
||||
final ToolCommandRunner runner = ToolCommandRunner(
|
||||
environment: env,
|
||||
configs: <String, BuildConfig>{},
|
||||
configs: <String, BuilderConfig>{},
|
||||
);
|
||||
final int result = await runner.run(<String>[
|
||||
'format',
|
||||
@@ -70,15 +70,17 @@ void main() {
|
||||
final Environment env = linuxEnv(logger, manager);
|
||||
final ToolCommandRunner runner = ToolCommandRunner(
|
||||
environment: env,
|
||||
configs: <String, BuildConfig>{},
|
||||
configs: <String, BuilderConfig>{},
|
||||
);
|
||||
final int result = await runner.run(<String>[
|
||||
'format', '--$dryRunFlag',
|
||||
'format',
|
||||
'--$dryRunFlag',
|
||||
]);
|
||||
expect(result, equals(0));
|
||||
});
|
||||
|
||||
test('exit code is non-zero when ci/bin/format.dart exit code was non zero', () async {
|
||||
test('exit code is non-zero when ci/bin/format.dart exit code was non zero',
|
||||
() async {
|
||||
final Logger logger = Logger.test();
|
||||
final FakeProcessManager manager = _formatProcessManager(
|
||||
expectedFlags: <String>['--fix'],
|
||||
@@ -87,7 +89,7 @@ void main() {
|
||||
final Environment env = linuxEnv(logger, manager);
|
||||
final ToolCommandRunner runner = ToolCommandRunner(
|
||||
environment: env,
|
||||
configs: <String, BuildConfig>{},
|
||||
configs: <String, BuilderConfig>{},
|
||||
);
|
||||
final int result = await runner.run(<String>[
|
||||
'format',
|
||||
@@ -103,10 +105,11 @@ void main() {
|
||||
final Environment env = linuxEnv(logger, manager);
|
||||
final ToolCommandRunner runner = ToolCommandRunner(
|
||||
environment: env,
|
||||
configs: <String, BuildConfig>{},
|
||||
configs: <String, BuilderConfig>{},
|
||||
);
|
||||
final int result = await runner.run(<String>[
|
||||
'format', '--$allFlag',
|
||||
'format',
|
||||
'--$allFlag',
|
||||
]);
|
||||
expect(result, equals(0));
|
||||
});
|
||||
@@ -119,10 +122,11 @@ void main() {
|
||||
final Environment env = linuxEnv(logger, manager);
|
||||
final ToolCommandRunner runner = ToolCommandRunner(
|
||||
environment: env,
|
||||
configs: <String, BuildConfig>{},
|
||||
configs: <String, BuilderConfig>{},
|
||||
);
|
||||
final int result = await runner.run(<String>[
|
||||
'format', '--$verboseFlag',
|
||||
'format',
|
||||
'--$verboseFlag',
|
||||
]);
|
||||
expect(result, equals(0));
|
||||
});
|
||||
@@ -137,10 +141,11 @@ void main() {
|
||||
final Environment env = linuxEnv(logger, manager);
|
||||
final ToolCommandRunner runner = ToolCommandRunner(
|
||||
environment: env,
|
||||
configs: <String, BuildConfig>{},
|
||||
configs: <String, BuilderConfig>{},
|
||||
);
|
||||
final int result = await runner.run(<String>[
|
||||
'format', '--$quietFlag',
|
||||
'format',
|
||||
'--$quietFlag',
|
||||
]);
|
||||
expect(result, equals(0));
|
||||
expect(stringsFromLogs(logger.testLogs), equals(<String>['error\n']));
|
||||
@@ -152,14 +157,17 @@ void main() {
|
||||
expectedFlags: <String>['--fix'],
|
||||
stdout: <String>[
|
||||
'To fix, run `et format` or:',
|
||||
'many', 'lines', 'of', 'output',
|
||||
'many',
|
||||
'lines',
|
||||
'of',
|
||||
'output',
|
||||
'DONE',
|
||||
].join('\n'),
|
||||
);
|
||||
final Environment env = linuxEnv(logger, manager);
|
||||
final ToolCommandRunner runner = ToolCommandRunner(
|
||||
environment: env,
|
||||
configs: <String, BuildConfig>{},
|
||||
configs: <String, BuilderConfig>{},
|
||||
);
|
||||
final int result = await runner.run(<String>[
|
||||
'format',
|
||||
@@ -174,32 +182,39 @@ void main() {
|
||||
expectedFlags: <String>[],
|
||||
stdout: <String>[
|
||||
'To fix, run `et format` or:',
|
||||
'many', 'lines', 'of', 'output',
|
||||
'many',
|
||||
'lines',
|
||||
'of',
|
||||
'output',
|
||||
'DONE',
|
||||
].join('\n'),
|
||||
);
|
||||
final Environment env = linuxEnv(logger, manager);
|
||||
final ToolCommandRunner runner = ToolCommandRunner(
|
||||
environment: env,
|
||||
configs: <String, BuildConfig>{},
|
||||
configs: <String, BuilderConfig>{},
|
||||
);
|
||||
final int result = await runner.run(<String>[
|
||||
'format', '--$dryRunFlag',
|
||||
'format',
|
||||
'--$dryRunFlag',
|
||||
]);
|
||||
expect(result, equals(0));
|
||||
expect(
|
||||
stringsFromLogs(logger.testLogs),
|
||||
equals(<String>[
|
||||
'To fix, run `et format` or:\n',
|
||||
'many\n', 'lines\n', 'of\n', 'output\n',
|
||||
'DONE\n',
|
||||
]));
|
||||
stringsFromLogs(logger.testLogs),
|
||||
equals(<String>[
|
||||
'To fix, run `et format` or:\n',
|
||||
'many\n',
|
||||
'lines\n',
|
||||
'of\n',
|
||||
'output\n',
|
||||
'DONE\n',
|
||||
]));
|
||||
});
|
||||
|
||||
test('progress lines are followed by a carriage return', () async {
|
||||
final Logger logger = Logger.test();
|
||||
const String progressLine = 'diff Jobs: 46% done, 1528/3301 completed, '
|
||||
'7 in progress, 1753 pending, 13 failed.';
|
||||
'7 in progress, 1753 pending, 13 failed.';
|
||||
final FakeProcessManager manager = _formatProcessManager(
|
||||
expectedFlags: <String>['--fix'],
|
||||
stdout: progressLine,
|
||||
@@ -207,15 +222,14 @@ void main() {
|
||||
final Environment env = linuxEnv(logger, manager);
|
||||
final ToolCommandRunner runner = ToolCommandRunner(
|
||||
environment: env,
|
||||
configs: <String, BuildConfig>{},
|
||||
configs: <String, BuilderConfig>{},
|
||||
);
|
||||
final int result = await runner.run(<String>[
|
||||
'format',
|
||||
]);
|
||||
expect(result, equals(0));
|
||||
expect(
|
||||
stringsFromLogs(logger.testLogs),
|
||||
equals(<String>['$progressLine\r']));
|
||||
stringsFromLogs(logger.testLogs), equals(<String>['$progressLine\r']));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -239,11 +253,12 @@ FakeProcessManager _formatProcessManager({
|
||||
_ => failUnknown ? io.ProcessResult(1, 1, '', '') : success,
|
||||
},
|
||||
onStart: (List<String> cmd) => switch (cmd) {
|
||||
[final String exe, final String fmt, ... final List<String> rest]
|
||||
when exe.endsWith('dart') &&
|
||||
fmt.endsWith('ci/bin/format.dart') &&
|
||||
rest.length == expectedFlags.length &&
|
||||
expectedFlags.every(rest.contains) => formatProcess,
|
||||
[final String exe, final String fmt, ...final List<String> rest]
|
||||
when exe.endsWith('dart') &&
|
||||
fmt.endsWith('ci/bin/format.dart') &&
|
||||
rest.length == expectedFlags.length &&
|
||||
expectedFlags.every(rest.contains) =>
|
||||
formatProcess,
|
||||
_ => failUnknown ? FakeProcess(exitCode: 1) : FakeProcess(),
|
||||
},
|
||||
);
|
||||
|
||||
@@ -29,25 +29,25 @@ void main() {
|
||||
return;
|
||||
}
|
||||
|
||||
final BuildConfig linuxTestConfig = BuildConfig.fromJson(
|
||||
final BuilderConfig linuxTestConfig = BuilderConfig.fromJson(
|
||||
path: 'ci/builders/linux_test_config.json',
|
||||
map: convert.jsonDecode(fixtures.testConfig('Linux'))
|
||||
as Map<String, Object?>,
|
||||
);
|
||||
|
||||
final BuildConfig macTestConfig = BuildConfig.fromJson(
|
||||
final BuilderConfig macTestConfig = BuilderConfig.fromJson(
|
||||
path: 'ci/builders/mac_test_config.json',
|
||||
map: convert.jsonDecode(fixtures.testConfig('Mac-12'))
|
||||
as Map<String, Object?>,
|
||||
);
|
||||
|
||||
final BuildConfig winTestConfig = BuildConfig.fromJson(
|
||||
final BuilderConfig winTestConfig = BuilderConfig.fromJson(
|
||||
path: 'ci/builders/win_test_config.json',
|
||||
map: convert.jsonDecode(fixtures.testConfig('Windows-11'))
|
||||
as Map<String, Object?>,
|
||||
);
|
||||
|
||||
final Map<String, BuildConfig> configs = <String, BuildConfig>{
|
||||
final Map<String, BuilderConfig> configs = <String, BuilderConfig>{
|
||||
'linux_test_config': linuxTestConfig,
|
||||
'linux_test_config2': linuxTestConfig,
|
||||
'mac_test_config': macTestConfig,
|
||||
|
||||
@@ -32,7 +32,9 @@ void main(List<String> args) {
|
||||
|
||||
// Find and parse the engine build configs.
|
||||
final io.Directory buildConfigsDir = io.Directory(p.join(
|
||||
engine.flutterDir.path, 'ci', 'builders',
|
||||
engine.flutterDir.path,
|
||||
'ci',
|
||||
'builders',
|
||||
));
|
||||
final BuildConfigLoader loader = BuildConfigLoader(
|
||||
buildConfigsDir: buildConfigsDir,
|
||||
@@ -40,7 +42,7 @@ void main(List<String> args) {
|
||||
|
||||
// Treat it as an error if no build configs were found. The caller likely
|
||||
// expected to find some.
|
||||
final Map<String, BuildConfig> configs = loader.configs;
|
||||
final Map<String, BuilderConfig> configs = loader.configs;
|
||||
if (configs.isEmpty) {
|
||||
io.stderr.writeln(
|
||||
'Error: No build configs found under ${buildConfigsDir.path}',
|
||||
@@ -55,7 +57,7 @@ void main(List<String> args) {
|
||||
|
||||
// Check the parsed build configs for validity.
|
||||
for (final String name in configs.keys) {
|
||||
final BuildConfig buildConfig = configs[name]!;
|
||||
final BuilderConfig buildConfig = configs[name]!;
|
||||
final List<String> buildConfigErrors = buildConfig.check(name);
|
||||
if (buildConfigErrors.isNotEmpty) {
|
||||
io.stderr.writeln('Errors in ${buildConfig.path}:');
|
||||
@@ -68,24 +70,26 @@ void main(List<String> args) {
|
||||
|
||||
// Check that global builds for the same platform are uniquely named.
|
||||
final List<String> hostPlatforms = <String>[
|
||||
Platform.linux, Platform.macOS, Platform.windows,
|
||||
Platform.linux,
|
||||
Platform.macOS,
|
||||
Platform.windows,
|
||||
];
|
||||
|
||||
// For each host platform, a mapping from GlobalBuild.name to GlobalBuild.
|
||||
final Map<String, Map<String, (BuildConfig, GlobalBuild)>> builds =
|
||||
<String, Map<String, (BuildConfig, GlobalBuild)>>{};
|
||||
final Map<String, Map<String, (BuilderConfig, Build)>> builds =
|
||||
<String, Map<String, (BuilderConfig, Build)>>{};
|
||||
for (final String platform in hostPlatforms) {
|
||||
builds[platform] = <String, (BuildConfig, GlobalBuild)>{};
|
||||
builds[platform] = <String, (BuilderConfig, Build)>{};
|
||||
}
|
||||
for (final String name in configs.keys) {
|
||||
final BuildConfig buildConfig = configs[name]!;
|
||||
for (final GlobalBuild build in buildConfig.builds) {
|
||||
final BuilderConfig buildConfig = configs[name]!;
|
||||
for (final Build build in buildConfig.builds) {
|
||||
for (final String platform in hostPlatforms) {
|
||||
if (!build.canRunOn(FakePlatform(operatingSystem: platform))) {
|
||||
continue;
|
||||
}
|
||||
if (builds[platform]!.containsKey(build.name)) {
|
||||
final (BuildConfig oldConfig, _) = builds[platform]![build.name]!;
|
||||
final (BuilderConfig oldConfig, _) = builds[platform]![build.name]!;
|
||||
io.stderr.writeln(
|
||||
'${build.name} is duplicated.\n'
|
||||
'\tFound definition in ${buildConfig.path}.\n'
|
||||
|
||||
@@ -56,7 +56,9 @@ The build names are the "name" fields of the maps in the list of "builds".
|
||||
|
||||
// Find and parse the engine build configs.
|
||||
final io.Directory buildConfigsDir = io.Directory(p.join(
|
||||
engine.flutterDir.path, 'ci', 'builders',
|
||||
engine.flutterDir.path,
|
||||
'ci',
|
||||
'builders',
|
||||
));
|
||||
final BuildConfigLoader loader = BuildConfigLoader(
|
||||
buildConfigsDir: buildConfigsDir,
|
||||
@@ -64,7 +66,7 @@ The build names are the "name" fields of the maps in the list of "builds".
|
||||
|
||||
// Treat it as an error if no build configs were found. The caller likely
|
||||
// expected to find some.
|
||||
final Map<String, BuildConfig> configs = loader.configs;
|
||||
final Map<String, BuilderConfig> configs = loader.configs;
|
||||
if (configs.isEmpty) {
|
||||
io.stderr.writeln(
|
||||
'Error: No build configs found under ${buildConfigsDir.path}',
|
||||
@@ -78,7 +80,7 @@ The build names are the "name" fields of the maps in the list of "builds".
|
||||
}
|
||||
|
||||
// Check the parsed build configs for validity.
|
||||
final BuildConfig? targetConfig = configs[configName];
|
||||
final BuilderConfig? targetConfig = configs[configName];
|
||||
if (targetConfig == null) {
|
||||
io.stderr.writeln('Build config "$configName" not found.');
|
||||
io.exitCode = 1;
|
||||
@@ -94,9 +96,9 @@ The build names are the "name" fields of the maps in the list of "builds".
|
||||
return;
|
||||
}
|
||||
|
||||
GlobalBuild? targetBuild;
|
||||
Build? targetBuild;
|
||||
for (int i = 0; i < targetConfig.builds.length; i++) {
|
||||
final GlobalBuild build = targetConfig.builds[i];
|
||||
final Build build = targetConfig.builds[i];
|
||||
if (build.name == buildName) {
|
||||
targetBuild = build;
|
||||
}
|
||||
@@ -111,13 +113,16 @@ The build names are the "name" fields of the maps in the list of "builds".
|
||||
|
||||
// If RBE config files aren't in the tree, then disable RBE.
|
||||
final String rbeConfigPath = p.join(
|
||||
engine.srcDir.path, 'flutter', 'build', 'rbe',
|
||||
engine.srcDir.path,
|
||||
'flutter',
|
||||
'build',
|
||||
'rbe',
|
||||
);
|
||||
final List<String> extraGnArgs = <String>[
|
||||
if (!io.Directory(rbeConfigPath).existsSync()) '--no-rbe',
|
||||
];
|
||||
|
||||
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
|
||||
final BuildRunner buildRunner = BuildRunner(
|
||||
platform: const LocalPlatform(),
|
||||
processRunner: ProcessRunner(),
|
||||
abi: ffi.Abi.current(),
|
||||
@@ -133,26 +138,28 @@ The build names are the "name" fields of the maps in the list of "builds".
|
||||
io.stdout.writeln('$event: ${event.command.join(' ')}');
|
||||
case RunnerProgress(done: true):
|
||||
io.stdout.writeln(event);
|
||||
case RunnerProgress(done: false): {
|
||||
final int width = io.stdout.terminalColumns;
|
||||
final String percent = '${event.percent.toStringAsFixed(1)}%';
|
||||
final String fraction = '(${event.completed}/${event.total})';
|
||||
final String prefix = '[${event.name}] $percent $fraction ';
|
||||
final int remainingSpace = width - prefix.length;
|
||||
final String what;
|
||||
if (remainingSpace >= event.what.length) {
|
||||
what = event.what;
|
||||
} else {
|
||||
what = event.what.substring(event.what.length - remainingSpace + 1);
|
||||
case RunnerProgress(done: false):
|
||||
{
|
||||
final int width = io.stdout.terminalColumns;
|
||||
final String percent = '${event.percent.toStringAsFixed(1)}%';
|
||||
final String fraction = '(${event.completed}/${event.total})';
|
||||
final String prefix = '[${event.name}] $percent $fraction ';
|
||||
final int remainingSpace = width - prefix.length;
|
||||
final String what;
|
||||
if (remainingSpace >= event.what.length) {
|
||||
what = event.what;
|
||||
} else {
|
||||
what = event.what.substring(event.what.length - remainingSpace + 1);
|
||||
}
|
||||
final String spaces = ' ' * width;
|
||||
io.stdout.write('$spaces\r'); // Erase the old line.
|
||||
io.stdout.write('$prefix$what\r'); // Print the new line.
|
||||
}
|
||||
final String spaces = ' ' * width;
|
||||
io.stdout.write('$spaces\r'); // Erase the old line.
|
||||
io.stdout.write('$prefix$what\r'); // Print the new line.
|
||||
}
|
||||
default:
|
||||
io.stdout.writeln(event);
|
||||
}
|
||||
}
|
||||
|
||||
final bool buildResult = await buildRunner.run(handler);
|
||||
io.exitCode = buildResult ? 0 : 1;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:platform/platform.dart';
|
||||
|
||||
// This library parses Engine build config data out of the "Engine v2" build
|
||||
// This library parses Engine builder config data out of the "Engine v2" build
|
||||
// config JSON files with the format described at:
|
||||
// https://github.com/flutter/engine/blob/main/ci/builders/README.md
|
||||
|
||||
@@ -31,10 +31,10 @@ sealed class BuildConfigBase {
|
||||
}
|
||||
}
|
||||
|
||||
/// The build configuration is a json file containing a list of builds, tests,
|
||||
/// The builder configuration is a json file containing a list of builds, tests,
|
||||
/// generators and archives.
|
||||
///
|
||||
/// Each build config file contains a top-level json map with the following
|
||||
/// Each builder config file contains a top-level json map with the following
|
||||
/// fields:
|
||||
/// {
|
||||
/// "builds": [],
|
||||
@@ -44,25 +44,31 @@ sealed class BuildConfigBase {
|
||||
/// },
|
||||
/// "archives": []
|
||||
/// }
|
||||
final class BuildConfig extends BuildConfigBase {
|
||||
final class BuilderConfig extends BuildConfigBase {
|
||||
/// Load build configuration data into an instance of this class.
|
||||
///
|
||||
/// [path] should be the file system path to the file that the JSON data comes
|
||||
/// from. [map] must be the JSON data returned by e.g. `JsonDecoder.convert`.
|
||||
factory BuildConfig.fromJson({
|
||||
factory BuilderConfig.fromJson({
|
||||
required String path,
|
||||
required Map<String, Object?> map,
|
||||
}) {
|
||||
final List<String> errors = <String>[];
|
||||
|
||||
// Parse the "builds" field.
|
||||
final List<GlobalBuild>? builds = objListOfJson<GlobalBuild>(
|
||||
map, 'builds', errors, GlobalBuild.fromJson,
|
||||
final List<Build>? builds = objListOfJson<Build>(
|
||||
map,
|
||||
'builds',
|
||||
errors,
|
||||
Build.fromJson,
|
||||
);
|
||||
|
||||
// Parse the "tests" field.
|
||||
final List<GlobalTest>? tests = objListOfJson<GlobalTest>(
|
||||
map, 'tests', errors, GlobalTest.fromJson,
|
||||
map,
|
||||
'tests',
|
||||
errors,
|
||||
GlobalTest.fromJson,
|
||||
);
|
||||
|
||||
// Parse the "generators" field.
|
||||
@@ -83,19 +89,22 @@ final class BuildConfig extends BuildConfigBase {
|
||||
|
||||
// Parse the "archives" field.
|
||||
final List<GlobalArchive>? archives = objListOfJson<GlobalArchive>(
|
||||
map, 'archives', errors, GlobalArchive.fromJson,
|
||||
map,
|
||||
'archives',
|
||||
errors,
|
||||
GlobalArchive.fromJson,
|
||||
);
|
||||
|
||||
if (builds == null ||
|
||||
tests == null ||
|
||||
generators == null ||
|
||||
archives == null) {
|
||||
return BuildConfig._invalid(path, errors);
|
||||
return BuilderConfig._invalid(path, errors);
|
||||
}
|
||||
return BuildConfig._(path, builds, tests, generators, archives);
|
||||
return BuilderConfig._(path, builds, tests, generators, archives);
|
||||
}
|
||||
|
||||
BuildConfig._(
|
||||
BuilderConfig._(
|
||||
this.path,
|
||||
this.builds,
|
||||
this.tests,
|
||||
@@ -103,18 +112,18 @@ final class BuildConfig extends BuildConfigBase {
|
||||
this.archives,
|
||||
) : super(null);
|
||||
|
||||
BuildConfig._invalid(this.path, super.errors) :
|
||||
builds = <GlobalBuild>[],
|
||||
tests = <GlobalTest>[],
|
||||
generators = <TestTask>[],
|
||||
archives = <GlobalArchive>[];
|
||||
BuilderConfig._invalid(this.path, super.errors)
|
||||
: builds = <Build>[],
|
||||
tests = <GlobalTest>[],
|
||||
generators = <TestTask>[],
|
||||
archives = <GlobalArchive>[];
|
||||
|
||||
/// The path to the JSON file.
|
||||
final String path;
|
||||
|
||||
/// A list of independent builds that have no dependencies among them. They
|
||||
/// can run in parallel if need be.
|
||||
final List<GlobalBuild> builds;
|
||||
final List<Build> builds;
|
||||
|
||||
/// A list of tests. The tests may have dependencies on one or more of the
|
||||
/// builds.
|
||||
@@ -133,7 +142,7 @@ final class BuildConfig extends BuildConfigBase {
|
||||
final List<String> errors = <String>[];
|
||||
errors.addAll(super.check(path));
|
||||
for (int i = 0; i < builds.length; i++) {
|
||||
final GlobalBuild build = builds[i];
|
||||
final Build build = builds[i];
|
||||
errors.addAll(build.check('$path/builds[$i]'));
|
||||
}
|
||||
for (int i = 0; i < tests.length; i++) {
|
||||
@@ -151,10 +160,10 @@ final class BuildConfig extends BuildConfigBase {
|
||||
return errors;
|
||||
}
|
||||
|
||||
/// Returns true if any of the [GlobalBuild]s it contains can run on
|
||||
/// Returns true if any of the [Build]s it contains can run on
|
||||
/// `platform`, and false otherwise.
|
||||
bool canRunOn(Platform platform) {
|
||||
return builds.any((GlobalBuild b) => b.canRunOn(platform));
|
||||
return builds.any((Build b) => b.canRunOn(platform));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,19 +184,27 @@ final class BuildConfig extends BuildConfigBase {
|
||||
/// "drone_dimensions": [""],
|
||||
/// "gclient_variables": {}
|
||||
/// }
|
||||
final class GlobalBuild extends BuildConfigBase {
|
||||
factory GlobalBuild.fromJson(Map<String, Object?> map) {
|
||||
final class Build extends BuildConfigBase {
|
||||
factory Build.fromJson(Map<String, Object?> map) {
|
||||
final List<String> errors = <String>[];
|
||||
final String? name = stringOfJson(map, 'name', errors);
|
||||
final List<String>? gn = stringListOfJson(map, 'gn', errors);
|
||||
final List<BuildTest>? tests = objListOfJson(
|
||||
map, 'tests', errors, BuildTest.fromJson,
|
||||
map,
|
||||
'tests',
|
||||
errors,
|
||||
BuildTest.fromJson,
|
||||
);
|
||||
final List<BuildArchive>? archives = objListOfJson(
|
||||
map, 'archives', errors, BuildArchive.fromJson,
|
||||
map,
|
||||
'archives',
|
||||
errors,
|
||||
BuildArchive.fromJson,
|
||||
);
|
||||
final List<String>? droneDimensions = stringListOfJson(
|
||||
map, 'drone_dimensions', errors,
|
||||
map,
|
||||
'drone_dimensions',
|
||||
errors,
|
||||
);
|
||||
|
||||
final BuildNinja? ninja;
|
||||
@@ -237,15 +254,21 @@ final class GlobalBuild extends BuildConfigBase {
|
||||
generators == null ||
|
||||
droneDimensions == null ||
|
||||
gclientVariables == null) {
|
||||
return GlobalBuild._invalid(errors);
|
||||
return Build._invalid(errors);
|
||||
}
|
||||
return GlobalBuild._(
|
||||
name, gn, ninja, tests, generators, archives, droneDimensions,
|
||||
return Build._(
|
||||
name,
|
||||
gn,
|
||||
ninja,
|
||||
tests,
|
||||
generators,
|
||||
archives,
|
||||
droneDimensions,
|
||||
gclientVariables,
|
||||
);
|
||||
}
|
||||
|
||||
GlobalBuild._(
|
||||
Build._(
|
||||
this.name,
|
||||
this.gn,
|
||||
this.ninja,
|
||||
@@ -256,15 +279,15 @@ final class GlobalBuild extends BuildConfigBase {
|
||||
this.gclientVariables,
|
||||
) : super(null);
|
||||
|
||||
GlobalBuild._invalid(super.errors) :
|
||||
name = '',
|
||||
gn = <String>[],
|
||||
ninja = BuildNinja.nop(),
|
||||
tests = <BuildTest>[],
|
||||
generators = <BuildTask>[],
|
||||
archives = <BuildArchive>[],
|
||||
droneDimensions = <String>[],
|
||||
gclientVariables = <String, Object?>{};
|
||||
Build._invalid(super.errors)
|
||||
: name = '',
|
||||
gn = <String>[],
|
||||
ninja = BuildNinja.nop(),
|
||||
tests = <BuildTest>[],
|
||||
generators = <BuildTask>[],
|
||||
archives = <BuildArchive>[],
|
||||
droneDimensions = <String>[],
|
||||
gclientVariables = <String, Object?>{};
|
||||
|
||||
/// The name of the build which may also be used to reference it as a
|
||||
/// depdendency of a global test.
|
||||
@@ -337,14 +360,14 @@ final class BuildNinja extends BuildConfigBase {
|
||||
|
||||
BuildNinja._(this.config, this.targets) : super(null);
|
||||
|
||||
BuildNinja._invalid(super.errors) :
|
||||
config = '',
|
||||
targets = <String>[];
|
||||
BuildNinja._invalid(super.errors)
|
||||
: config = '',
|
||||
targets = <String>[];
|
||||
|
||||
BuildNinja.nop() :
|
||||
config = '',
|
||||
targets = <String>[],
|
||||
super(null);
|
||||
BuildNinja.nop()
|
||||
: config = '',
|
||||
targets = <String>[],
|
||||
super(null);
|
||||
|
||||
/// The name of the configuration created by gn.
|
||||
///
|
||||
@@ -371,10 +394,14 @@ final class BuildTest extends BuildConfigBase {
|
||||
final String? language = stringOfJson(map, 'language', errors);
|
||||
final String? script = stringOfJson(map, 'script', errors);
|
||||
final List<String>? parameters = stringListOfJson(
|
||||
map, 'parameters', errors,
|
||||
map,
|
||||
'parameters',
|
||||
errors,
|
||||
);
|
||||
final List<String>? contexts = stringListOfJson(
|
||||
map, 'contexts', errors,
|
||||
map,
|
||||
'contexts',
|
||||
errors,
|
||||
);
|
||||
if (name == null ||
|
||||
language == null ||
|
||||
@@ -394,12 +421,12 @@ final class BuildTest extends BuildConfigBase {
|
||||
this.contexts,
|
||||
) : super(null);
|
||||
|
||||
BuildTest._invalid(super.errors) :
|
||||
name = '',
|
||||
language = '',
|
||||
script = '',
|
||||
parameters = <String>[],
|
||||
contexts = <String>[];
|
||||
BuildTest._invalid(super.errors)
|
||||
: name = '',
|
||||
language = '',
|
||||
script = '',
|
||||
parameters = <String>[],
|
||||
contexts = <String>[];
|
||||
|
||||
/// The human readable description of the test.
|
||||
final String name;
|
||||
@@ -444,7 +471,9 @@ final class BuildTask extends BuildConfigBase {
|
||||
final String? language = stringOfJson(map, 'language', errors);
|
||||
final List<String>? scripts = stringListOfJson(map, 'scripts', errors);
|
||||
final List<String>? parameters = stringListOfJson(
|
||||
map, 'parameters', errors,
|
||||
map,
|
||||
'parameters',
|
||||
errors,
|
||||
);
|
||||
if (name == null ||
|
||||
language == null ||
|
||||
@@ -455,14 +484,14 @@ final class BuildTask extends BuildConfigBase {
|
||||
return BuildTask._(name, language, scripts, parameters);
|
||||
}
|
||||
|
||||
BuildTask._invalid(super.errors) :
|
||||
name = '',
|
||||
language = '',
|
||||
scripts = <String>[],
|
||||
parameters = <String>[];
|
||||
BuildTask._invalid(super.errors)
|
||||
: name = '',
|
||||
language = '',
|
||||
scripts = <String>[],
|
||||
parameters = <String>[];
|
||||
|
||||
BuildTask._(this.name, this.language, this.scripts, this.parameters) :
|
||||
super(null);
|
||||
BuildTask._(this.name, this.language, this.scripts, this.parameters)
|
||||
: super(null);
|
||||
|
||||
/// The human readable name of the step running the script.
|
||||
final String name;
|
||||
@@ -496,7 +525,9 @@ final class BuildArchive extends BuildConfigBase {
|
||||
final String? basePath = stringOfJson(map, 'base_path', errors);
|
||||
final String? realm = stringOfJson(map, 'realm', errors);
|
||||
final List<String>? includePaths = stringListOfJson(
|
||||
map, 'include_paths', errors,
|
||||
map,
|
||||
'include_paths',
|
||||
errors,
|
||||
);
|
||||
if (name == null ||
|
||||
type == null ||
|
||||
@@ -508,12 +539,12 @@ final class BuildArchive extends BuildConfigBase {
|
||||
return BuildArchive._(name, type, basePath, realm, includePaths);
|
||||
}
|
||||
|
||||
BuildArchive._invalid(super.error) :
|
||||
name = '',
|
||||
type = '',
|
||||
basePath = '',
|
||||
realm = '',
|
||||
includePaths = <String>[];
|
||||
BuildArchive._invalid(super.error)
|
||||
: name = '',
|
||||
type = '',
|
||||
basePath = '',
|
||||
realm = '',
|
||||
includePaths = <String>[];
|
||||
|
||||
BuildArchive._(
|
||||
this.name,
|
||||
@@ -553,16 +584,26 @@ final class GlobalTest extends BuildConfigBase {
|
||||
final String? name = stringOfJson(map, 'name', errors);
|
||||
final String? recipe = stringOfJson(map, 'recipe', errors);
|
||||
final List<String>? droneDimensions = stringListOfJson(
|
||||
map, 'drone_dimensions', errors,
|
||||
map,
|
||||
'drone_dimensions',
|
||||
errors,
|
||||
);
|
||||
final List<String>? dependencies = stringListOfJson(
|
||||
map, 'dependencies', errors,
|
||||
map,
|
||||
'dependencies',
|
||||
errors,
|
||||
);
|
||||
final List<TestDependency>? testDependencies = objListOfJson(
|
||||
map, 'test_dependencies', errors, TestDependency.fromJson,
|
||||
map,
|
||||
'test_dependencies',
|
||||
errors,
|
||||
TestDependency.fromJson,
|
||||
);
|
||||
final List<TestTask>? tasks = objListOfJson(
|
||||
map, 'tasks', errors, TestTask.fromJson,
|
||||
map,
|
||||
'tasks',
|
||||
errors,
|
||||
TestTask.fromJson,
|
||||
);
|
||||
if (name == null ||
|
||||
recipe == null ||
|
||||
@@ -573,16 +614,16 @@ final class GlobalTest extends BuildConfigBase {
|
||||
return GlobalTest._invalid(errors);
|
||||
}
|
||||
return GlobalTest._(
|
||||
name, recipe, droneDimensions, dependencies, testDependencies, tasks);
|
||||
name, recipe, droneDimensions, dependencies, testDependencies, tasks);
|
||||
}
|
||||
|
||||
GlobalTest._invalid(super.errors) :
|
||||
name = '',
|
||||
recipe = '',
|
||||
droneDimensions = <String>[],
|
||||
dependencies = <String>[],
|
||||
testDependencies = <TestDependency>[],
|
||||
tasks = <TestTask>[];
|
||||
GlobalTest._invalid(super.errors)
|
||||
: name = '',
|
||||
recipe = '',
|
||||
droneDimensions = <String>[],
|
||||
dependencies = <String>[],
|
||||
testDependencies = <TestDependency>[],
|
||||
tasks = <TestTask>[];
|
||||
|
||||
GlobalTest._(
|
||||
this.name,
|
||||
@@ -648,7 +689,9 @@ final class TestDependency extends BuildConfigBase {
|
||||
return TestDependency._(dependency, version);
|
||||
}
|
||||
|
||||
TestDependency._invalid(super.error) : dependency = '', version = '';
|
||||
TestDependency._invalid(super.error)
|
||||
: dependency = '',
|
||||
version = '';
|
||||
|
||||
TestDependency._(this.dependency, this.version) : super(null);
|
||||
|
||||
@@ -673,9 +716,12 @@ final class TestTask extends BuildConfigBase {
|
||||
final String? name = stringOfJson(map, 'name', errors);
|
||||
final String? language = stringOfJson(map, 'language', errors);
|
||||
final String? script = stringOfJson(map, 'script', errors);
|
||||
final int? maxAttempts = intOfJson(map, 'max_attempts', fallback: 1, errors);
|
||||
final int? maxAttempts =
|
||||
intOfJson(map, 'max_attempts', fallback: 1, errors);
|
||||
final List<String>? parameters = stringListOfJson(
|
||||
map, 'parameters', errors,
|
||||
map,
|
||||
'parameters',
|
||||
errors,
|
||||
);
|
||||
if (name == null ||
|
||||
language == null ||
|
||||
@@ -687,12 +733,12 @@ final class TestTask extends BuildConfigBase {
|
||||
return TestTask._(name, language, script, maxAttempts, parameters);
|
||||
}
|
||||
|
||||
TestTask._invalid(super.error) :
|
||||
name = '',
|
||||
language = '',
|
||||
script = '',
|
||||
maxAttempts = 0,
|
||||
parameters = <String>[];
|
||||
TestTask._invalid(super.error)
|
||||
: name = '',
|
||||
language = '',
|
||||
script = '',
|
||||
maxAttempts = 0,
|
||||
parameters = <String>[];
|
||||
|
||||
TestTask._(
|
||||
this.name,
|
||||
@@ -732,21 +778,18 @@ final class GlobalArchive extends BuildConfigBase {
|
||||
final String? source = stringOfJson(map, 'source', errors);
|
||||
final String? destination = stringOfJson(map, 'destination', errors);
|
||||
final String? realm = stringOfJson(map, 'realm', errors);
|
||||
if (source == null ||
|
||||
destination == null ||
|
||||
realm == null) {
|
||||
if (source == null || destination == null || realm == null) {
|
||||
return GlobalArchive._invalid(errors);
|
||||
}
|
||||
return GlobalArchive._(source, destination, realm);
|
||||
}
|
||||
|
||||
GlobalArchive._invalid(super.error) :
|
||||
source = '',
|
||||
destination = '',
|
||||
realm = '';
|
||||
GlobalArchive._invalid(super.error)
|
||||
: source = '',
|
||||
destination = '',
|
||||
realm = '';
|
||||
|
||||
GlobalArchive._(this.source, this.destination, this.realm) :
|
||||
super(null);
|
||||
GlobalArchive._(this.source, this.destination, this.realm) : super(null);
|
||||
|
||||
/// The path of the artifact relative to the engine checkout.
|
||||
final String source;
|
||||
@@ -764,7 +807,8 @@ bool _canRunOn(List<String> droneDimensions, Platform platform) {
|
||||
for (final String dimension in droneDimensions) {
|
||||
os ??= switch (dimension.split('=')) {
|
||||
['os', 'Linux'] => Platform.linux,
|
||||
['os', final String win] when win.startsWith('Windows') => Platform.windows,
|
||||
['os', final String win] when win.startsWith('Windows') =>
|
||||
Platform.windows,
|
||||
['os', final String mac] when mac.startsWith('Mac') => Platform.macOS,
|
||||
_ => null,
|
||||
};
|
||||
@@ -813,7 +857,9 @@ List<T>? objListOfJson<T>(
|
||||
}
|
||||
}
|
||||
return (map[field]! as List<Object?>)
|
||||
.cast<Map<String, Object?>>().map<T>(fn).toList();
|
||||
.cast<Map<String, Object?>>()
|
||||
.map<T>(fn)
|
||||
.toList();
|
||||
}
|
||||
|
||||
List<String>? stringListOfJson(
|
||||
|
||||
@@ -28,28 +28,29 @@ class BuildConfigLoader {
|
||||
/// are added as strings to the [errors] list. That last should be checked
|
||||
/// for errors after accessing this getter.
|
||||
///
|
||||
/// The [BuildConfig]s given by this getter should be further checked for
|
||||
/// The [BuilderConfig]s given by this getter should be further checked for
|
||||
/// validity by calling `BuildConfig.check()` on each one. See
|
||||
/// `bin/check.dart` for an example.
|
||||
late final Map<String, BuildConfig> configs = (){
|
||||
late final Map<String, BuilderConfig> configs = () {
|
||||
return _parseAllBuildConfigs(buildConfigsDir);
|
||||
}();
|
||||
|
||||
Map<String, BuildConfig> _parseAllBuildConfigs(io.Directory dir) {
|
||||
final Map<String, BuildConfig> result = <String, BuildConfig>{};
|
||||
Map<String, BuilderConfig> _parseAllBuildConfigs(io.Directory dir) {
|
||||
final Map<String, BuilderConfig> result = <String, BuilderConfig>{};
|
||||
if (!dir.existsSync()) {
|
||||
errors.add('${buildConfigsDir.path} does not exist.');
|
||||
return result;
|
||||
}
|
||||
final List<io.File> jsonFiles = dir
|
||||
.listSync(recursive: true)
|
||||
.whereType<io.File>()
|
||||
.where((io.File f) => f.path.endsWith('.json'))
|
||||
.toList();
|
||||
.listSync(recursive: true)
|
||||
.whereType<io.File>()
|
||||
.where((io.File f) => f.path.endsWith('.json'))
|
||||
.toList();
|
||||
for (final io.File jsonFile in jsonFiles) {
|
||||
final String basename = p.basename(jsonFile.path);
|
||||
final String name = basename.substring(
|
||||
0, basename.length - 5,
|
||||
0,
|
||||
basename.length - 5,
|
||||
);
|
||||
final String jsonData = jsonFile.readAsStringSync();
|
||||
final dynamic maybeJson;
|
||||
@@ -63,7 +64,8 @@ class BuildConfigLoader {
|
||||
errors.add('${jsonFile.path} did not contain a json map.');
|
||||
continue;
|
||||
}
|
||||
result[name] = BuildConfig.fromJson(path: jsonFile.path, map: maybeJson);
|
||||
result[name] =
|
||||
BuilderConfig.fromJson(path: jsonFile.path, map: maybeJson);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -40,8 +40,13 @@ final class RunnerStart extends RunnerEvent {
|
||||
/// A [RunnerEvent] representing the progress of a started command.
|
||||
final class RunnerProgress extends RunnerEvent {
|
||||
RunnerProgress(
|
||||
super.name, super.command, super.timestamp,
|
||||
this.what, this.completed, this.total, this.done,
|
||||
super.name,
|
||||
super.command,
|
||||
super.timestamp,
|
||||
this.what,
|
||||
this.completed,
|
||||
this.total,
|
||||
this.done,
|
||||
) : percent = (completed * 100) / total;
|
||||
|
||||
/// What a command is currently working on, for example a build target or
|
||||
@@ -164,12 +169,12 @@ final ProcessRunnerResult _dryRunResult = ProcessRunnerResult(
|
||||
pid: 0, // pid,
|
||||
);
|
||||
|
||||
/// The [Runner] for a [GlobalBuild].
|
||||
/// The [Runner] for a [Build].
|
||||
///
|
||||
/// Runs the specified `gn` and `ninja` commands, followed by generator tasks,
|
||||
/// and finally tests.
|
||||
final class GlobalBuildRunner extends Runner {
|
||||
GlobalBuildRunner({
|
||||
final class BuildRunner extends Runner {
|
||||
BuildRunner({
|
||||
Platform? platform,
|
||||
ProcessRunner? processRunner,
|
||||
ffi.Abi? abi,
|
||||
@@ -184,15 +189,15 @@ final class GlobalBuildRunner extends Runner {
|
||||
this.runTests = true,
|
||||
bool dryRun = false,
|
||||
}) : super(
|
||||
platform ?? const LocalPlatform(),
|
||||
processRunner ?? ProcessRunner(),
|
||||
abi ?? ffi.Abi.current(),
|
||||
engineSrcDir,
|
||||
dryRun,
|
||||
);
|
||||
platform ?? const LocalPlatform(),
|
||||
processRunner ?? ProcessRunner(),
|
||||
abi ?? ffi.Abi.current(),
|
||||
engineSrcDir,
|
||||
dryRun,
|
||||
);
|
||||
|
||||
/// The [GlobalBuild] to run.
|
||||
final GlobalBuild build;
|
||||
/// The [Build] to run.
|
||||
final Build build;
|
||||
|
||||
/// Extra arguments to append to the `gn` command.
|
||||
final List<String> extraGnArgs;
|
||||
@@ -219,7 +224,9 @@ final class GlobalBuildRunner extends Runner {
|
||||
Future<bool> run(RunnerEventHandler eventHandler) async {
|
||||
if (!build.canRunOn(platform)) {
|
||||
eventHandler(RunnerError(
|
||||
build.name, <String>[], DateTime.now(),
|
||||
build.name,
|
||||
<String>[],
|
||||
DateTime.now(),
|
||||
'Build with drone_dimensions "{${build.droneDimensions.join(',')}}" '
|
||||
'cannot run on platform ${platform.operatingSystem}',
|
||||
));
|
||||
@@ -294,21 +301,27 @@ final class GlobalBuildRunner extends Runner {
|
||||
);
|
||||
}
|
||||
final RunnerResult result = RunnerResult(
|
||||
'${build.name}: GN', command, DateTime.now(), processResult,
|
||||
'${build.name}: GN',
|
||||
command,
|
||||
DateTime.now(),
|
||||
processResult,
|
||||
);
|
||||
eventHandler(result);
|
||||
return result.ok;
|
||||
}
|
||||
|
||||
late final String _hostCpu = (){
|
||||
late final String _hostCpu = () {
|
||||
return switch (abi) {
|
||||
ffi.Abi.linuxArm64 || ffi.Abi.macosArm64 || ffi.Abi.windowsArm64 => 'arm64',
|
||||
ffi.Abi.linuxArm64 ||
|
||||
ffi.Abi.macosArm64 ||
|
||||
ffi.Abi.windowsArm64 =>
|
||||
'arm64',
|
||||
ffi.Abi.linuxX64 || ffi.Abi.macosX64 || ffi.Abi.windowsX64 => 'x64',
|
||||
_ => throw StateError('This host platform "$abi" is not supported.'),
|
||||
};
|
||||
}();
|
||||
|
||||
late final String _buildtoolsPath = (){
|
||||
late final String _buildtoolsPath = () {
|
||||
final String os = platform.operatingSystem;
|
||||
final String platformDir = switch (os) {
|
||||
Platform.linux => 'linux-$_hostCpu',
|
||||
@@ -335,21 +348,24 @@ final class GlobalBuildRunner extends Runner {
|
||||
_ => throw StateError('This host OS "$os" is not supported.'),
|
||||
};
|
||||
final String reclientConfigPath = p.join(
|
||||
engineSrcDir.path, 'flutter', 'build', 'rbe', reclientConfigFile,
|
||||
engineSrcDir.path,
|
||||
'flutter',
|
||||
'build',
|
||||
'rbe',
|
||||
reclientConfigFile,
|
||||
);
|
||||
final List<String> bootstrapCommand = <String>[
|
||||
bootstrapPath,
|
||||
'--re_proxy=$reproxyPath',
|
||||
'--automatic_auth=true',
|
||||
if (shutdown)
|
||||
'--shutdown'
|
||||
else ...<String>[
|
||||
'--cfg=$reclientConfigPath'
|
||||
],
|
||||
if (shutdown) '--shutdown' else ...<String>['--cfg=$reclientConfigPath'],
|
||||
];
|
||||
if (!processRunner.processManager.canRun(bootstrapPath)) {
|
||||
eventHandler(RunnerError(
|
||||
build.name, <String>[], DateTime.now(), '"$bootstrapPath" not found.',
|
||||
build.name,
|
||||
<String>[],
|
||||
DateTime.now(),
|
||||
'"$bootstrapPath" not found.',
|
||||
));
|
||||
return false;
|
||||
}
|
||||
@@ -363,7 +379,8 @@ final class GlobalBuildRunner extends Runner {
|
||||
bootstrapResult = _dryRunResult;
|
||||
} else {
|
||||
bootstrapResult = await processRunner.runProcess(
|
||||
bootstrapCommand, failOk: true,
|
||||
bootstrapCommand,
|
||||
failOk: true,
|
||||
);
|
||||
}
|
||||
eventHandler(RunnerResult(
|
||||
@@ -384,20 +401,27 @@ final class GlobalBuildRunner extends Runner {
|
||||
bool success = false;
|
||||
try {
|
||||
final String ninjaPath = p.join(
|
||||
engineSrcDir.path, 'flutter', 'third_party', 'ninja', 'ninja',
|
||||
engineSrcDir.path,
|
||||
'flutter',
|
||||
'third_party',
|
||||
'ninja',
|
||||
'ninja',
|
||||
);
|
||||
final String outDir = p.join(
|
||||
engineSrcDir.path, 'out', build.ninja.config,
|
||||
engineSrcDir.path,
|
||||
'out',
|
||||
build.ninja.config,
|
||||
);
|
||||
final List<String> command = <String>[
|
||||
ninjaPath,
|
||||
'-C', outDir,
|
||||
'-C',
|
||||
outDir,
|
||||
if (_isGomaOrRbe) ...<String>['-j', '200'],
|
||||
...extraNinjaArgs,
|
||||
...build.ninja.targets,
|
||||
];
|
||||
eventHandler(RunnerStart(
|
||||
'${build.name}: ninja', command, DateTime.now()),
|
||||
eventHandler(
|
||||
RunnerStart('${build.name}: ninja', command, DateTime.now()),
|
||||
);
|
||||
final ProcessRunnerResult processResult;
|
||||
if (dryRun) {
|
||||
@@ -412,14 +436,14 @@ final class GlobalBuildRunner extends Runner {
|
||||
final Completer<void> stderrComplete = Completer<void>();
|
||||
|
||||
process.stdout
|
||||
.transform<String>(const Utf8Decoder())
|
||||
.transform(const LineSplitter())
|
||||
.listen(
|
||||
(String line) {
|
||||
_ninjaProgress(eventHandler, command, line);
|
||||
},
|
||||
onDone: () async => stdoutComplete.complete(),
|
||||
);
|
||||
.transform<String>(const Utf8Decoder())
|
||||
.transform(const LineSplitter())
|
||||
.listen(
|
||||
(String line) {
|
||||
_ninjaProgress(eventHandler, command, line);
|
||||
},
|
||||
onDone: () async => stdoutComplete.complete(),
|
||||
);
|
||||
|
||||
process.stderr.listen(
|
||||
stderrOutput.addAll,
|
||||
@@ -427,7 +451,8 @@ final class GlobalBuildRunner extends Runner {
|
||||
);
|
||||
|
||||
await Future.wait<void>(<Future<void>>[
|
||||
stdoutComplete.future, stderrComplete.future,
|
||||
stdoutComplete.future,
|
||||
stderrComplete.future,
|
||||
]);
|
||||
final int exitCode = await process.exitCode;
|
||||
|
||||
@@ -440,7 +465,10 @@ final class GlobalBuildRunner extends Runner {
|
||||
);
|
||||
}
|
||||
eventHandler(RunnerResult(
|
||||
'${build.name}: ninja', command, DateTime.now(), processResult,
|
||||
'${build.name}: ninja',
|
||||
command,
|
||||
DateTime.now(),
|
||||
processResult,
|
||||
));
|
||||
success = processResult.exitCode == 0;
|
||||
} finally {
|
||||
@@ -467,9 +495,8 @@ final class GlobalBuildRunner extends Runner {
|
||||
}
|
||||
// Extract the two numbers by stripping the '[' and ']' and splitting on
|
||||
// the '/'.
|
||||
final List<String> progress = maybeProgress
|
||||
.substring(1, maybeProgress.length - 1)
|
||||
.split('/');
|
||||
final List<String> progress =
|
||||
maybeProgress.substring(1, maybeProgress.length - 1).split('/');
|
||||
if (progress.length < 2) {
|
||||
return;
|
||||
}
|
||||
@@ -485,7 +512,7 @@ final class GlobalBuildRunner extends Runner {
|
||||
line.replaceFirst(maybeProgress, '').trim(),
|
||||
completed,
|
||||
total,
|
||||
completed == total, // True when done.
|
||||
completed == total, // True when done.
|
||||
));
|
||||
}
|
||||
|
||||
@@ -529,7 +556,7 @@ final class GlobalBuildRunner extends Runner {
|
||||
}
|
||||
}
|
||||
|
||||
/// The [Runner] for a [BuildTask] of a generator of a [GlobalBuild].
|
||||
/// The [Runner] for a [BuildTask] of a generator of a [Build].
|
||||
final class BuildTaskRunner extends Runner {
|
||||
BuildTaskRunner({
|
||||
Platform? platform,
|
||||
@@ -539,12 +566,12 @@ final class BuildTaskRunner extends Runner {
|
||||
required this.task,
|
||||
bool dryRun = false,
|
||||
}) : super(
|
||||
platform ?? const LocalPlatform(),
|
||||
processRunner ?? ProcessRunner(),
|
||||
abi ?? ffi.Abi.current(),
|
||||
engineSrcDir,
|
||||
dryRun,
|
||||
);
|
||||
platform ?? const LocalPlatform(),
|
||||
processRunner ?? ProcessRunner(),
|
||||
abi ?? ffi.Abi.current(),
|
||||
engineSrcDir,
|
||||
dryRun,
|
||||
);
|
||||
|
||||
/// The task to run.
|
||||
final BuildTask task;
|
||||
@@ -570,7 +597,10 @@ final class BuildTaskRunner extends Runner {
|
||||
);
|
||||
}
|
||||
final RunnerResult result = RunnerResult(
|
||||
task.name, command, DateTime.now(), processResult,
|
||||
task.name,
|
||||
command,
|
||||
DateTime.now(),
|
||||
processResult,
|
||||
);
|
||||
eventHandler(result);
|
||||
if (!result.ok) {
|
||||
@@ -581,7 +611,7 @@ final class BuildTaskRunner extends Runner {
|
||||
}
|
||||
}
|
||||
|
||||
/// The [Runner] for a [BuildTest] of a [GlobalBuild].
|
||||
/// The [Runner] for a [BuildTest] of a [Build].
|
||||
final class BuildTestRunner extends Runner {
|
||||
BuildTestRunner({
|
||||
Platform? platform,
|
||||
@@ -592,12 +622,12 @@ final class BuildTestRunner extends Runner {
|
||||
this.extraTestArgs = const <String>[],
|
||||
bool dryRun = false,
|
||||
}) : super(
|
||||
platform ?? const LocalPlatform(),
|
||||
processRunner ?? ProcessRunner(),
|
||||
abi ?? ffi.Abi.current(),
|
||||
engineSrcDir,
|
||||
dryRun,
|
||||
);
|
||||
platform ?? const LocalPlatform(),
|
||||
processRunner ?? ProcessRunner(),
|
||||
abi ?? ffi.Abi.current(),
|
||||
engineSrcDir,
|
||||
dryRun,
|
||||
);
|
||||
|
||||
/// The test to run.
|
||||
final BuildTest test;
|
||||
@@ -630,7 +660,10 @@ final class BuildTestRunner extends Runner {
|
||||
);
|
||||
}
|
||||
final RunnerResult result = RunnerResult(
|
||||
test.name, command, DateTime.now(), processResult,
|
||||
test.name,
|
||||
command,
|
||||
DateTime.now(),
|
||||
processResult,
|
||||
);
|
||||
eventHandler(result);
|
||||
return result.ok;
|
||||
|
||||
@@ -33,7 +33,10 @@ int main() {
|
||||
test('BuildConfigLoader gives an empty config when no configs found', () {
|
||||
final FileSystem fs = MemoryFileSystem();
|
||||
final String buildConfigPath = fs.path.join(
|
||||
'flutter', 'ci', 'builders', 'linux_test_build.json',
|
||||
'flutter',
|
||||
'ci',
|
||||
'builders',
|
||||
'linux_test_build.json',
|
||||
);
|
||||
final Directory buildConfigsDir = fs.directory(buildConfigPath);
|
||||
final BuildConfigLoader loader = BuildConfigLoader(
|
||||
@@ -41,10 +44,12 @@ int main() {
|
||||
);
|
||||
|
||||
expect(loader.configs, isNotNull);
|
||||
expect(loader.errors[0], equals(
|
||||
'flutter/ci/builders/linux_test_build.json does not exist.',
|
||||
));
|
||||
expect(loader.configs, equals(<String, BuildConfig>{}));
|
||||
expect(
|
||||
loader.errors[0],
|
||||
equals(
|
||||
'flutter/ci/builders/linux_test_build.json does not exist.',
|
||||
));
|
||||
expect(loader.configs, equals(<String, BuilderConfig>{}));
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ void main() {
|
||||
return;
|
||||
}
|
||||
|
||||
final BuildConfig buildConfig = BuildConfig.fromJson(
|
||||
final BuilderConfig buildConfig = BuilderConfig.fromJson(
|
||||
path: 'linux_test_config',
|
||||
map: convert.jsonDecode(fixtures.buildConfigJson) as Map<String, Object?>,
|
||||
);
|
||||
@@ -89,8 +89,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('GlobalBuildRunner runs the right commands', () async {
|
||||
final GlobalBuild targetBuild = buildConfig.builds[0];
|
||||
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
|
||||
final Build targetBuild = buildConfig.builds[0];
|
||||
final BuildRunner buildRunner = BuildRunner(
|
||||
platform: FakePlatform(operatingSystem: Platform.linux),
|
||||
processRunner: ProcessRunner(
|
||||
// dryRun should not try to spawn any processes.
|
||||
@@ -123,7 +123,8 @@ void main() {
|
||||
expect(events[2] is RunnerStart, isTrue);
|
||||
expect(events[2].name, equals('$buildName: ninja'));
|
||||
expect(events[2].command[0], contains('ninja'));
|
||||
final String configPath = '${engine.srcDir.path}/out/${targetBuild.ninja.config}';
|
||||
final String configPath =
|
||||
'${engine.srcDir.path}/out/${targetBuild.ninja.config}';
|
||||
expect(events[2].command.contains(configPath), isTrue);
|
||||
for (final String target in targetBuild.ninja.targets) {
|
||||
expect(events[2].command.contains(target), isTrue);
|
||||
@@ -151,8 +152,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('GlobalBuildRunner extra args are propagated correctly', () async {
|
||||
final GlobalBuild targetBuild = buildConfig.builds[0];
|
||||
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
|
||||
final Build targetBuild = buildConfig.builds[0];
|
||||
final BuildRunner buildRunner = BuildRunner(
|
||||
platform: FakePlatform(operatingSystem: Platform.linux),
|
||||
processRunner: ProcessRunner(
|
||||
// dryRun should not try to spawn any processes.
|
||||
@@ -191,8 +192,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('GlobalBuildRunner passes large -j for a goma build', () async {
|
||||
final GlobalBuild targetBuild = buildConfig.builds[0];
|
||||
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
|
||||
final Build targetBuild = buildConfig.builds[0];
|
||||
final BuildRunner buildRunner = BuildRunner(
|
||||
platform: FakePlatform(operatingSystem: Platform.linux),
|
||||
processRunner: ProcessRunner(
|
||||
// dryRun should not try to spawn any processes.
|
||||
@@ -220,8 +221,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('GlobalBuildRunner passes large -j for an rbe build', () async {
|
||||
final GlobalBuild targetBuild = buildConfig.builds[0];
|
||||
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
|
||||
final Build targetBuild = buildConfig.builds[0];
|
||||
final BuildRunner buildRunner = BuildRunner(
|
||||
platform: FakePlatform(operatingSystem: Platform.linux),
|
||||
processRunner: ProcessRunner(
|
||||
processManager: _fakeProcessManager(),
|
||||
@@ -261,8 +262,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('GlobalBuildRunner skips GN when runGn is false', () async {
|
||||
final GlobalBuild targetBuild = buildConfig.builds[0];
|
||||
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
|
||||
final Build targetBuild = buildConfig.builds[0];
|
||||
final BuildRunner buildRunner = BuildRunner(
|
||||
platform: FakePlatform(operatingSystem: Platform.linux),
|
||||
processRunner: ProcessRunner(
|
||||
// dryRun should not try to spawn any processes.
|
||||
@@ -286,7 +287,8 @@ void main() {
|
||||
expect(events[0] is RunnerStart, isTrue);
|
||||
expect(events[0].name, equals('$buildName: ninja'));
|
||||
expect(events[0].command[0], contains('ninja'));
|
||||
final String configPath = '${engine.srcDir.path}/out/${targetBuild.ninja.config}';
|
||||
final String configPath =
|
||||
'${engine.srcDir.path}/out/${targetBuild.ninja.config}';
|
||||
expect(events[0].command.contains(configPath), isTrue);
|
||||
for (final String target in targetBuild.ninja.targets) {
|
||||
expect(events[0].command.contains(target), isTrue);
|
||||
@@ -296,8 +298,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('GlobalBuildRunner skips Ninja when runNinja is false', () async {
|
||||
final GlobalBuild targetBuild = buildConfig.builds[0];
|
||||
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
|
||||
final Build targetBuild = buildConfig.builds[0];
|
||||
final BuildRunner buildRunner = BuildRunner(
|
||||
platform: FakePlatform(operatingSystem: Platform.linux),
|
||||
processRunner: ProcessRunner(
|
||||
// dryRun should not try to spawn any processes.
|
||||
@@ -337,9 +339,10 @@ void main() {
|
||||
expect(events[3].name, equals('generator_task'));
|
||||
});
|
||||
|
||||
test('GlobalBuildRunner skips generators when runGenerators is false', () async {
|
||||
final GlobalBuild targetBuild = buildConfig.builds[0];
|
||||
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
|
||||
test('GlobalBuildRunner skips generators when runGenerators is false',
|
||||
() async {
|
||||
final Build targetBuild = buildConfig.builds[0];
|
||||
final BuildRunner buildRunner = BuildRunner(
|
||||
platform: FakePlatform(operatingSystem: Platform.linux),
|
||||
processRunner: ProcessRunner(
|
||||
// dryRun should not try to spawn any processes.
|
||||
@@ -363,7 +366,8 @@ void main() {
|
||||
expect(events[2] is RunnerStart, isTrue);
|
||||
expect(events[2].name, equals('$buildName: ninja'));
|
||||
expect(events[2].command[0], contains('ninja'));
|
||||
final String configPath = '${engine.srcDir.path}/out/${targetBuild.ninja.config}';
|
||||
final String configPath =
|
||||
'${engine.srcDir.path}/out/${targetBuild.ninja.config}';
|
||||
expect(events[2].command.contains(configPath), isTrue);
|
||||
for (final String target in targetBuild.ninja.targets) {
|
||||
expect(events[2].command.contains(target), isTrue);
|
||||
@@ -382,8 +386,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('GlobalBuildRunner skips tests when runTests is false', () async {
|
||||
final GlobalBuild targetBuild = buildConfig.builds[0];
|
||||
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
|
||||
final Build targetBuild = buildConfig.builds[0];
|
||||
final BuildRunner buildRunner = BuildRunner(
|
||||
platform: FakePlatform(operatingSystem: Platform.linux),
|
||||
processRunner: ProcessRunner(
|
||||
// dryRun should not try to spawn any processes.
|
||||
@@ -414,8 +418,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('GlobalBuildRunner extraGnArgs overrides build config args', () async {
|
||||
final GlobalBuild targetBuild = buildConfig.builds[0];
|
||||
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
|
||||
final Build targetBuild = buildConfig.builds[0];
|
||||
final BuildRunner buildRunner = BuildRunner(
|
||||
platform: FakePlatform(operatingSystem: Platform.linux),
|
||||
processRunner: ProcessRunner(
|
||||
processManager: _fakeProcessManager(),
|
||||
@@ -449,8 +453,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('GlobalBuildRunner canRun returns false on OS mismatch', () async {
|
||||
final GlobalBuild targetBuild = buildConfig.builds[0];
|
||||
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
|
||||
final Build targetBuild = buildConfig.builds[0];
|
||||
final BuildRunner buildRunner = BuildRunner(
|
||||
platform: FakePlatform(operatingSystem: Platform.macOS),
|
||||
processRunner: ProcessRunner(
|
||||
// dryRun should not try to spawn any processes.
|
||||
@@ -470,8 +474,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('GlobalBuildRunner fails when gn fails', () async {
|
||||
final GlobalBuild targetBuild = buildConfig.builds[0];
|
||||
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
|
||||
final Build targetBuild = buildConfig.builds[0];
|
||||
final BuildRunner buildRunner = BuildRunner(
|
||||
platform: FakePlatform(operatingSystem: Platform.linux),
|
||||
processRunner: ProcessRunner(
|
||||
processManager: _fakeProcessManager(
|
||||
@@ -497,8 +501,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('GlobalBuildRunner fails when ninja fails', () async {
|
||||
final GlobalBuild targetBuild = buildConfig.builds[0];
|
||||
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
|
||||
final Build targetBuild = buildConfig.builds[0];
|
||||
final BuildRunner buildRunner = BuildRunner(
|
||||
platform: FakePlatform(operatingSystem: Platform.linux),
|
||||
processRunner: ProcessRunner(
|
||||
processManager: _fakeProcessManager(
|
||||
@@ -524,8 +528,8 @@ void main() {
|
||||
});
|
||||
|
||||
test('GlobalBuildRunner fails an RBE build when bootstrap fails', () async {
|
||||
final GlobalBuild targetBuild = buildConfig.builds[0];
|
||||
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
|
||||
final Build targetBuild = buildConfig.builds[0];
|
||||
final BuildRunner buildRunner = BuildRunner(
|
||||
platform: FakePlatform(operatingSystem: Platform.linux),
|
||||
processRunner: ProcessRunner(
|
||||
processManager: _fakeProcessManager(
|
||||
@@ -552,9 +556,10 @@ void main() {
|
||||
expect((events[3] as RunnerResult).ok, isFalse);
|
||||
});
|
||||
|
||||
test('GlobalBuildRunner fails an RBE build when bootstrap does not exist', () async {
|
||||
final GlobalBuild targetBuild = buildConfig.builds[0];
|
||||
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
|
||||
test('GlobalBuildRunner fails an RBE build when bootstrap does not exist',
|
||||
() async {
|
||||
final Build targetBuild = buildConfig.builds[0];
|
||||
final BuildRunner buildRunner = BuildRunner(
|
||||
platform: FakePlatform(operatingSystem: Platform.linux),
|
||||
processRunner: ProcessRunner(
|
||||
processManager: _fakeProcessManager(
|
||||
@@ -580,9 +585,10 @@ void main() {
|
||||
expect(events[2] is RunnerError, isTrue);
|
||||
});
|
||||
|
||||
test('GlobalBuildRunner throws a StateError on an unsupported host cpu', () async {
|
||||
final GlobalBuild targetBuild = buildConfig.builds[0];
|
||||
final GlobalBuildRunner buildRunner = GlobalBuildRunner(
|
||||
test('GlobalBuildRunner throws a StateError on an unsupported host cpu',
|
||||
() async {
|
||||
final Build targetBuild = buildConfig.builds[0];
|
||||
final BuildRunner buildRunner = BuildRunner(
|
||||
platform: FakePlatform(operatingSystem: Platform.linux),
|
||||
processRunner: ProcessRunner(
|
||||
processManager: _fakeProcessManager(),
|
||||
@@ -612,18 +618,17 @@ FakeProcessManager _fakeProcessManager({
|
||||
}) {
|
||||
final io.ProcessResult success = io.ProcessResult(1, 0, '', '');
|
||||
FakeProcess fakeProcess(io.ProcessResult? result) => FakeProcess(
|
||||
exitCode: result?.exitCode ?? 0,
|
||||
stdout: result?.stdout as String? ?? '',
|
||||
stderr: result?.stderr as String? ?? '',
|
||||
);
|
||||
exitCode: result?.exitCode ?? 0,
|
||||
stdout: result?.stdout as String? ?? '',
|
||||
stderr: result?.stderr as String? ?? '',
|
||||
);
|
||||
return FakeProcessManager(
|
||||
canRun: canRun ?? (Object? exe, {String? workingDirectory}) => true,
|
||||
onRun: (List<String> cmd) => switch (cmd) {
|
||||
_ => failUnknown ? io.ProcessResult(1, 1, '', '') : success,
|
||||
},
|
||||
onStart: (List<String> cmd) => switch (cmd) {
|
||||
[final String exe, ...] when exe.endsWith('gn') =>
|
||||
fakeProcess(gnResult),
|
||||
[final String exe, ...] when exe.endsWith('gn') => fakeProcess(gnResult),
|
||||
[final String exe, ...] when exe.endsWith('bootstrap') =>
|
||||
fakeProcess(bootstrapResult),
|
||||
[final String exe, ...] when exe.endsWith('ninja') =>
|
||||
|
||||
@@ -12,7 +12,7 @@ import 'fixtures.dart' as fixtures;
|
||||
|
||||
int main() {
|
||||
test('BuildConfig parser works', () {
|
||||
final BuildConfig buildConfig = BuildConfig.fromJson(
|
||||
final BuilderConfig buildConfig = BuilderConfig.fromJson(
|
||||
path: 'linux_test_config',
|
||||
map: convert.jsonDecode(fixtures.buildConfigJson) as Map<String, Object?>,
|
||||
);
|
||||
@@ -20,7 +20,7 @@ int main() {
|
||||
expect(buildConfig.errors, isNull);
|
||||
expect(buildConfig.builds.length, equals(1));
|
||||
|
||||
final GlobalBuild globalBuild = buildConfig.builds[0];
|
||||
final Build globalBuild = buildConfig.builds[0];
|
||||
expect(globalBuild.name, equals('build_name'));
|
||||
expect(globalBuild.gn.length, equals(4));
|
||||
expect(globalBuild.gn[0], equals('--gn-arg'));
|
||||
@@ -106,14 +106,16 @@ int main() {
|
||||
"tests": []
|
||||
}
|
||||
''';
|
||||
final BuildConfig buildConfig = BuildConfig.fromJson(
|
||||
final BuilderConfig buildConfig = BuilderConfig.fromJson(
|
||||
path: 'linux_test_config',
|
||||
map: convert.jsonDecode(invalidInput) as Map<String, Object?>,
|
||||
);
|
||||
expect(buildConfig.valid, isFalse);
|
||||
expect(buildConfig.errors![0], equals(
|
||||
'For field "builds", expected type: list, actual type: int.',
|
||||
));
|
||||
expect(
|
||||
buildConfig.errors![0],
|
||||
equals(
|
||||
'For field "builds", expected type: list, actual type: int.',
|
||||
));
|
||||
});
|
||||
|
||||
test('GlobalBuild flags invalid input', () {
|
||||
@@ -128,16 +130,18 @@ int main() {
|
||||
"tests": []
|
||||
}
|
||||
''';
|
||||
final BuildConfig buildConfig = BuildConfig.fromJson(
|
||||
final BuilderConfig buildConfig = BuilderConfig.fromJson(
|
||||
path: 'linux_test_config',
|
||||
map: convert.jsonDecode(invalidInput) as Map<String, Object?>,
|
||||
);
|
||||
expect(buildConfig.valid, isTrue);
|
||||
expect(buildConfig.builds.length, equals(1));
|
||||
expect(buildConfig.builds[0].valid, isFalse);
|
||||
expect(buildConfig.builds[0].errors![0], equals(
|
||||
'For field "name", expected type: string, actual type: int.',
|
||||
));
|
||||
expect(
|
||||
buildConfig.builds[0].errors![0],
|
||||
equals(
|
||||
'For field "name", expected type: string, actual type: int.',
|
||||
));
|
||||
});
|
||||
|
||||
test('BuildNinja flags invalid input', () {
|
||||
@@ -154,7 +158,7 @@ int main() {
|
||||
"tests": []
|
||||
}
|
||||
''';
|
||||
final BuildConfig buildConfig = BuildConfig.fromJson(
|
||||
final BuilderConfig buildConfig = BuilderConfig.fromJson(
|
||||
path: 'linux_test_config',
|
||||
map: convert.jsonDecode(invalidInput) as Map<String, Object?>,
|
||||
);
|
||||
@@ -162,9 +166,11 @@ int main() {
|
||||
expect(buildConfig.builds.length, equals(1));
|
||||
expect(buildConfig.builds[0].valid, isTrue);
|
||||
expect(buildConfig.builds[0].ninja.valid, isFalse);
|
||||
expect(buildConfig.builds[0].ninja.errors![0], equals(
|
||||
'For field "config", expected type: string, actual type: int.',
|
||||
));
|
||||
expect(
|
||||
buildConfig.builds[0].ninja.errors![0],
|
||||
equals(
|
||||
'For field "config", expected type: string, actual type: int.',
|
||||
));
|
||||
});
|
||||
|
||||
test('BuildTest flags invalid input', () {
|
||||
@@ -183,7 +189,7 @@ int main() {
|
||||
"tests": []
|
||||
}
|
||||
''';
|
||||
final BuildConfig buildConfig = BuildConfig.fromJson(
|
||||
final BuilderConfig buildConfig = BuilderConfig.fromJson(
|
||||
path: 'linux_test_config',
|
||||
map: convert.jsonDecode(invalidInput) as Map<String, Object?>,
|
||||
);
|
||||
@@ -191,9 +197,11 @@ int main() {
|
||||
expect(buildConfig.builds.length, equals(1));
|
||||
expect(buildConfig.builds[0].valid, isTrue);
|
||||
expect(buildConfig.builds[0].tests[0].valid, isFalse);
|
||||
expect(buildConfig.builds[0].tests[0].errors![0], equals(
|
||||
'For field "language", expected type: string, actual type: int.',
|
||||
));
|
||||
expect(
|
||||
buildConfig.builds[0].tests[0].errors![0],
|
||||
equals(
|
||||
'For field "language", expected type: string, actual type: int.',
|
||||
));
|
||||
});
|
||||
|
||||
test('BuildTask flags invalid input', () {
|
||||
@@ -214,7 +222,7 @@ int main() {
|
||||
"tests": []
|
||||
}
|
||||
''';
|
||||
final BuildConfig buildConfig = BuildConfig.fromJson(
|
||||
final BuilderConfig buildConfig = BuilderConfig.fromJson(
|
||||
path: 'linux_test_config',
|
||||
map: convert.jsonDecode(invalidInput) as Map<String, Object?>,
|
||||
);
|
||||
@@ -222,9 +230,11 @@ int main() {
|
||||
expect(buildConfig.builds.length, equals(1));
|
||||
expect(buildConfig.builds[0].valid, isTrue);
|
||||
expect(buildConfig.builds[0].generators[0].valid, isFalse);
|
||||
expect(buildConfig.builds[0].generators[0].errors![0], equals(
|
||||
'For field "name", expected type: string, actual type: int.',
|
||||
));
|
||||
expect(
|
||||
buildConfig.builds[0].generators[0].errors![0],
|
||||
equals(
|
||||
'For field "name", expected type: string, actual type: int.',
|
||||
));
|
||||
});
|
||||
|
||||
test('BuildArchive flags invalid input', () {
|
||||
@@ -243,7 +253,7 @@ int main() {
|
||||
"tests": []
|
||||
}
|
||||
''';
|
||||
final BuildConfig buildConfig = BuildConfig.fromJson(
|
||||
final BuilderConfig buildConfig = BuilderConfig.fromJson(
|
||||
path: 'linux_test_config',
|
||||
map: convert.jsonDecode(invalidInput) as Map<String, Object?>,
|
||||
);
|
||||
@@ -251,9 +261,11 @@ int main() {
|
||||
expect(buildConfig.builds.length, equals(1));
|
||||
expect(buildConfig.builds[0].valid, isTrue);
|
||||
expect(buildConfig.builds[0].archives[0].valid, isFalse);
|
||||
expect(buildConfig.builds[0].archives[0].errors![0], equals(
|
||||
'For field "name", expected type: string, actual type: int.',
|
||||
));
|
||||
expect(
|
||||
buildConfig.builds[0].archives[0].errors![0],
|
||||
equals(
|
||||
'For field "name", expected type: string, actual type: int.',
|
||||
));
|
||||
});
|
||||
|
||||
test('GlobalTest flags invalid input', () {
|
||||
@@ -266,16 +278,18 @@ int main() {
|
||||
]
|
||||
}
|
||||
''';
|
||||
final BuildConfig buildConfig = BuildConfig.fromJson(
|
||||
final BuilderConfig buildConfig = BuilderConfig.fromJson(
|
||||
path: 'linux_test_config',
|
||||
map: convert.jsonDecode(invalidInput) as Map<String, Object?>,
|
||||
);
|
||||
expect(buildConfig.valid, isTrue);
|
||||
expect(buildConfig.tests.length, equals(1));
|
||||
expect(buildConfig.tests[0].valid, isFalse);
|
||||
expect(buildConfig.tests[0].errors![0], equals(
|
||||
'For field "name", expected type: string, actual type: int.',
|
||||
));
|
||||
expect(
|
||||
buildConfig.tests[0].errors![0],
|
||||
equals(
|
||||
'For field "name", expected type: string, actual type: int.',
|
||||
));
|
||||
});
|
||||
|
||||
test('TestTask flags invalid input', () {
|
||||
@@ -292,16 +306,18 @@ int main() {
|
||||
]
|
||||
}
|
||||
''';
|
||||
final BuildConfig buildConfig = BuildConfig.fromJson(
|
||||
final BuilderConfig buildConfig = BuilderConfig.fromJson(
|
||||
path: 'linux_test_config',
|
||||
map: convert.jsonDecode(invalidInput) as Map<String, Object?>,
|
||||
);
|
||||
expect(buildConfig.valid, isTrue);
|
||||
expect(buildConfig.tests.length, equals(1));
|
||||
expect(buildConfig.tests[0].tasks[0].valid, isFalse);
|
||||
expect(buildConfig.tests[0].tasks[0].errors![0], contains(
|
||||
'For field "name", expected type: string, actual type: int.',
|
||||
));
|
||||
expect(
|
||||
buildConfig.tests[0].tasks[0].errors![0],
|
||||
contains(
|
||||
'For field "name", expected type: string, actual type: int.',
|
||||
));
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user