Testing is complete!! And a nice build runner script to boot
This commit is contained in:
@@ -0,0 +1,178 @@
|
||||
// ignore_for_file: avoid_print
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
const packages = ['backend', 'frontend', 'shared_models'];
|
||||
Map<int, Process> runnerWatchProcesses = {};
|
||||
|
||||
void main(List<String> args) async {
|
||||
// Get args and create bool for if `--watch` passed in
|
||||
final watch = args.contains('--watch');
|
||||
|
||||
if (watch) {
|
||||
print('👀 Running build_runner in watch mode for all packages...\n');
|
||||
} else {
|
||||
print('🏃 Running build_runner in build mode for all packages...\n');
|
||||
}
|
||||
|
||||
final projectRootPath = await Process.run(
|
||||
'git',
|
||||
['rev-parse', '--show-toplevel'],
|
||||
).then((result) => result.stdout.toString().trim());
|
||||
|
||||
for (final package in packages) {
|
||||
unawaited(runBuildRunner('$projectRootPath/$package', watch: watch));
|
||||
}
|
||||
await Future<void>.delayed(const Duration(seconds: 1));
|
||||
|
||||
var i = 0;
|
||||
var j = 0;
|
||||
while (runnerWatchProcesses.isNotEmpty) {
|
||||
await Future<void>.delayed(const Duration(seconds: 1));
|
||||
i++;
|
||||
|
||||
if (i == 10) {
|
||||
if (!watch) print(' Waiting for build to finish... ${runnerWatchProcesses.keys}');
|
||||
if (packages.length != runnerWatchProcesses.entries.length) {
|
||||
j++;
|
||||
} else {
|
||||
j = 0;
|
||||
}
|
||||
if (j == 2) {
|
||||
print(
|
||||
'Missing build runners for too long in tracked processes. Something probably went wrong. Check logs and fix the script.',
|
||||
);
|
||||
exitRunners();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
print('\n✅ All build_runner tasks completed successfully!');
|
||||
}
|
||||
|
||||
Future<void> runBuildRunner(String packagePath, {required bool watch}) async {
|
||||
final package = packagePath.split('/').last;
|
||||
print('📦 Starting build_runner for $package...');
|
||||
Future<(Process, bool)> buildRunnerFunc() => watch ? _runBuildRunnerWatch(packagePath) : _runBuildRunner(packagePath);
|
||||
const maxAttempts = 5;
|
||||
|
||||
Future<void> attemptRecover(Object? e, int i) async {
|
||||
try {
|
||||
print('\n⚠️ Error in $package:\n$e\nAttempting recovery (${i + 1} / $maxAttempts)...\n');
|
||||
|
||||
print(' Waiting 10 seconds before retry...');
|
||||
await Future<void>.delayed(const Duration(seconds: 1));
|
||||
|
||||
// Recovery attempt
|
||||
print(' Running pub get...');
|
||||
await Process.run(
|
||||
package == 'frontend' ? 'flutter' : 'dart',
|
||||
['pub', 'get'],
|
||||
workingDirectory: packagePath,
|
||||
);
|
||||
|
||||
print(' Retrying build_runner...');
|
||||
return;
|
||||
} catch (e) {
|
||||
print('Error while trying to recover $package: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Object? err;
|
||||
for (var i = 0; i < maxAttempts; i++) {
|
||||
try {
|
||||
final (process, needsRestart) = await buildRunnerFunc();
|
||||
final removed = runnerWatchProcesses.remove(process.pid);
|
||||
assert(removed != null, true);
|
||||
if (needsRestart) {
|
||||
await attemptRecover(process.stderr, i);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
await attemptRecover(e, i);
|
||||
}
|
||||
}
|
||||
print('\n❌ Failed to recover $packagePath: $err');
|
||||
exitRunners();
|
||||
}
|
||||
|
||||
Future<(Process, bool)> _runBuildRunner(String package) async {
|
||||
final process = await Process.start(
|
||||
'dart',
|
||||
['run', 'build_runner', 'build', '--delete-conflicting-outputs'],
|
||||
workingDirectory: package,
|
||||
);
|
||||
|
||||
runnerWatchProcesses.addAll({process.pid: process});
|
||||
|
||||
final outputLines = <String>[];
|
||||
final errorLines = <String>[];
|
||||
|
||||
process.stdout.transform(const SystemEncoding().decoder).listen(outputLines.add);
|
||||
|
||||
process.stderr.transform(const SystemEncoding().decoder).listen(errorLines.add);
|
||||
|
||||
final exitCode = await process.exitCode;
|
||||
|
||||
if (exitCode != 0) {
|
||||
// Print filtered error output
|
||||
final relevantErrors = errorLines
|
||||
.where((line) => line.contains('ERROR') || line.contains('Exception') || line.contains('Failed'))
|
||||
.join('\n');
|
||||
|
||||
print('Build runner failed for $package:\n$relevantErrors');
|
||||
return (process, true);
|
||||
}
|
||||
|
||||
// Print success with minimal output
|
||||
final successMessage =
|
||||
outputLines.where((line) => line.contains('Succeeded') || line.contains('Generated')).join('\n').trim();
|
||||
|
||||
print(' ${successMessage.isEmpty ? "Completed successfully" : successMessage}');
|
||||
return (process, false);
|
||||
}
|
||||
|
||||
Future<(Process, bool)> _runBuildRunnerWatch(String packagePath) async {
|
||||
final package = packagePath.split('/').last;
|
||||
final process = await Process.start(
|
||||
'dart',
|
||||
['run', 'build_runner', 'watch', '--delete-conflicting-outputs'],
|
||||
workingDirectory: packagePath,
|
||||
);
|
||||
|
||||
runnerWatchProcesses.addAll({process.pid: process});
|
||||
|
||||
var restart = false;
|
||||
process.stdout.transform(const SystemEncoding().decoder).listen((line) {
|
||||
if (line.contains('Succeeded') || line.contains('Generated')) {
|
||||
print('🎯 [${package.toUpperCase()}] - ${line.trim()}');
|
||||
}
|
||||
if (line.contains('SEVERE')) {
|
||||
print('🚩 [${package.toUpperCase()}] - ${line.trim()}');
|
||||
restart = true;
|
||||
}
|
||||
});
|
||||
|
||||
process.stderr.transform(const SystemEncoding().decoder).listen((line) {
|
||||
if (line.contains('ERROR') || line.contains('Exception') || line.contains('Failed')) {
|
||||
print('🎯 [${package.toUpperCase()}] - ${line.trim()}');
|
||||
restart = true;
|
||||
}
|
||||
});
|
||||
|
||||
final code = await process.exitCode;
|
||||
if (!restart) {
|
||||
restart = code != 0;
|
||||
}
|
||||
return (process, restart);
|
||||
}
|
||||
|
||||
void exitRunners() {
|
||||
print('❌ Killing processes');
|
||||
for (final pEntry in runnerWatchProcesses.entries) {
|
||||
pEntry.value.kill();
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
Reference in New Issue
Block a user