mirror of https://github.com/flutter/samples.git
parent
8b19871277
commit
78b847cf12
@ -1,13 +1,14 @@
|
|||||||
name: analysis_defaults
|
name: analysis_defaults
|
||||||
description: Analysis defaults for flutter/samples
|
description: Analysis defaults for flutter/samples
|
||||||
publish_to: none
|
publish_to: none
|
||||||
|
resolution: workspace
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.9.0-0 <4.0.0'
|
sdk: '^3.5.0'
|
||||||
|
|
||||||
# NOTE: Code is not allowed in this package. Do not add more dependencies.
|
# NOTE: Code is not allowed in this package. Do not add more dependencies.
|
||||||
# The `flutter_lints` dependency is required for `lib/flutter.yaml`.
|
# The `flutter_lints` dependency is required for `lib/flutter.yaml`.
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter_lints: ^5.0.0
|
flutter_lints: ^6.0.0
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
## `jsonexample` sample retired
|
|
||||||
|
|
||||||
The `jsonexample` sample has reached the end of it's useful life. It was great code
|
|
||||||
when it has written, but the world has changed. Dart 3 introduced Patterns and
|
|
||||||
records. There is also various JSON parsing tools like `json_serializable`.
|
|
||||||
|
|
||||||
For further information, please see:
|
|
||||||
- The [Dive into Dart's patterns and records](https://codelabs.developers.google.com/codelabs/dart-patterns-records)
|
|
||||||
codelab for a deep dive into Dart 3's patterns and records with an application to parsing JSON
|
|
||||||
- The Flutter.dev documentation on [JSON and serialization](https://docs.flutter.dev/data-and-backend/serialization/json)
|
|
@ -0,0 +1,51 @@
|
|||||||
|
name: samples
|
||||||
|
description: A collection of samples for Dart and Flutter.
|
||||||
|
|
||||||
|
environment:
|
||||||
|
sdk: '^3.5.0'
|
||||||
|
|
||||||
|
workspace:
|
||||||
|
- add_to_app/android_view/flutter_module_using_plugin
|
||||||
|
- add_to_app/books/flutter_module_books
|
||||||
|
- add_to_app/fullscreen/flutter_module
|
||||||
|
- add_to_app/multiple_flutters/multiple_flutters_module
|
||||||
|
- add_to_app/plugin/flutter_module_using_plugin
|
||||||
|
- add_to_app/prebuilt_module/flutter_module
|
||||||
|
- analysis_defaults
|
||||||
|
- android_splash_screen
|
||||||
|
- animations
|
||||||
|
- asset_transformation
|
||||||
|
- background_isolate_channels
|
||||||
|
- code_sharing/client
|
||||||
|
- code_sharing/server
|
||||||
|
- code_sharing/shared
|
||||||
|
- context_menus
|
||||||
|
- date_planner
|
||||||
|
- deeplink_store_example
|
||||||
|
- desktop_photo_search/fluent_ui
|
||||||
|
- desktop_photo_search/material
|
||||||
|
- dynamic_theme
|
||||||
|
- form_app
|
||||||
|
- flutter_maps_firestore
|
||||||
|
- game_template
|
||||||
|
- gemini_tasks
|
||||||
|
- google_maps
|
||||||
|
- infinite_list
|
||||||
|
- ios_app_clip
|
||||||
|
- isolate_example
|
||||||
|
- material_3_demo
|
||||||
|
- navigation_and_routing
|
||||||
|
- pedometer
|
||||||
|
- pedometer/example
|
||||||
|
- platform_channels
|
||||||
|
- platform_design
|
||||||
|
- platform_view_swift
|
||||||
|
- provider_counter
|
||||||
|
- provider_shopper
|
||||||
|
- simple_shader
|
||||||
|
- simplistic_calculator
|
||||||
|
- simplistic_editor
|
||||||
|
- testing_app
|
||||||
|
- veggieseasons
|
||||||
|
- web_embedding/element_embedding_demo
|
||||||
|
- web_embedding/ng-flutter/flutter
|
@ -0,0 +1,12 @@
|
|||||||
|
name: release_cleaner
|
||||||
|
description: A tool to automate release cleanup for the samples monorepo.
|
||||||
|
environment:
|
||||||
|
sdk: '>=3.0.0 <4.0.0'
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
args: ^2.4.2
|
||||||
|
io: ^1.0.4
|
||||||
|
path: ^1.9.0
|
||||||
|
pub_semver: ^2.1.4
|
||||||
|
yaml: ^3.1.2
|
||||||
|
yaml_edit: ^2.1.1
|
@ -0,0 +1,274 @@
|
|||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:args/args.dart';
|
||||||
|
import 'package:io/ansi.dart';
|
||||||
|
import 'package:path/path.dart' as p;
|
||||||
|
import 'package:pub_semver/pub_semver.dart';
|
||||||
|
import 'package:yaml/yaml.dart';
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!await isFlutterInstalled()) {
|
||||||
|
log(red.wrap('Flutter is not installed or not in PATH')!, stderr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
log(styleBold.wrap('\n=========================================')!, stdout);
|
||||||
|
log(styleBold.wrap('Upgrading Flutter SDK')!, stdout);
|
||||||
|
log(styleBold.wrap('=========================================')!, stdout);
|
||||||
|
|
||||||
|
if (!await runCommand('flutter', ['upgrade'], isDryRun: isDryRun)) {
|
||||||
|
log(red.wrap('Failed to upgrade Flutter SDK')!, stderr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
final flutterVersion = await getFlutterVersion();
|
||||||
|
if (flutterVersion == null) {
|
||||||
|
log(red.wrap('Failed to get Flutter version.'), stderr);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
log(blue.wrap('Flutter upgraded to version: $flutterVersion'), stdout);
|
||||||
|
|
||||||
|
final packages = await getWorkspacePackages();
|
||||||
|
if (packages.isEmpty) {
|
||||||
|
log(yellow.wrap('No packages found in the root pubspec.yaml workspace.'),
|
||||||
|
stdout);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
log(
|
||||||
|
blue.wrap(
|
||||||
|
'Found ${packages.length} Flutter project(s): ${packages.join(', ')}'),
|
||||||
|
stdout);
|
||||||
|
|
||||||
|
final failedProjects = <String>[];
|
||||||
|
for (final packagePath in packages) {
|
||||||
|
final success = await processProject(packagePath, flutterVersion, isDryRun);
|
||||||
|
if (!success) {
|
||||||
|
failedProjects.add(packagePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printSummary(packages.length, failedProjects);
|
||||||
|
|
||||||
|
log(
|
||||||
|
styleBold.wrap(
|
||||||
|
'\nFlutter Monorepo Update Script Completed: ${DateTime.now()}'),
|
||||||
|
stdout);
|
||||||
|
|
||||||
|
if (failedProjects.isNotEmpty) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setupLogging() {
|
||||||
|
final logsDir = Directory(logDir);
|
||||||
|
if (!logsDir.existsSync()) {
|
||||||
|
logsDir.createSync(recursive: true);
|
||||||
|
}
|
||||||
|
final timestamp = DateTime.now().toIso8601String().replaceAll(':', '-');
|
||||||
|
_logFile = File(p.join(logDir, 'flutter_update_$timestamp.log'));
|
||||||
|
}
|
||||||
|
|
||||||
|
void log(String? message, IOSink sink) {
|
||||||
|
if (message == null) return;
|
||||||
|
sink.writeln(message);
|
||||||
|
_logFile.writeAsStringSync(
|
||||||
|
'${overrideAnsiOutput(false, () => message)}\n',
|
||||||
|
mode: FileMode.append,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> isFlutterInstalled() async {
|
||||||
|
try {
|
||||||
|
final result = await Process.run('flutter', ['--version']);
|
||||||
|
return result.exitCode == 0;
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String?> getFlutterVersion() async {
|
||||||
|
try {
|
||||||
|
final result = await Process.run('flutter', ['--version', '--machine']);
|
||||||
|
if (result.exitCode == 0) {
|
||||||
|
final json = loadYaml(result.stdout as String) as YamlMap;
|
||||||
|
return json['frameworkVersion'] as String?;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
log(red.wrap('Error getting Flutter version: $e'), stderr);
|
||||||
|
}
|
||||||
|
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 [];
|
||||||
|
}
|
||||||
|
|
||||||
|
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 [];
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> processProject(
|
||||||
|
String projectPath, String flutterVersion, bool isDryRun) async {
|
||||||
|
final projectName = p.basename(projectPath);
|
||||||
|
final projectDir = Directory(projectPath);
|
||||||
|
|
||||||
|
if (!projectDir.existsSync()) {
|
||||||
|
log(red.wrap('Project directory not found: $projectPath'), stderr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
log(styleBold.wrap('\n========================================='), stdout);
|
||||||
|
log(styleBold.wrap('Processing project: $projectName'), stdout);
|
||||||
|
log(styleBold.wrap('========================================='), stdout);
|
||||||
|
|
||||||
|
log(blue.wrap('Updating SDK constraints to use Flutter $flutterVersion'),
|
||||||
|
stdout);
|
||||||
|
if (!isDryRun) {
|
||||||
|
if (!await updateSdkConstraints(projectPath, flutterVersion)) {
|
||||||
|
log(red.wrap('Failed to update SDK constraints for $projectName'),
|
||||||
|
stderr);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final commands = [
|
||||||
|
Command('Updating dependencies...', 'flutter', ['pub', 'upgrade']),
|
||||||
|
Command('Running pub get...', 'flutter', ['pub', 'get']),
|
||||||
|
Command('Running dart analyze...', 'dart', ['analyze']),
|
||||||
|
Command('Running dart format...', 'dart', ['format', '.']),
|
||||||
|
Command('Running tests...', 'flutter', ['test']),
|
||||||
|
];
|
||||||
|
|
||||||
|
for (final command in commands) {
|
||||||
|
log(blue.wrap(command.description), stdout);
|
||||||
|
if (!await runCommand(command.executable, command.arguments,
|
||||||
|
workingDirectory: projectPath, isDryRun: isDryRun)) {
|
||||||
|
log(red.wrap('${command.description} failed for $projectName'), stderr);
|
||||||
|
// For analyze, format, and test, we might not want to hard fail the whole script.
|
||||||
|
// The original script continued on format errors but failed on test errors.
|
||||||
|
if (command.executable == 'flutter' &&
|
||||||
|
command.arguments.first == 'test') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final version = Version.parse(versionString);
|
||||||
|
final nextMajor = version.major + 1;
|
||||||
|
final newConstraint = "'>=${version} <$nextMajor.0.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<bool> 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
final process = await Process.start(executable, arguments,
|
||||||
|
workingDirectory: workingDirectory, runInShell: true);
|
||||||
|
|
||||||
|
final stdoutFuture =
|
||||||
|
process.stdout.transform(SystemEncoding().decoder).forEach((line) {
|
||||||
|
log(line, stdout);
|
||||||
|
});
|
||||||
|
final stderrFuture =
|
||||||
|
process.stderr.transform(SystemEncoding().decoder).forEach((line) {
|
||||||
|
log(red.wrap(line), stderr);
|
||||||
|
});
|
||||||
|
|
||||||
|
await Future.wait([stdoutFuture, stderrFuture]);
|
||||||
|
|
||||||
|
return await process.exitCode == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (failed.isNotEmpty) {
|
||||||
|
log(red.wrap('Failed: ${failed.length}'), stderr);
|
||||||
|
log(red.wrap('Failed projects: ${failed.join(', ')}'), stderr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Command {
|
||||||
|
final String description;
|
||||||
|
final String executable;
|
||||||
|
final List<String> arguments;
|
||||||
|
|
||||||
|
Command(this.description, this.executable, this.arguments);
|
||||||
|
}
|
@ -1 +1,6 @@
|
|||||||
Read https://dart.dev/tools/pub/workspaces
|
You are a Dart developer that maintains packages. Your current task is to incrementally update monorepos to use pub workspaces.
|
||||||
|
|
||||||
|
- 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…
Reference in new issue