This document provides guidance for AI agents to effectively contribute to the flutter/packages
repository.
CHANGELOG.md
and pubspec.yaml
version.To ensure a consistent and functional environment, configure your VM with the following setup. This provides the necessary Flutter SDK and dependencies for building and testing packages.
curl -L https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_3.32.8-stable.tar.xz | tar -xJ -C $HOME export FLUTTER_HOME=$HOME/flutter export PATH=$FLUTTER_HOME/bin:$PATH flutter --disable-analytics flutter precache --force # Sanity check the configuration. flutter doctor --verbose
This is a monorepo containing many Flutter packages.
packages/
.third_party/packages/
.script/tool/
.Many packages are part of federated plugins. A federated plugin has a main package (e.g., path_provider
) that defines the API used by plugin clients, a platform interface package (e.g., path_provider_platform_interface
) that defines the interface that each platform implementation must implement, and one or more platform implementation packages (e.g., path_provider_android
, path_provider_ios
) that implement that platform interface. When working on a federated plugin, you may need to modify multiple packages.
For more details, see the main README.md
and CONTRIBUTING.md
.
The primary tool for this repository is flutter_plugin_tools.dart
.
First, initialize the tooling:
cd $REPO_ROOT/script/tool # $REPO_ROOT is the repository root dart pub get
Most tool commands take a --packages
argument. You must correctly identify all packages affected by your changes. You can derive this from git diff.
For example, to find changed files against the main branch of the upstream remote (assuming the upstream remote is named origin
):
git diff --name-only origin/main...HEAD
Then, for each file path, find its enclosing package. A package is a directory containing a pubspec.yaml
file. The directory name is usually the package name. Ignore pubspec.yaml
files within example/
directories when determining the package for a file.
Running a tool command without a --packages
argument will run the command on all packages. For example, a dependency can be updated for all packages in the repository:
dart run $REPO_ROOT/script/tool/bin/flutter_plugin_tools.dart update-dependency --pub-package <dependency_name>
Formatting: Always format your changes.
dart run $REPO_ROOT/script/tool/bin/flutter_plugin_tools.dart format --packages <changed_packages>
Testing: All changes must pass analysis and tests:
# Run static analysis dart run $REPO_ROOT/script/tool/bin/flutter_plugin_tools.dart analyze --packages <changed_packages> # Run Dart unit tests dart run $REPO_ROOT/script/tool/bin/flutter_plugin_tools.dart dart-test --packages <changed_packages>
The tool can also run native and integration tests, but these may require a more complete environment than is available.
Validation: Run these checks to ensure that changes follow team guidelines:
dart run $REPO_ROOT/script/tool/bin/flutter_plugin_tools.dart publish-check --packages <changed_packages> dart run $REPO_ROOT/script/tool/bin/flutter_plugin_tools.dart readme-check --packages <changed_packages> dart run $REPO_ROOT/script/tool/bin/flutter_plugin_tools.dart version-check --packages <changed_packages> dart run $REPO_ROOT/script/tool/bin/flutter_plugin_tools.dart license-check dart run $REPO_ROOT/script/tool/bin/flutter_plugin_tools.dart repo-package-info-check
Federated Plugin Development: If you change multiple packages in a federated plugin that depend on each other, use make-deps-path-based
to make their pubspec.yaml files use path:
dependencies. This allows you to test them together locally.
dart run $REPO_ROOT/script/tool/bin/flutter_plugin_tools.dart make-deps-path-based --target-dependencies=<changed_plugin_packages>
The CI system will run tests with path-based dependencies automatically, so this is not required for PRs, but can be useful for local testing.
Updating Dependencies: To update a dependency across multiple packages:
dart run $REPO_ROOT/script/tool/bin/flutter_plugin_tools.dart update-dependency --pub-package <dependency_name> --packages <packages_to_update>
Updating README Code Samples: If you change example code that is included in a README.md:
dart run $REPO_ROOT/script/tool/bin/flutter_plugin_tools.dart update-excerpts --packages <changed_packages>
Some packages use code generators, and changes to those packages require running the relevant code generators.
pigeons/
directory, you must run the Pigeon generator:# Run from the package's directory dart run pigeon --input pigeons/<changed_file>.dart
mockito
for tests (check dev_dependencies
in pubspec.yaml
), you must run its mock generator:# Run from the package's directory dart run build_runner build -d
All code must adhere to the repository's style guides. The format
command handles most of this, but be aware of the specific style guides for each language, as detailed in CONTRIBUTING.md:
dart format
.clang-format
.google-java-format
.ktfmt
.clang-format
.swift-format
.Any PR that changes non-test code in a package should update its version in pubspec.yaml and add a corresponding entry in CHANGELOG.md.
This process can be automated. The update-release-info
command is the preferred way to handle this. It determines changed packages, bumps versions, and updates changelogs automatically.
dart run $REPO_ROOT/script/tool/bin/flutter_plugin_tools.dart update-release-info \ --version=minimal \ --base-branch=origin/main \ --changelog="A description of the changes."
--version=minimal
: Bumps patch for bug fixes, and skips unchanged packages. This is usually the best option unless a new feature is being added.--version=minor
instead.--base-branch=origin/main
: Diffs against the main
branch to find changed packages.If you update manually, follow semantic versioning and the repository's CHANGELOG format.