blob: d4263e423b3571195644d76a392c58b8753b78f1 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'dart:convert';
import 'dart:io' as io;
import 'package:args/command_runner.dart';
import 'package:path/path.dart' as path;
import 'environment.dart';
import 'felt_config.dart';
import 'package_lock.dart';
class GenerateBuilderJsonCommand extends Command<bool> {
@override
String get description =>
'Generates JSON for the engine_v2 builders to build and copy all artifacts, '
'compile all test bundles, and run all test suites on all platforms.';
@override
String get name => 'generate-builder-json';
@override
FutureOr<bool>? run() {
final PackageLock packageLock = PackageLock();
final FeltConfig config = FeltConfig.fromFile(
path.join(environment.webUiTestDir.path, 'felt_config.yaml')
);
final String configString = generate(config, packageLock);
final io.File configFile = io.File(path.join(
environment.flutterDirectory.path,
'ci',
'builders',
'linux_web_engine.json',
));
configFile.writeAsStringSync('$configString\n');
return true;
}
String generate(FeltConfig config, PackageLock packageLock) {
final Map<String, dynamic> outputJson = <String, dynamic>{
'_comment': 'THIS IS A GENERATED FILE. Do not edit this file directly.',
'_comment2': 'See `generate_builder_json.dart` for the generator code',
'builds': <dynamic>[
_getArtifactBuildStep(),
for (final TestBundle bundle in config.testBundles)
_getBundleBuildStep(bundle),
],
'tests': _getAllTestSteps(config.testSuites, packageLock)
};
return const JsonEncoder.withIndent(' ').convert(outputJson);
}
Map<String, dynamic> _getArtifactBuildStep() {
return <String, dynamic>{
'name': 'web_tests/artifacts',
'drone_dimensions': <String>[
'device_type=none',
'os=Linux',
'cores=32'
],
'gclient_variables': <String, dynamic>{
'download_android_deps': false,
'download_jdk': false,
'download_emsdk': true,
},
'gn': <String>[
'--web',
'--runtime-mode=release',
'--no-goma',
],
'ninja': <String, dynamic>{
'config': 'wasm_release',
'targets': <String>[
'flutter/web_sdk:flutter_web_sdk_archive'
]
},
'archives': <dynamic>[
<String, dynamic>{
'name': 'wasm_release',
'base_path': 'out/wasm_release/zip_archives/',
'type': 'gcs',
'include_paths': <String>[
'out/wasm_release/zip_archives/flutter-web-sdk.zip'
],
'realm': 'production',
}
],
'generators': <String, dynamic>{
'tasks': <dynamic>[
<String, dynamic>{
'name': 'check licenses',
'parameters': <String>[
'check-licenses'
],
'scripts': <String>[ 'flutter/lib/web_ui/dev/felt' ],
},
<String, dynamic>{
'name': 'web engine analysis',
'parameters': <String>[
'analyze'
],
'scripts': <String>[ 'flutter/lib/web_ui/dev/felt' ],
},
<String, dynamic>{
'name': 'copy artifacts for web tests',
'parameters': <String>[
'test',
'--copy-artifacts',
],
'scripts': <String>[ 'flutter/lib/web_ui/dev/felt' ],
},
]
},
};
}
Map<String, dynamic> _getBundleBuildStep(TestBundle bundle) {
return <String, dynamic>{
'name': 'web_tests/test_bundles/${bundle.name}',
'drone_dimensions': <String>[
'device_type=none',
'os=Linux',
],
'generators': <String, dynamic>{
'tasks': <dynamic>[
<String, dynamic>{
'name': 'compile bundle ${bundle.name}',
'parameters': <String>[
'test',
'--compile',
'--bundle=${bundle.name}',
],
'scripts': <String>[ 'flutter/lib/web_ui/dev/felt' ],
}
]
},
};
}
Iterable<dynamic> _getAllTestSteps(List<TestSuite> suites, PackageLock packageLock) {
return <dynamic>[
_getTestStepForPlatformAndBrowser(suites, packageLock, 'Linux', BrowserName.chrome),
_getTestStepForPlatformAndBrowser(suites, packageLock, 'Linux', BrowserName.firefox),
_getTestStepForPlatformAndBrowser(suites, packageLock, 'Mac', BrowserName.safari, specificOS: 'Mac-13', cpu: 'arm64'),
_getTestStepForPlatformAndBrowser(suites, packageLock, 'Windows', BrowserName.chrome)
];
}
Map<String, dynamic> _getTestStepForPlatformAndBrowser(
List<TestSuite> suites,
PackageLock packageLock,
String platform,
BrowserName browser, {
String? specificOS,
String? cpu,
}) {
final filteredSuites = suites.where((suite) => suite.runConfig.browser == browser);
final bundles = filteredSuites.map((suite) => suite.testBundle).toSet();
return <String, dynamic>{
'name': '$platform run ${browser.name} suites',
'recipe': 'engine_v2/tester_engine',
'drone_dimensions': <String>[
'device_type=none',
'os=${specificOS ?? platform}',
if (cpu != null) 'cpu=$cpu',
],
'gclient_variables': <String, dynamic>{
'download_android_deps': false,
'download_jdk': false,
},
'dependencies': <String>[
'web_tests/artifacts',
...bundles.map((bundle) => 'web_tests/test_bundles/${bundle.name}'),
],
'test_dependencies': <dynamic>[
<String, dynamic>{
'dependency': 'goldctl',
'version': 'git_revision:720a542f6fe4f92922c3b8f0fdcc4d2ac6bb83cd',
},
if (browser == BrowserName.chrome)
<String, dynamic>{
'dependency': 'chrome_and_driver',
'version': packageLock.chromeLock.version,
},
if (browser == BrowserName.firefox)
<String, dynamic>{
'dependency': 'firefox',
'version': 'version:${packageLock.firefoxLock.version}',
}
],
'tasks': filteredSuites.map((suite) => <String, dynamic> {
'name': 'run suite ${suite.name}',
'parameters': <String>[
'test',
'--run',
'--suite=${suite.name}',
],
'script': 'flutter/lib/web_ui/dev/felt',
}).toList(),
};
}
}