| // 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(), |
| }; |
| } |
| } |