mirror of
https://github.com/flutter/packages.git
synced 2025-07-04 09:38:17 +08:00
[pigeon] Validate generated files in CI (#3224)
* Add autoformatting option to generation * Extract to helper * Add validation * Test change to demonstrate behavior * Actually fail when validation fails * Revert "Test change to demonstrate behavior" This reverts commit 7c47d56a6d6b5892b41977df64dab377c5cdd701.
This commit is contained in:
@ -12,19 +12,47 @@
|
|||||||
|
|
||||||
import 'dart:io' show Platform, exit;
|
import 'dart:io' show Platform, exit;
|
||||||
|
|
||||||
|
import 'package:args/args.dart';
|
||||||
import 'package:path/path.dart' as p;
|
import 'package:path/path.dart' as p;
|
||||||
|
|
||||||
import 'shared/generation.dart';
|
import 'shared/generation.dart';
|
||||||
|
|
||||||
|
const String _helpFlag = 'help';
|
||||||
|
const String _formatFlag = 'format';
|
||||||
|
|
||||||
Future<void> main(List<String> args) async {
|
Future<void> main(List<String> args) async {
|
||||||
|
final ArgParser parser = ArgParser()
|
||||||
|
..addFlag(_formatFlag, abbr: 'f', help: 'Autoformats after generation.')
|
||||||
|
..addFlag(_helpFlag,
|
||||||
|
negatable: false, abbr: 'h', help: 'Print this reference.');
|
||||||
|
|
||||||
|
final ArgResults argResults = parser.parse(args);
|
||||||
|
if (argResults.wasParsed(_helpFlag)) {
|
||||||
|
print('''
|
||||||
|
usage: dart run tool/generate.dart [options]
|
||||||
|
|
||||||
|
${parser.usage}''');
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
final String baseDir = p.dirname(p.dirname(Platform.script.toFilePath()));
|
final String baseDir = p.dirname(p.dirname(Platform.script.toFilePath()));
|
||||||
|
|
||||||
print('Generating platform_test/ output...');
|
print('Generating platform_test/ output...');
|
||||||
final int exitCode = await generatePigeons(baseDir: baseDir);
|
final int generateExitCode = await generatePigeons(baseDir: baseDir);
|
||||||
if (exitCode == 0) {
|
if (generateExitCode == 0) {
|
||||||
print('Generation complete!');
|
print('Generation complete!');
|
||||||
} else {
|
} else {
|
||||||
print('Generation failed; see above for errors.');
|
print('Generation failed; see above for errors.');
|
||||||
|
exit(generateExitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argResults.wasParsed(_formatFlag)) {
|
||||||
|
print('Formatting generated output...');
|
||||||
|
final int formatExitCode =
|
||||||
|
await formatAllFiles(repositoryRoot: p.dirname(p.dirname(baseDir)));
|
||||||
|
if (formatExitCode != 0) {
|
||||||
|
print('Formatting failed; see above for errors.');
|
||||||
|
exit(formatExitCode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
exit(exitCode);
|
|
||||||
}
|
}
|
||||||
|
@ -9,8 +9,11 @@
|
|||||||
///
|
///
|
||||||
/// For any use other than CI, use test.dart instead.
|
/// For any use other than CI, use test.dart instead.
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
import 'dart:io' show Platform, exit;
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:path/path.dart' as p;
|
||||||
|
|
||||||
|
import 'shared/generation.dart';
|
||||||
import 'shared/test_runner.dart';
|
import 'shared/test_runner.dart';
|
||||||
import 'shared/test_suites.dart';
|
import 'shared/test_suites.dart';
|
||||||
|
|
||||||
@ -29,6 +32,77 @@ void _validateTestCoverage(List<List<String>> shards) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _validateGeneratedTestFiles() async {
|
||||||
|
final String baseDir = p.dirname(p.dirname(Platform.script.toFilePath()));
|
||||||
|
final String repositoryRoot = p.dirname(p.dirname(baseDir));
|
||||||
|
final String relativePigeonPath = p.relative(baseDir, from: repositoryRoot);
|
||||||
|
|
||||||
|
print('Validating generated files:');
|
||||||
|
print(' Generating output...');
|
||||||
|
final int generateExitCode = await generatePigeons(baseDir: baseDir);
|
||||||
|
if (generateExitCode != 0) {
|
||||||
|
print('Generation failed; see above for errors.');
|
||||||
|
exit(generateExitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
print(' Formatting output...');
|
||||||
|
final int formatExitCode =
|
||||||
|
await formatAllFiles(repositoryRoot: repositoryRoot);
|
||||||
|
if (formatExitCode != 0) {
|
||||||
|
print('Formatting failed; see above for errors.');
|
||||||
|
exit(formatExitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
print(' Checking for changes...');
|
||||||
|
final List<String> modifiedFiles = await _modifiedFiles(
|
||||||
|
repositoryRoot: repositoryRoot, relativePigeonPath: relativePigeonPath);
|
||||||
|
|
||||||
|
if (modifiedFiles.isEmpty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
print('The following files are not updated, or not formatted correctly:');
|
||||||
|
modifiedFiles.map((String line) => ' $line').forEach(print);
|
||||||
|
|
||||||
|
print('\nTo fix run "dart run tool/generate.dart --format" from the pigeon/ '
|
||||||
|
'directory, or apply the diff with the command below.\n');
|
||||||
|
|
||||||
|
final ProcessResult diffResult = await Process.run(
|
||||||
|
'git',
|
||||||
|
<String>['diff', relativePigeonPath],
|
||||||
|
workingDirectory: repositoryRoot,
|
||||||
|
);
|
||||||
|
if (diffResult.exitCode != 0) {
|
||||||
|
print('Unable to determine diff.');
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
print('patch -p1 <<DONE');
|
||||||
|
print(diffResult.stdout);
|
||||||
|
print('DONE');
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<String>> _modifiedFiles(
|
||||||
|
{required String repositoryRoot,
|
||||||
|
required String relativePigeonPath}) async {
|
||||||
|
final ProcessResult result = await Process.run(
|
||||||
|
'git',
|
||||||
|
<String>['ls-files', '--modified', relativePigeonPath],
|
||||||
|
workingDirectory: repositoryRoot,
|
||||||
|
);
|
||||||
|
if (result.exitCode != 0) {
|
||||||
|
print('Unable to determine changed files.');
|
||||||
|
print(result.stdout);
|
||||||
|
print(result.stderr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
return (result.stdout as String)
|
||||||
|
.split('\n')
|
||||||
|
.map((String line) => line.trim())
|
||||||
|
.where((String line) => line.isNotEmpty)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> main(List<String> args) async {
|
Future<void> main(List<String> args) async {
|
||||||
// Run most tests on Linux, since Linux tends to be the easiest and cheapest.
|
// Run most tests on Linux, since Linux tends to be the easiest and cheapest.
|
||||||
const List<String> linuxHostTests = <String>[
|
const List<String> linuxHostTests = <String>[
|
||||||
@ -85,6 +159,14 @@ Future<void> main(List<String> args) async {
|
|||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
// Ensure that all generated files are up to date. This is run only on Linux
|
||||||
|
// both to avoid duplication of work, and to avoid issues if different CI
|
||||||
|
// configurations have different setups (e.g., different clang-format versions
|
||||||
|
// or no clang-format at all).
|
||||||
|
if (Platform.isLinux) {
|
||||||
|
await _validateGeneratedTestFiles();
|
||||||
|
}
|
||||||
|
|
||||||
final List<String> testsToRun;
|
final List<String> testsToRun;
|
||||||
if (Platform.isMacOS) {
|
if (Platform.isMacOS) {
|
||||||
if (Platform.environment['LUCI_CI'] != null) {
|
if (Platform.environment['LUCI_CI'] != null) {
|
||||||
|
@ -2,9 +2,13 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'dart:io' show Platform;
|
||||||
|
|
||||||
import 'package:path/path.dart' as p;
|
import 'package:path/path.dart' as p;
|
||||||
import 'package:pigeon/pigeon.dart';
|
import 'package:pigeon/pigeon.dart';
|
||||||
|
|
||||||
|
import 'process_utils.dart';
|
||||||
|
|
||||||
enum GeneratorLanguages {
|
enum GeneratorLanguages {
|
||||||
cpp,
|
cpp,
|
||||||
java,
|
java,
|
||||||
@ -166,3 +170,23 @@ Future<int> runPigeon({
|
|||||||
swiftOptions: const SwiftOptions(),
|
swiftOptions: const SwiftOptions(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Runs the repository tooling's format command on this package.
|
||||||
|
///
|
||||||
|
/// This is intended for formatting generated autoput, but since there's no
|
||||||
|
/// way to filter to specific files in with the repo tooling it runs over the
|
||||||
|
/// entire package.
|
||||||
|
Future<int> formatAllFiles({required String repositoryRoot}) {
|
||||||
|
final String dartCommand = Platform.isWindows ? 'dart.exe' : 'dart';
|
||||||
|
return runProcess(
|
||||||
|
dartCommand,
|
||||||
|
<String>[
|
||||||
|
'run',
|
||||||
|
'script/tool/bin/flutter_plugin_tools.dart',
|
||||||
|
'format',
|
||||||
|
'--packages=pigeon',
|
||||||
|
],
|
||||||
|
streamOutput: false,
|
||||||
|
workingDirectory: repositoryRoot,
|
||||||
|
logFailure: true);
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user