pull/2701/head
Eric Windmill 1 month ago
parent b023fdabcb
commit b23c073be5

@ -1,32 +0,0 @@
# Changelog
The purpose of this changelog is to track the freshness of samples and which
samples reflect *current best practices*. It describes **human-made, significant
** changes made to the repository or samples in the repository.
While all samples in this repository build and run, some of them were written
long ago, and no longer reflect what we want developers to learn. For example,
samples should have been refactored when Dart 3 released to include patterns and
records, where appropriate.
* **DO include:**
* The addition of new samples.
* The removal of existing samples.
* Considerable refactoring of any given sample.
* **DO NOT include:**
* Simple changes that reflect minor version bumps in Flutter. For example,
in a recent Flutter update, `Color.red` became `Color.r`.
* Dependency updates.
* Bug fixes.
* Any changes made to simply 'keep the lights on'.
# Log
| DATE (YYYY-MM-DD) | Sample(s) | author | Changes |
|-------------------|-------------------|--------------|-----------------------------------------------|
| NEXT GOES HERE | | | |
| | | | |
| 2024-12-04 | N/A - repo change | ericwindmill | Added changelog |
| 2024-11-27 | fake_sample | ericwindmill | Refactored fake_sample to use Dart 3 features |
| 2020-04-17 | fake_sample | ericwindmill | Created fake_sample |

@ -2,7 +2,7 @@ include: package:flutter_lints/flutter.yaml
formatter:
trailing_commas: preserve
page_width: 75
page_width: 79
analyzer:
language:

@ -1,31 +0,0 @@
# This file configures the static analysis results for your project (errors,
# warnings, and lints).
#
# This enables the 'recommended' set of lints from `package:lints`.
# This set helps identify many issues that may lead to problems when running
# or consuming Dart code, and enforces writing Dart using a single, idiomatic
# style and format.
#
# If you want a smaller set of lints you can change this to specify
# 'package:lints/core.yaml'. These are just the most critical lints
# (the recommended set includes the core lints).
# The core lints are also what is used by pub.dev for scoring packages.
include: package:analysis_defaults/flutter.yaml
# Uncomment the following section to specify additional rules.
# linter:
# rules:
# - camel_case_types
# analyzer:
# exclude:
# - path/to/excluded/files/**
# For more information about the core and recommended set of lints, see
# https://dart.dev/go/core-lints
# For additional information about configuring this file, see
# https://dart.dev/guides/language/analysis-options

@ -47,18 +47,3 @@ You are an AI assistant tasked with keeping a repository of Flutter projects up-
Please proceed with this task.
Next:
- Run the CLI command `flutter channel beta` to ensure the Flutter SDK on my machine is using the latest beta
- Run the CI running the bash file @/tool/flutter_ci_script_stable.sh
- When there's a non-0 response, attempt to fix the issue.
- remove samples and replace with a README
- Update script to look into sub-directories. Because some projects are themselves mono repos.
- Make sure this is in every pubspec yaml
analysis_defaults:
path: ../analysis_defaults
- shouldn't run flutter-test unless theirs a test dir

@ -8,322 +8,307 @@ import 'package:yaml_edit/yaml_edit.dart';
const String logDir = 'logs';
late File _logFile;
void main(List<String> arguments) async {
final parser = ArgParser()
..addFlag('dry-run',
negatable: false,
help:
'Prints the commands that would be executed, but does not run them.');
final argResults = parser.parse(arguments);
final isDryRun = argResults['dry-run'] as bool;
setupLogging();
log(
styleBold
.wrap('Flutter Monorepo Update Script Started: ${DateTime.now()}')!,
stdout);
log(blue.wrap('Log file: ${_logFile.path}')!, stdout);
if (isDryRun) {
log(yellow.wrap('--- DRY RUN MODE ---')!, stdout);
}
final runner = ReleaseScriptRunner();
await runner.run(arguments);
}
if (!await isFlutterInstalled()) {
log(red.wrap('Flutter is not installed or not in PATH')!, stderr);
exit(1);
}
class ReleaseScriptRunner {
late final File _logFile;
bool _isDryRun = false;
// log(styleBold.wrap('\n=========================================')!, stdout);
// log(styleBold.wrap('Upgrading Flutter SDK')!, stdout);
// log(styleBold.wrap('=========================================')!, stdout);
// final (didFlutterUpgrade, _) =
// await runCommand('flutter', ['upgrade'], isDryRun: isDryRun);
// if (!didFlutterUpgrade) {
// log(red.wrap('Failed to upgrade Flutter SDK')!, stderr);
// exit(1);
// }
// log(styleBold.wrap('\n=========================================')!, stdout);
// log(styleBold.wrap('Resolving workspace dependencies')!, stdout);
// log(styleBold.wrap('=========================================')!, stdout);
// final (didPubUpgrade, _) =
// await runCommand('flutter', ['pub', 'upgrade'], isDryRun: isDryRun);
// if (!didPubUpgrade) {
// log(red.wrap('Failed to upgrade workspace dependencies'), stderr);
// exit(1);
// }
// final (didPubGet, _) =
// await runCommand('flutter', ['pub', 'get'], isDryRun: isDryRun);
// if (!didPubGet) {
// log(red.wrap('Failed to get workspace dependencies'), stderr);
// exit(1);
// }
final dartVersion = await getDartVersion();
if (dartVersion == null) {
log(red.wrap('Failed to get Dart SDK version.'), stderr);
exit(1);
}
log(blue.wrap('Using Dart SDK version: $dartVersion'), stdout);
Future<void> run(List<String> arguments) async {
final parser = ArgParser()
..addFlag('dry-run',
negatable: false,
help:
'Prints the commands that would be executed, but does not run them.');
final argResults = parser.parse(arguments);
_isDryRun = argResults['dry-run'] as bool;
_setupLogging();
final packages = await getWorkspacePackages();
if (packages.isEmpty) {
log(yellow.wrap('No packages found in the root pubspec.yaml workspace.'),
log(
styleBold
.wrap('Flutter Monorepo Update Script Started: ${DateTime.now()}'),
stdout);
exit(0);
}
log(blue.wrap('Log file: ${_logFile.path}')!, stdout);
log(
blue.wrap(
'Found ${packages.length} Flutter project(s): ${packages.join(', ')}'),
stdout);
if (_isDryRun) {
log(yellow.wrap('--- DRY RUN MODE ---')!, stdout);
}
final failedProjects = <String>[];
for (final packagePath in packages) {
final success = await processProject(packagePath, dartVersion, isDryRun);
if (!success) {
failedProjects.add(packagePath);
if (!await _isFlutterInstalled()) {
log(red.wrap('Flutter is not installed or not in PATH')!, stderr);
exit(1);
}
}
printSummary(packages.length, failedProjects);
final dartVersion = await _getDartVersion();
if (dartVersion == null) {
log(red.wrap('Failed to get Dart SDK version.'), stderr);
exit(1);
}
log(blue.wrap('Using Dart SDK version: $dartVersion'), stdout);
log(
styleBold.wrap(
'\nFlutter Monorepo Update Script Completed: ${DateTime.now()}'),
stdout);
final packages = await _getWorkspacePackages();
if (packages.isEmpty) {
log(yellow.wrap('No packages found in the root pubspec.yaml workspace.'),
stdout);
exit(0);
}
if (failedProjects.isNotEmpty) {
exit(1);
}
}
log(
blue.wrap(
'Found ${packages.length} Flutter project(s): ${packages.join(', ')}'),
stdout);
void setupLogging() {
final logsDir = Directory(logDir);
if (!logsDir.existsSync()) {
logsDir.createSync(recursive: true);
}
final timestamp = DateTime.now().toIso8601String().replaceAll(':', '-');
_logFile = File(p.join(logDir, 'release_logs_$timestamp.log'));
}
final failedProjects = <String>[];
for (final packagePath in packages) {
final success = await _processProject(packagePath, dartVersion);
if (!success) {
failedProjects.add(packagePath);
}
}
void log(String? message, IOSink sink) {
if (message == null) return;
sink.writeln(message);
}
_printSummary(packages.length, failedProjects);
void logToFile(String? message) {
if (message == null) return;
_logFile.writeAsStringSync(
'\n${stripAnsiCodes(message)}',
mode: FileMode.append,
);
}
log(
styleBold.wrap(
'\nFlutter Monorepo Update Script Completed: ${DateTime.now()}'),
stdout);
Future<bool> isFlutterInstalled() async {
try {
final result = await Process.run('flutter', ['--version']);
return result.exitCode == 0;
} catch (e) {
return false;
if (failedProjects.isNotEmpty) {
exit(1);
}
}
}
Future<String?> getDartVersion() async {
try {
final result = await Process.run('flutter', ['--version', '--machine']);
if (result.exitCode == 0) {
final json = loadYaml(result.stdout as String) as YamlMap;
final fullDartVersion = json['dartSdkVersion'] as String?;
if (fullDartVersion != null) {
return fullDartVersion.split(' ').first;
}
return null;
void _setupLogging() {
final logsDir = Directory(logDir);
if (!logsDir.existsSync()) {
logsDir.createSync(recursive: true);
}
} catch (e) {
log(red.wrap('Error getting Dart SDK version: $e'), stderr);
final timestamp = DateTime.now().toIso8601String().replaceAll(':', '-');
_logFile = File(p.join(logDir, 'release_logs_$timestamp.log'));
}
return null;
}
Future<List<String>> getWorkspacePackages() async {
final rootPubspec = File('pubspec.yaml');
if (!rootPubspec.existsSync()) {
log(red.wrap('Root pubspec.yaml not found!'), stderr);
return [];
void log(String? message, IOSink sink) {
if (message == null) return;
sink.writeln(message);
}
try {
final content = await rootPubspec.readAsString();
final yaml = loadYaml(content) as YamlMap;
final workspace = yaml['workspace'] as YamlList?;
if (workspace != null) {
return workspace.nodes.map((node) => node.value as String).toList();
}
} catch (e) {
log(red.wrap('Error reading workspace packages: $e'), stderr);
void logToFile(String? message) {
if (message == null) return;
_logFile.writeAsStringSync(
'\n${_stripAnsiCodes(message)}',
mode: FileMode.append,
);
}
return [];
}
Future<bool> processProject(
String projectPath, String dartVersion, bool isDryRun) async {
final projectName = p.basename(projectPath);
final projectDir = Directory(projectPath);
final issues = [];
if (!projectDir.existsSync()) {
log(red.wrap('Project directory not found: $projectPath'), stderr);
return false;
Future<bool> _isFlutterInstalled() async {
try {
final result = await Process.run('flutter', ['--version']);
return result.exitCode == 0;
} catch (e) {
return false;
}
}
// For stdout
log(styleBold.wrap('\n========================================='), stdout);
log(styleBold.wrap('Processing project: $projectName'), stdout);
log(styleBold.wrap('=========================================')!, stdout);
log(blue.wrap('Updating SDK constraints to use Dart $dartVersion'), stdout);
if (!isDryRun) {
if (!await updateSdkConstraints(projectPath, dartVersion)) {
log(red.wrap('Failed to update SDK constraints for $projectName'),
stderr);
return false;
Future<String?> _getDartVersion() async {
try {
final result = await Process.run('flutter', ['--version', '--machine']);
if (result.exitCode == 0) {
final json = loadYaml(result.stdout as String) as YamlMap;
final fullDartVersion = json['dartSdkVersion'] as String?;
if (fullDartVersion != null) {
return fullDartVersion.split(' ').first;
}
return null;
}
} catch (e) {
log(red.wrap('Error getting Dart SDK version: $e'), stderr);
}
return null;
}
final commands = [
Command('dart analyze', 'Running dart analyze...', 'dart',
['analyze', '--fatal-infos', '--fatal-warnings']),
Command('dart format', 'Running dart format...', 'dart', ['format', '.']),
];
Future<List<String>> _getWorkspacePackages() async {
final rootPubspec = File('pubspec.yaml');
if (!rootPubspec.existsSync()) {
log(red.wrap('Root pubspec.yaml not found!'), stderr);
return [];
}
final testDir = Directory(p.join(projectPath, 'test'));
if (projectName != 'material_3_demo' && testDir.existsSync()) {
commands
.add(Command('flutter test', 'Running tests...', 'flutter', ['test']));
try {
final content = await rootPubspec.readAsString();
final yaml = loadYaml(content) as YamlMap;
final workspace = yaml['workspace'] as YamlList?;
if (workspace != null) {
return workspace.nodes.map((node) => node.value as String).toList();
}
} catch (e) {
log(red.wrap('Error reading workspace packages: $e'), stderr);
}
return [];
}
for (final command in commands) {
log(blue.wrap(command.description), stdout);
Future<bool> _processProject(String projectPath, String dartVersion) async {
final projectName = p.basename(projectPath);
final projectDir = Directory(projectPath);
final issues = [];
final (didPass, output) = await runCommand(
command.executable,
command.arguments,
workingDirectory: projectPath,
isDryRun: isDryRun,
);
if (!projectDir.existsSync()) {
log(red.wrap('Project directory not found: $projectPath'), stderr);
return false;
}
if (!didPass) {
log(red.wrap('${command.displayName} failed for $projectName'), stderr);
log(styleBold.wrap('\n========================================='), stdout);
log(styleBold.wrap('Processing project: $projectName'), stdout);
log(styleBold.wrap('=========================================')!, stdout);
if (command.displayName == 'pub upgrade' ||
command.displayName == 'pub get' &&
output.contains('Failed to update packages.')) {
issues.add(output);
log(blue.wrap('Updating SDK constraints to use Dart $dartVersion'), stdout);
if (!_isDryRun) {
if (!await _updateSdkConstraints(projectPath, dartVersion)) {
log(red.wrap('Failed to update SDK constraints for $projectName'),
stderr);
return false;
}
}
if (command.displayName == 'dart analyze' &&
output.contains('issue found.') ||
output.contains('issues found.')) {
issues.add(output);
}
final commands = [
Command('dart analyze', 'Running dart analyze...', 'dart',
['analyze', '--fatal-infos', '--fatal-warnings']),
Command('dart format', 'Running dart format...', 'dart', ['format', '.']),
];
final testDir = Directory(p.join(projectPath, 'test'));
if (projectName != 'material_3_demo' && testDir.existsSync()) {
commands.add(
Command('flutter test', 'Running tests...', 'flutter', ['test']));
}
if (command.displayName == 'flutter test' &&
!output.contains('All tests passed!')) {
issues.add(output);
for (final command in commands) {
log(blue.wrap(command.description), stdout);
final (didPass, output) = await _runCommand(
command.executable,
command.arguments,
workingDirectory: projectPath,
);
if (!didPass) {
log(red.wrap('${command.displayName} failed for $projectName'), stderr);
if (command.displayName == 'pub upgrade' ||
command.displayName == 'pub get' &&
output.contains('Failed to update packages.')) {
issues.add(output);
}
if (command.displayName == 'dart analyze' &&
output.contains('issue found.') ||
output.contains('issues found.')) {
issues.add(output);
}
if (command.displayName == 'flutter test' &&
!output.contains('All tests passed!')) {
issues.add(output);
}
}
}
}
if (issues.isNotEmpty) {
logToFile('- Issues found in $projectName');
for (final issue in issues) {
if (isOnlyWhitespace(issue)) continue;
logToFile('-- $issue');
if (issues.isNotEmpty) {
logToFile('- Issues found in $projectName');
for (final issue in issues) {
if (_isOnlyWhitespace(issue)) continue;
logToFile('-- $issue');
}
}
log(green.wrap('Successfully processed $projectName'), stdout);
return true;
}
log(green.wrap('Successfully processed $projectName'), stdout);
return true;
}
Future<bool> _updateSdkConstraints(
String projectDir, String versionString) async {
final pubspecFile = File(p.join(projectDir, 'pubspec.yaml'));
if (!pubspecFile.existsSync()) {
log(red.wrap('pubspec.yaml not found in $projectDir'), stderr);
return false;
}
Future<bool> updateSdkConstraints(
String projectDir, String versionString) async {
final pubspecFile = File(p.join(projectDir, 'pubspec.yaml'));
if (!pubspecFile.existsSync()) {
log(red.wrap('pubspec.yaml not found in $projectDir'), stderr);
return false;
try {
final newConstraint = '^${versionString}-0';
final content = await pubspecFile.readAsString();
final editor = YamlEditor(content);
editor.update(['environment', 'sdk'], newConstraint);
await pubspecFile.writeAsString(editor.toString());
log(
blue.wrap(
'Updated Dart SDK constraint in $projectDir to: $newConstraint'),
stdout);
return true;
} catch (e) {
log(red.wrap('Failed to update SDK constraint in $projectDir: $e'),
stderr);
return false;
}
}
try {
final newConstraint = '^${versionString}-0';
final content = await pubspecFile.readAsString();
final editor = YamlEditor(content);
editor.update(['environment', 'sdk'], newConstraint);
Future<(bool, String)> _runCommand(String executable, List<String> arguments,
{String? workingDirectory}) async {
final commandString = '$executable ${arguments.join(' ')}';
if (_isDryRun) {
log(
yellow.wrap(
' [DRY RUN] Would execute: `$commandString` in `${workingDirectory ?? '.'}`'),
stdout);
return (true, '');
}
await pubspecFile.writeAsString(editor.toString());
log(
blue.wrap(
'Updated Dart SDK constraint in $projectDir to: $newConstraint'),
stdout);
return true;
} catch (e) {
log(red.wrap('Failed to update SDK constraint in $projectDir: $e'), stderr);
return false;
}
}
final process = await Process.start(executable, arguments,
workingDirectory: workingDirectory, runInShell: true);
Future<(bool, String)> runCommand(String executable, List<String> arguments,
{String? workingDirectory, bool isDryRun = false}) async {
final commandString = '$executable ${arguments.join(' ')}';
if (isDryRun) {
log(
yellow.wrap(
' [DRY RUN] Would execute: `$commandString` in `${workingDirectory ?? '.'}`'),
stdout);
return (true, '');
}
StringBuffer output = StringBuffer('');
final process = await Process.start(executable, arguments,
workingDirectory: workingDirectory, runInShell: true);
final stdoutFuture =
process.stdout.transform(SystemEncoding().decoder).forEach((line) {
log(line, stdout);
if (!_isOnlyWhitespace(line)) output.writeln('${line.trim().padLeft(2)}');
});
StringBuffer output = StringBuffer('');
final stderrFuture =
process.stderr.transform(SystemEncoding().decoder).forEach((line) {
log(red.wrap(line), stderr);
if (!_isOnlyWhitespace(line)) output.writeln('${line.trim().padLeft(2)}');
});
final stdoutFuture =
process.stdout.transform(SystemEncoding().decoder).forEach((line) {
log(line, stdout);
if (!isOnlyWhitespace(line)) output.writeln('${line.trim().padLeft(2)}');
});
await Future.wait([stdoutFuture, stderrFuture]);
final stderrFuture =
process.stderr.transform(SystemEncoding().decoder).forEach((line) {
log(red.wrap(line), stderr);
if (!isOnlyWhitespace(line)) output.writeln('${line.trim().padLeft(2)}');
});
return (await process.exitCode == 0, output.toString());
}
await Future.wait([stdoutFuture, stderrFuture]);
void _printSummary(int total, List<String> failed) {
log(styleBold.wrap('\n=========================================')!, stdout);
log(styleBold.wrap('Update Summary')!, stdout);
log(styleBold.wrap('=========================================')!, stdout);
log(blue.wrap('Total projects processed: $total'), stdout);
log(green.wrap('Successful: ${total - failed.length}'), stdout);
return (await process.exitCode == 0, output.toString());
}
if (failed.isNotEmpty) {
log(red.wrap('Failed: ${failed.length}'), stderr);
log(red.wrap('Failed projects: ${failed.join(', ')}'), stderr);
}
}
void printSummary(int total, List<String> failed) {
log(styleBold.wrap('\n=========================================')!, stdout);
log(styleBold.wrap('Update Summary')!, stdout);
log(styleBold.wrap('=========================================')!, stdout);
log(blue.wrap('Total projects processed: $total'), stdout);
log(green.wrap('Successful: ${total - failed.length}'), stdout);
String _stripAnsiCodes(String text) {
final ansiRegex = RegExp(r'\x1B\[[0-?]*[ -/]*[@-~]');
return text.replaceAll(ansiRegex, '');
}
if (failed.isNotEmpty) {
log(red.wrap('Failed: ${failed.length}'), stderr);
log(red.wrap('Failed projects: ${failed.join(', ')}'), stderr);
bool _isOnlyWhitespace(String text) {
return text.trim().isEmpty;
}
}
@ -335,12 +320,3 @@ class Command {
Command(this.displayName, this.description, this.executable, this.arguments);
}
String stripAnsiCodes(String text) {
final ansiRegex = RegExp(r'\x1B\[[0-?]*[ -/]*[@-~]');
return text.replaceAll(ansiRegex, '');
}
bool isOnlyWhitespace(String text) {
return text.trim().isEmpty;
}

@ -1,267 +0,0 @@
#!/bin/bash
set -e
# Configuration
LOGS_DIR="logs"
LOG_FILE="$LOGS_DIR/flutter_update_$(date +%Y-%m-%d_%H-%M-%S).log"
TEMP_LOG="/tmp/flutter_temp_$$.log"
# Create logs directory if it doesn't exist
mkdir -p "$LOGS_DIR"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Logging function
log() {
echo -e "$1" | tee -a "$LOG_FILE"
}
log_error() {
echo -e "${RED}ERROR: $1${NC}" | tee -a "$LOG_FILE"
}
log_warning() {
echo -e "${YELLOW}WARNING: $1${NC}" | tee -a "$LOG_FILE"
}
log_info() {
echo -e "${BLUE}INFO: $1${NC}" | tee -a "$LOG_FILE"
}
# Function to check if directory is a Flutter project
is_flutter_project() {
local dir="$1"
[[ -f "$dir/pubspec.yaml" ]] && grep -q "flutter:" "$dir/pubspec.yaml"
}
# Function to get current Flutter version
get_flutter_version() {
flutter --version --machine | grep '"frameworkVersion"' | cut -d'"' -f4
}
# Function to update SDK constraints in pubspec.yaml
update_sdk_constraints() {
local project_dir="$1"
local current_version="$2"
local pubspec="pubspec.yaml"
if [[ ! -f "$pubspec" ]]; then
log_error "pubspec.yaml not found in $project_dir"
return 1
fi
# Extract major and minor version numbers
local major=$(echo "$current_version" | cut -d'.' -f1)
local minor=$(echo "$current_version" | cut -d'.' -f2)
local next_major=$((major + 1))
# Create SDK constraint string
local sdk_constraint=">=$current_version <$next_major.0.0"
# Update only the Dart SDK constraint under environment: section
# This specifically targets the sdk: line under environment: and not flutter dependencies
if grep -A5 "^environment:" "$pubspec" | grep -q "sdk:"; then
# Use perl to update only the environment sdk constraint
perl -i -pe '
BEGIN { $in_env = 0; }
if (/^environment:/) { $in_env = 1; }
elsif (/^\w/ && !/^\s/) { $in_env = 0; }
if ($in_env && /(\s+sdk:\s*)['\''"]?[^'\''"]*['\''"]?/) {
s/(\s+sdk:\s*)['\''"]?[^'\''"]*['\''"]?/$1'\'''"$sdk_constraint"'\''/;
}
' "$pubspec"
log_info "Updated Dart SDK constraint in $project_dir to: $sdk_constraint"
else
log_warning "No Dart SDK constraint found under environment: in $project_dir/pubspec.yaml"
return 1
fi
}
# Function to process a single Flutter project
process_project() {
local project_dir="$1"
local project_name=$(basename "$project_dir")
log ""
log "========================================="
log "Processing project: $project_name"
log "========================================="
cd "$project_dir"
# Get current Flutter version for SDK constraints
local flutter_version
flutter_version=$(get_flutter_version)
if [[ $? -ne 0 ]]; then
log_error "Failed to get Flutter version for $project_name"
return 1
fi
# Update SDK constraints
log_info "Updating SDK constraints to use Flutter $flutter_version"
if ! update_sdk_constraints "$project_dir" "$flutter_version"; then
log_error "Failed to update SDK constraints for $project_name"
return 1
fi
# Update dependencies
log_info "Updating dependencies..."
if ! flutter pub upgrade > "$TEMP_LOG" 2>&1; then
log_error "Failed to upgrade dependencies for $project_name"
cat "$TEMP_LOG" >> "$LOG_FILE"
return 1
fi
# Run pub get
log_info "Running pub get..."
if ! flutter pub get > "$TEMP_LOG" 2>&1; then
log_error "Failed to run pub get for $project_name"
cat "$TEMP_LOG" >> "$LOG_FILE"
return 1
fi
# Run dart analyze and capture output
log_info "Running dart analyze..."
if ! dart analyze > "$TEMP_LOG" 2>&1; then
local exit_code=$?
log_error "Dart analyze found issues in $project_name (exit code: $exit_code)"
# Filter and log only errors, warnings, and infos (not success messages)
if grep -E "(error|warning|info):" "$TEMP_LOG" > /dev/null; then
log "Analyze results for $project_name:"
grep -E "(error|warning|info):" "$TEMP_LOG" >> "$LOG_FILE"
fi
# Check if there are fatal errors (errors that would prevent compilation)
if grep -E "^error:" "$TEMP_LOG" > /dev/null; then
log_error "Fatal errors found in $project_name, skipping further processing"
return 1
fi
else
# Even on success, check for warnings and infos
if grep -E "(warning|info):" "$TEMP_LOG" > /dev/null; then
log "Analyze results for $project_name:"
grep -E "(warning|info):" "$TEMP_LOG" >> "$LOG_FILE"
fi
fi
# Run dart format
log_info "Running dart format..."
if ! dart format . > "$TEMP_LOG" 2>&1; then
log_error "Failed to format code for $project_name"
cat "$TEMP_LOG" >> "$LOG_FILE"
# Continue anyway, formatting errors are not fatal
fi
# Run tests
log_info "Running tests..."
if ! flutter test > "$TEMP_LOG" 2>&1; then
local exit_code=$?
log_error "Tests failed for $project_name (exit code: $exit_code)"
# Log test failures
if grep -E "(FAILED|ERROR|Exception)" "$TEMP_LOG" > /dev/null; then
log "Test failures for $project_name:"
grep -E "(FAILED|ERROR|Exception)" "$TEMP_LOG" >> "$LOG_FILE"
fi
return 1
fi
log_info "Successfully processed $project_name"
return 0
}
# Main execution
main() {
local original_dir="$PWD"
log "Flutter Monorepo Update Script Started: $(date)"
log "Log file: $LOG_FILE"
# Check if Flutter is installed
if ! command -v flutter &> /dev/null; then
log_error "Flutter is not installed or not in PATH"
exit 1
fi
# Upgrade Flutter SDK
log ""
log "========================================="
log "Upgrading Flutter SDK"
log "========================================="
if ! flutter upgrade > "$TEMP_LOG" 2>&1; then
log_error "Failed to upgrade Flutter SDK"
cat "$TEMP_LOG" >> "$LOG_FILE"
exit 1
fi
local flutter_version
flutter_version=$(get_flutter_version)
log_info "Flutter upgraded to version: $flutter_version"
# Find all Flutter projects in the current directory
local projects=()
for dir in */; do
if [[ -d "$dir" ]] && is_flutter_project "$dir"; then
projects+=("$dir")
fi
done
if [[ ${#projects[@]} -eq 0 ]]; then
log_warning "No Flutter projects found in the current directory"
exit 0
fi
log_info "Found ${#projects[@]} Flutter project(s): ${projects[*]}"
# Process each project
local success_count=0
local failure_count=0
local failed_projects=()
for project in "${projects[@]}"; do
if process_project "$project"; then
((success_count++))
else
((failure_count++))
failed_projects+=("$(basename "$project")")
fi
# Return to root directory
cd "$original_dir"
done
# Summary
log ""
log "========================================="
log "Update Summary"
log "========================================="
log_info "Total projects processed: ${#projects[@]}"
log_info "Successful: $success_count"
if [[ $failure_count -gt 0 ]]; then
log_error "Failed: $failure_count"
log_error "Failed projects: ${failed_projects[*]}"
fi
log ""
log "Flutter Monorepo Update Script Completed: $(date)"
# Cleanup
rm -f "$TEMP_LOG"
# Exit with error code if any projects failed
if [[ $failure_count -gt 0 ]]; then
exit 1
fi
}
# Run main function
main "$@"

@ -1,8 +1,25 @@
You are a Dart developer that maintains this monorepo of Flutter sample projects.
You are a Dart developer that maintains this monorepo of sample projects. These are the tasks you need to do when necessary:
- Update for release of a new version of flutter/dart
- Read the release blog posts at (USER WILL PROVIDE)
- In the repository, checkout the "beta" git branch and make sure its up to date
- Make sure the local flutter SDK is pointing to the beta channel
- Run 'tool/release.dart', which will create a log file.
- Read the log file and address any issues it describes.
- Use the gh cli to make a PR
- Delete samples and replace with a README
- Remove all files within a sample project directory.
- Create a README and explain that the project is deprecated.
- Look at issues on (USER WILL PROVIDE LINK TO GITHUB ISSUES)
- If there are any open issues that describe deleting this sample, link to it in the README
- Mark stale code
- Create a 'stale_code.md' file if it doesn't exist.
- For each sample, look at the git logs and find the most recent commit to a .dart file in sample made by a real person.
- If that commit was more than one year ago, log it by appending to the stale code log 'sample name, git user name, date of last commit'
-
- Read https://dart.dev/tools/pub/workspaces
- Create a gloabl pubspec.yaml and populate it
- Determine 5 packages in this repository that could easily be migrated to workspaces.
- Migrate those 5 packages.

Loading…
Cancel
Save