Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/tag.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ on:
# schedule:
# - cron: "0 15 1,15 * *"

# WHILE THIS MODULE IS PRE-1.0, DO NOT DISPATCH THIS FOR A BREAKING CHANGE.
# ccv has no 0.x special case: a `feat!:`/`fix!:` subject or a
# `BREAKING CHANGE:` footer maps straight to IncMajor(), so a run over such
# a commit tags v1.0.0 -- and the guard on the release job below then skips
# the release, leaving a major tag with no artifacts behind it. Pre-1.0
# breaking changes are released by pushing the intended minor tag by hand
# (`git tag v0.3.0 && git push origin v0.3.0`), which release.yml picks up
# on its own.

jobs:
tag:
permissions:
Expand Down
42 changes: 41 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,45 @@ it reaches 1.0.

## [Unreleased]

## [0.3.0] - 2026-08-23

### Changed

- **Breaking:** `//flutter:remote_cache_trees` is a string flag taking `none`
(default), `workspaces` or `all` instead of a boolean. The assembled pub
cache and the prepared/overlay workspaces have very different economics — a
worker must materialize the pub cache locally either way, while remote-caching
the workspaces replaces a full `intl_utils` plus `build_runner` run with a
~180MB download — so they are no longer one decision. Migration:
`--//flutter:remote_cache_trees` becomes
`--//flutter:remote_cache_trees=all`.

The setting classifies _actions_, not individual outputs, so an action that
declares both kinds of tree counts as a pub cache and stays local under
`workspaces`. That is the dependency-preparation action of a library with
`assemble_dep_caches = False`, and of a pub package that assembles; the
default library path assembles in a separate action and is unaffected.

- `docs/hermeticity.md` records what `remote_cache_trees=workspaces` can and
cannot achieve: the prepared trees are not reproducible (`.dart_tool` embeds
the producing sandbox's execroot in text _and_ inside the host native-asset
binaries JIT codegen links, where load commands cannot be rewritten), and the
SDK filegroup contributes 51 mtime-fingerprinted source directories. Sharing
therefore works between workers that share an output base or a fetched SDK,
and not between independently provisioned ones.

### Fixed

- `PrepareFlutterAppWorkspace` carries the same execution posture as every
other tree-producing action. It had none, so a ~100MB rsync of the library
workspace was remote-execution eligible (which would upload its
`no-remote-cache` input tree) and its own ~100MB output was uploaded on every
build under `--remote_upload_local_results` — the drain
`//flutter:remote_cache_trees` exists to prevent.
- The dependency-preparation log (`<name>_pub_prepare.log`) no longer records a
wall-clock timestamp. It is a declared output, so the clock reading made the
action gratuitously unreproducible.

## [0.2.1] - 2026-07-14

### Fixed
Expand Down Expand Up @@ -117,6 +156,7 @@ it reaches 1.0.

- Deprecated, ignored `dart_proto_library` `options`/`grpc` attributes.

[Unreleased]: https://github.com/SpencerC/rules_flutter/compare/v0.2.1...HEAD
[Unreleased]: https://github.com/SpencerC/rules_flutter/compare/v0.3.0...HEAD
[0.3.0]: https://github.com/SpencerC/rules_flutter/compare/v0.2.1...v0.3.0
[0.2.1]: https://github.com/SpencerC/rules_flutter/compare/v0.2.0...v0.2.1
[0.2.0]: https://github.com/SpencerC/rules_flutter/commits/v0.2.0
35 changes: 31 additions & 4 deletions docs/hermeticity.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 31 additions & 12 deletions flutter/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,39 @@ bool_flag(
visibility = ["//visibility:public"],
)

# The prepare/assemble/workspace actions produce large tree artifacts (an
# assembled pub cache is multi-GB; prepared and per-target overlay workspaces
# run ~100MB each) that change with every source edit. Uploading them via
# The prepare/assemble/workspace actions produce large tree artifacts that
# change with every source edit. Uploading them via
# --remote_upload_local_results has been observed draining a CI gate for 485s
# after the last test finished, so by default they carry no-remote-cache:
# they are rebuilt locally when needed (the hardlink assembly runs in ~seconds
# per GB) and stay eligible for the local disk cache. Small, expensive,
# high-value results (staged pub packages, golden renders, flutter build
# outputs) remain remotely cached. Flip this flag to remote-cache the trees
# too — e.g. on an RBE fleet where executors share the cache:
# build --//flutter:remote_cache_trees
bool_flag(
# after the last test finished, so by default they carry no-remote-cache: they
# are rebuilt locally when needed (the hardlink assembly runs in ~seconds per
# GB) and stay eligible for the local disk cache. Small, expensive, high-value
# results (staged pub packages, golden renders, flutter build outputs) remain
# remotely cached.
#
# The two kinds of tree have very different economics, so this is not one
# decision:
#
# none (default) neither is remotely cached.
# workspaces The ~100MB prepared and per-target overlay workspaces are, the
# multi-GB assembled pub cache is not. This is the setting for a
# fleet whose workers start cold: a cold worker has to materialize
# the pub cache locally either way (it is an input to the
# local-only flutter build, and its own inputs -- the @pub_*
# repositories -- must be fetched to compute any action key at
# all), whereas downloading ~180MB of prepared workspace replaces
# a full intl_utils + build_runner codegen run.
# all Both. For an RBE fleet where executors share the cache and the
# pub cache upload is affordable.
#
# build --//flutter:remote_cache_trees=workspaces
string_flag(
name = "remote_cache_trees",
build_setting_default = False,
build_setting_default = "none",
values = [
"none",
"workspaces",
"all",
],
visibility = ["//visibility:public"],
)

Expand Down
11 changes: 11 additions & 0 deletions flutter/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -1475,6 +1475,17 @@ fi
command = copy_script,
mnemonic = "PrepareFlutterAppWorkspace",
progress_message = "Preparing Flutter workspace for %s" % ctx.label.name,
# Same posture as every other tree-producing action, which this one was
# missing: a ~100MB rsync of the library workspace feeding a local-only
# flutter build. Without it the action was remote-execution eligible
# (which would have to upload its no-remote-cache input tree) and its
# own 100MB output was uploaded on every run under
# --remote_upload_local_results -- exactly the drain the flag exists to
# avoid.
execution_requirements = tree_output_execution_requirements(
_allow_remote_exec(ctx),
_remote_cache_trees(ctx),
),
)

android = _android_environment(ctx)
Expand Down
Loading
Loading