From 6176d0de3ebf9815a3ab0b25f1c77f6b534abd57 Mon Sep 17 00:00:00 2001 From: Eric Windmill Date: Wed, 4 Feb 2026 10:54:41 -0800 Subject: [PATCH] checkin' --- tool/ci_with_channel.dart | 137 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 tool/ci_with_channel.dart diff --git a/tool/ci_with_channel.dart b/tool/ci_with_channel.dart new file mode 100644 index 000000000..47a39f16d --- /dev/null +++ b/tool/ci_with_channel.dart @@ -0,0 +1,137 @@ +import 'dart:io'; +import 'package:args/args.dart'; +import 'package:path/path.dart' as path; +import 'package:yaml/yaml.dart'; + +/// Do not use this with GitHub Actions. It is a convenience script for running +/// CI locally. +/// +/// Usage: dart tool/ci_with_channel.dart -c stable,beta + +Future main(List args) async { + final parser = ArgParser() + ..addFlag( + 'help', + abbr: 'h', + negatable: false, + help: 'Print this usage information.', + ) + ..addOption( + 'channels', + abbr: 'c', + help: + 'Comma-separated list of channels to run on (e.g., stable,beta,main)', + ); + + final results = parser.parse(args); + + if (results['help'] as bool) { + print(parser.usage); + return; + } + + final channelsArg = results['channels'] as String?; + + List channels; + if (channelsArg != null) { + channels = channelsArg.split(',').map((c) => c.trim()).toList(); + } else { + // Default to current channel if none specified + channels = []; + } + + final rootDir = Directory.current; + final originalChannel = await _getCurrentChannel(); + + try { + if (channels.isEmpty) { + print('Running on current channel: $originalChannel'); + await _runCI(rootDir); + } else { + for (final channel in channels) { + print('\n=== Switching to channel: $channel ==='); + await _runCommand('flutter', ['channel', channel]); + await _runCommand('flutter', ['doctor']); + await _runCI(rootDir); + } + } + } finally { + if (channels.isNotEmpty && originalChannel != null) { + print('\n=== Switching back to original channel: $originalChannel ==='); + await _runCommand('flutter', ['channel', originalChannel]); + } + } +} + +Future _getCurrentChannel() async { + final result = await Process.run('flutter', ['channel']); + if (result.exitCode != 0) { + return null; + } + final output = result.stdout as String; + final match = RegExp(r'\* (\w+)').firstMatch(output); + return match?.group(1); +} + +Future _runCI(Directory rootDir) async { + final pubspecFile = File(path.join(rootDir.path, 'pubspec.yaml')); + final pubspecContent = await pubspecFile.readAsString(); + final pubspecYaml = loadYaml(pubspecContent); + + final workspace = pubspecYaml['workspace'] as YamlList?; + if (workspace == null) { + print('No workspace found in pubspec.yaml'); + exit(1); + } + + // pub workspace, only run 'get' once + await _runCommand('flutter', ['pub', 'get'], workingDirectory: rootDir.path); + + final packages = workspace.map((e) => e.toString()).toList(); + + for (final package in packages) { + final packagePath = path.join(rootDir.path, package); + print('== Testing \'$package\' =='); + await _runCommand('dart', [ + 'analyze', + '--fatal-infos', + '--fatal-warnings', + ], workingDirectory: packagePath); + + await _runCommand('dart', ['format', '.'], workingDirectory: packagePath); + + if (await Directory(path.join(packagePath, 'test')).exists()) { + final packagePubspecFile = File(path.join(packagePath, 'pubspec.yaml')); + final packagePubspecContent = await packagePubspecFile.readAsString(); + if (packagePubspecContent.contains('flutter:')) { + await _runCommand('flutter', [ + 'test', + '--no-pub', + ], workingDirectory: packagePath); + } else { + await _runCommand('dart', ['test'], workingDirectory: packagePath); + } + } + } +} + +Future _runCommand( + String executable, + List arguments, { + String? workingDirectory, +}) async { + final process = await Process.start( + executable, + arguments, + workingDirectory: workingDirectory, + runInShell: true, + mode: ProcessStartMode.inheritStdio, + ); + final exitCode = await process.exitCode; + if (exitCode != 0) { + print( + 'Command "$executable ${arguments.join(' ')}" failed with exit code $exitCode in $workingDirectory', + ); + exit(exitCode); + } +}