Skip to content

Commit 9595c92

Browse files
jtmcdolemboetger
authored andcommitted
feat: start using the content aware hash for downloading artifacts (flutter#171927)
towards flutter#171790 Use the content aware hash when downloading engine artifacts. These are currently produced when changes to DEPs, engine/, or the release file are changed in a not-seen-before way. We can eventually remove `engine.version` being tracked in release branches as an optimization. `FLUTTER_PREBUILT_ENGINE_VERSION` will stay for overriding the engine.version for testing. Though Cocoon does not need to actually set it for framework only PRs anymore.
1 parent f6b2d21 commit 9595c92

File tree

5 files changed

+77
-47
lines changed

5 files changed

+77
-47
lines changed

bin/internal/update_engine_version.ps1

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,7 @@ if (![string]::IsNullOrEmpty($env:FLUTTER_PREBUILT_ENGINE_VERSION)) {
5757
# the current branch is forked from, which would be the last version of the
5858
# engine artifacts built from CI.
5959
} else {
60-
$ErrorActionPreference = "Continue"
61-
git -C "$flutterRoot" remote get-url upstream *> $null
62-
$exitCode = $?
63-
$ErrorActionPreference = "Stop"
64-
if ($exitCode) {
65-
$engineVersion = (git -C "$flutterRoot" merge-base HEAD upstream/master)
66-
} else {
67-
$engineVersion = (git -C "$flutterRoot" merge-base HEAD origin/master)
68-
}
60+
$engineVersion = & "$flutterRoot/bin/internal/content_aware_hash.ps1"
6961
}
7062

7163
# Write the engine version out so downstream tools know what to look for.

bin/internal/update_engine_version.sh

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,7 @@ elif [ -n "$(git -C "$FLUTTER_ROOT" ls-files bin/internal/engine.version)" ]; th
5757
# the current branch is forked from, which would be the last version of the
5858
# engine artifacts built from CI.
5959
else
60-
set +e
61-
# We fallback to origin/master if upstream is not detected.
62-
git -C "$FLUTTER_ROOT" remote get-url upstream >/dev/null 2>&1
63-
exit_code=$?
64-
set -e
65-
66-
if [[ $exit_code -eq 0 ]]; then
67-
ENGINE_VERSION=$(git -C "$FLUTTER_ROOT" merge-base HEAD upstream/master)
68-
else
69-
ENGINE_VERSION=$(git -C "$FLUTTER_ROOT" merge-base HEAD origin/master)
70-
fi
60+
ENGINE_VERSION=$("$FLUTTER_ROOT/bin/internal/content_aware_hash.sh")
7161
fi
7262

7363
# Write the engine version out so downstream tools know what to look for.

dev/tools/test/update_engine_version_test.dart

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ void main() {
105105
testRoot.binInternalUpdateEngineVersion.path,
106106
);
107107

108+
// Copy the content_aware_hash script and create a rough directory structure.
109+
flutterRoot.binInternalContentAwareHash.copySyncRecursive(
110+
testRoot.binInternalContentAwareHash.path,
111+
);
112+
108113
// Regression test for https://github.com/flutter/flutter/pull/164396;
109114
// on a fresh checkout bin/cache does not exist, so avoid trying to create
110115
// this folder.
@@ -132,6 +137,11 @@ void main() {
132137
'internal',
133138
localFs.path.basename(testRoot.binInternalUpdateEngineVersion.path),
134139
),
140+
localFs.path.join(
141+
'bin',
142+
'internal',
143+
localFs.path.basename(testRoot.binInternalContentAwareHash.path),
144+
),
135145
localFs.path.join('bin', 'internal', 'engine.version'),
136146
localFs.path.join('engine', 'src', '.gn'),
137147
'DEPS',
@@ -230,13 +240,22 @@ void main() {
230240
run('git', <String>['fetch', remote], workingPath: rootPath);
231241
}
232242

233-
/// Returns the SHA computed by `merge-base HEAD {{ref}}/master`.
234-
String gitMergeBase({required String ref}) {
235-
final io.ProcessResult mergeBaseHeadOrigin = run('git', <String>[
236-
'merge-base',
237-
'HEAD',
238-
'$ref/master',
239-
]);
243+
/// Returns the SHA computed by `content_aware_hash`.
244+
String gitContentHash({required _FlutterRootUnderTest fileSystem}) {
245+
final String executable;
246+
final List<String> args;
247+
final String script = fileSystem.binInternalContentAwareHash.path;
248+
if (const LocalPlatform().isWindows) {
249+
executable = 'powershell';
250+
args = <String>[script];
251+
} else if (usePowershellOnPosix) {
252+
executable = 'pwsh';
253+
args = <String>[script];
254+
} else {
255+
executable = script;
256+
args = <String>[];
257+
}
258+
final io.ProcessResult mergeBaseHeadOrigin = run(executable, args);
240259
return mergeBaseHeadOrigin.stdout as String;
241260
}
242261

@@ -312,7 +331,10 @@ void main() {
312331
pinEngineVersionForReleaseBranch(engineHash: 'abc123', gitTrack: false);
313332
runUpdateEngineVersion();
314333

315-
expect(testRoot.binCacheEngineStamp, _hasFileContentsMatching(gitMergeBase(ref: 'upstream')));
334+
expect(
335+
testRoot.binCacheEngineStamp,
336+
_hasFileContentsMatching(gitContentHash(fileSystem: testRoot)),
337+
);
316338
});
317339
});
318340

@@ -325,14 +347,20 @@ void main() {
325347
setupRemote(remote: 'upstream');
326348
runUpdateEngineVersion();
327349

328-
expect(testRoot.binCacheEngineStamp, _hasFileContentsMatching(gitMergeBase(ref: 'upstream')));
350+
expect(
351+
testRoot.binCacheEngineStamp,
352+
_hasFileContentsMatching(gitContentHash(fileSystem: testRoot)),
353+
);
329354
});
330355

331356
test('fallsback to origin/master', () async {
332357
setupRemote(remote: 'origin');
333358
runUpdateEngineVersion();
334359

335-
expect(testRoot.binCacheEngineStamp, _hasFileContentsMatching(gitMergeBase(ref: 'origin')));
360+
expect(
361+
testRoot.binCacheEngineStamp,
362+
_hasFileContentsMatching(gitContentHash(fileSystem: testRoot)),
363+
);
336364
});
337365
});
338366

@@ -392,6 +420,13 @@ final class _FlutterRootUnderTest {
392420
'update_engine_version.${platform.isWindows || forcePowershell ? 'ps1' : 'sh'}',
393421
),
394422
),
423+
binInternalContentAwareHash: root.childFile(
424+
fileSystem.path.join(
425+
'bin',
426+
'internal',
427+
'content_aware_hash.${platform.isWindows || forcePowershell ? 'ps1' : 'sh'}',
428+
),
429+
),
395430
);
396431
}
397432

@@ -417,6 +452,7 @@ final class _FlutterRootUnderTest {
417452
required this.binInternalEngineVersion,
418453
required this.binCacheEngineRealm,
419454
required this.binInternalUpdateEngineVersion,
455+
required this.binInternalContentAwareHash,
420456
});
421457

422458
final Directory root;
@@ -447,6 +483,11 @@ final class _FlutterRootUnderTest {
447483
/// - [binInternalEngineVersion]
448484
/// - [binInternalEngineRealm]
449485
final File binInternalUpdateEngineVersion;
486+
487+
/// `bin/internal/content_aware_hash.{sh|ps1}`.
488+
///
489+
/// This file contains a shell script that computes the content hash
490+
final File binInternalContentAwareHash;
450491
}
451492

452493
extension on File {

docs/tool/Engine-artifacts.md

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,19 @@ for Android, iOS, and so-on).
1313

1414
When using a _released_ version of Flutter, i.e. from a channel such as `stable`,
1515
[`bin/internal/engine.version`](../../bin/internal/engine.version) is set to the
16-
git commit SHA for a merged commit in `https://github.com/flutter/flutter`, where
16+
content hash SHA for a merged commit in `https://github.com/flutter/flutter`, where
1717
the engine artifacts have already been pre-built and uploaded.
1818

1919
When using the `master` channel, or _contributing_ to Flutter (which is typically
20-
as a fork of Flutter's `master` channel), the git commit SHA is _computed_ by
21-
using `git merge-base HEAD upstream/master` (falling back to `git merge-base HEAD origin/master`
22-
to support direct forks or `flutter/flutter`).
20+
as a fork of Flutter's `master` channel), the engine SHA is _computed_ by
21+
generating a content-aware hash of files that affect the engine build (such as
22+
`DEPS` and the `engine` directory itself).
2323

2424
For _advanced_ use-cases, such as on CI platforms, or for custom 1-off testing
2525
using a pre-built Flutter engine (to use a _locally_ built Flutter engine see
2626
[locally built engines](../contributing/testing/Running-and-writing-tests.md#locally-built-engines)), the environment variable `FLUTTER_PREBUILT_ENGINE_VERSION` can be set,
27-
again to a git commit SHA for a merged commit in `flutter/flutter`:
27+
again to a engine SHA for a merged commit in `flutter/flutter`. This is only needed
28+
if different artifacts from the content sha are desired:
2829

2930
```sh
3031
$ FLUTTER_PREBUILT_ENGINE_VERSION=abc123 flutter --version
@@ -40,33 +41,33 @@ stateDiagram-v2
4041
UseEnvVar: Use <code>FLUTTER_PREBUILT_ENGINE_VERSION</code>
4142
CheckReleaseFile: <code>bin/internal/engine.version</code> exists?
4243
UseReleaseFile: Use <code>bin/internal/engine.version</code>
43-
UseMergeBase: <code>git merge-base HEAD upstream/master</code>
44+
UseContentAwareHash: Compute content-aware hash
4445
4546
CheckEnvVar --> UseEnvVar: Yes
4647
CheckEnvVar --> CheckReleaseFile: No
4748
UseEnvVar --> [*]: Done
4849
CheckReleaseFile --> UseReleaseFile: Yes
49-
CheckReleaseFile --> UseMergeBase: No
50+
CheckReleaseFile --> UseContentAwareHash: No
5051
UseReleaseFile --> [*]: Done
51-
UseMergeBase --> [*]: Done
52+
UseContentAwareHash --> [*]: Done
5253
```
5354

5455
## Flutter CI/CD Testing
5556

5657
On Cocoon (Flutter's internal CI/CD) we _often_ set
5758
`FLUTTER_PREBUILT_ENGINE_VERSION` to the following:
5859

59-
| Branch | Presubmit | Merge Queue | Postsubmit |
60-
| ------------------------- | ------------ | ------------------ | ---------------------------------- |
61-
| `main` | `commit.sha` | _Uses normal flow_ | _Uses normal flow_ |
62-
| `flutter-x.x-candidate.x` | `commit.sha` | N/A[^1] | _Uses normal flow_ |
63-
| `stable` or `beta` | N/A[^3] | N/A[^1] | N/A[^3] |
64-
| _anything else_[^2] | `commit.sha` | _Uses normal flow_ | _Uses postsubmit engine artifacts_ |
60+
| Branch | Presubmit | Merge Queue | Postsubmit |
61+
| ------------------------- | ------------- | ------------- | ------------- |
62+
| `main` | `content.sha` | `content.sha` | `content.sha` |
63+
| `flutter-x.x-candidate.x` | `content.sha` | N/A[^1] | `content.sha` |
64+
| `stable` or `beta` | N/A[^3] | N/A[^1] | N/A[^3] |
65+
| _anything else_[^2] | `content.sha` | `content.sh` | `content.sha` |
6566

6667
> To generate a new `engine.version`:
6768
>
6869
> ```sh
69-
> ./bin/internal/last_engine_commit.sh > ./bin/internal/engine.version
70+
> ./bin/internal/content_aware_hash.sh > ./bin/internal/engine.version
7071
> ```
7172
>
7273
> As of [`b0ccfb53801abc9b0aa93e7cca3a3841513c3086`](https://flutter.googlesource.com/recipes/+/b0ccfb53801abc9b0aa93e7cca3a3841513c3086) (May 6 2025), the packaging release process will refuse to let you publish a

packages/flutter_tools/lib/src/flutter_cache.dart

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,10 @@ class FlutterRunnerSDKArtifacts extends CachedArtifact {
606606
if (!_platform.isLinux && !_platform.isMacOS) {
607607
return;
608608
}
609-
final url = '${cache.cipdBaseUrl}/flutter/fuchsia/+/git_revision:$version';
609+
// Keep in sync with
610+
// engine/src/flutter/tools/fuchsia/build_fuchsia_artifacts.py
611+
// engine/src/flutter/tools/fuchsia/merge_and_upload_debug_symbols.py
612+
final url = '${cache.cipdBaseUrl}/flutter/fuchsia/+/content_aware_hash:$version';
610613
await artifactUpdater.downloadZipArchive(
611614
'Downloading package flutter runner...',
612615
Uri.parse(url),
@@ -633,7 +636,10 @@ class CipdArchiveResolver extends VersionedPackageResolver {
633636

634637
@override
635638
String resolveUrl(String packageName, String version) {
636-
return '${cache.cipdBaseUrl}/flutter/$packageName/+/git_revision:$version';
639+
// Keep in sync with
640+
// engine/src/flutter/tools/fuchsia/build_fuchsia_artifacts.py
641+
// engine/src/flutter/tools/fuchsia/merge_and_upload_debug_symbols.py
642+
return '${cache.cipdBaseUrl}/flutter/$packageName/+/content_aware_hash:$version';
637643
}
638644
}
639645

0 commit comments

Comments
 (0)