Skip to content

Evolve how engine versions are computed #163896

@matanlurey

Description

@matanlurey

Background

Today, we have update_engine_version.sh (and friends) that do the following:

  1. If there is a git tracked bin/internal/engine.version file, we use it. Done.
  2. If there is a environment variable named FLUTTER_PREBUILT_ENGINE_VERSION set, we use it (write to a otherwise untracked engine.version). Done.
  3. If this appears to be a monorepo (it's always yes), then we branch:
    A. If is a Flutter internal recognized CI/CD (LUCI_CONTEXT), we use git rev-parse HEAD because we're building (and using) the engine from source.
    B. Otherwise, we use merge-base HEAD upstream/master (or technically, origin/master, if upstream not set)
stateDiagram-v2
    [*] --> CheckBinVersion
    CheckBinVersion: bin/internal/engine.version exists?
    BinVersionExists: Use bin/internal/engine.version
    CheckEnvVar: FLUTTER_PREBUILT_ENGINE_VERSION set?
    UseEnvVar: Use FLUTTER_PREBUILT_ENGINE_VERSION
    CheckCI: LUCI_CONTEXT set?
    UseHead: git rev-parse HEAD
    UseMergeBase: git merge-base HEAD upstream/master

    CheckBinVersion --> BinVersionExists: Yes
    CheckBinVersion --> CheckEnvVar: No
    BinVersionExists --> [*]: Done
    CheckEnvVar --> UseEnvVar: Yes
    CheckEnvVar --> CheckCI: No
    UseEnvVar --> [*]: Done
    CheckCI --> UseHead: Yes
    CheckCI --> UseMergeBase: No
    UseHead --> [*]: Done
    UseMergeBase --> [*]: Done
Loading

The reason to do this is to:

  1. Skip building the engine for framework-only changes;
  2. To allow for shipped branches to have a static (pre-computed) engine version;
  3. For developers of Flutter to get the relevant engine artifacts from the merge queue, similar to (1);
  4. ... and for CI's to build and test the engine from source (engine changes).

Problem

  1. What happens when bin/internal/engine.version flips from tracked (i.e. a shipped release) to untracked (i.e. master), or the inverse (from master to a shipped release)? There is now contention around the nature of the bin/internal/engine.version file - it's either being stomped on (which git prevents) or otherwise the state is unclean.

  2. How do you test a in-progress shipped branch? It's not shipped yet, so using a stamped engine.version isn't semantically correct (we still will have engine cherrypicks, for example, that need to built from source and used for presubmit testing, and even on post-submit, we want to use the latest build, not whatever the last engine.version happened to be)?

Possible Solution

The easiest option is to stop tracking engine.version in the source tree, or at minimum do not over-conflate the "we determined to use abcd1234 as the engine version" with "this is a shipped production release that must use abcd1234". One possible interpretation of this is:

/bin
  /internal
    /engine.release # Is always tracked by git, but should only be set in a shipped production release.
                               # This operates a little bit like a "sticky" FLUTTER_PREBUILT_ENGINE_VERSION.
    /engine.version  # Is *never* tracked by git, and should *only* be set by update_engine_version.{sh|ps1}

If we do this, we'd need to:

  • Cocoon (our CI) sets FLUTTER_PREBUILT_ENGINE_VERSION for every commit to master (pre and post).
    • HEAD (for all post-submits and engine pre-submits)
    • pr.baseRef (for framework pre-submits).
  • Cocoon (our CI) will, for cherry-picks to an unshipped release branch, we will set FLUTTER_PREBUILT_*:
    • HEAD : For pre-submits; build the engine from source, and set
    • ???????: For post-submits, store a ref somewhere, and use it

??????? could be a quasi admin-panel on Cocoon, where you associated a commit SHA with a release-branch:

flutter/3.99.99-release-candidate-0.1. ==> abc123

Finally, for shipping, the script that finalizes the release would write bin/internal/engine.release.

With this world, the update_engine_version.{sh|ps1} is simplified to:

  1. If there is a environment variable named FLUTTER_PREBUILT_ENGINE_VERSION set, we use it (write to a otherwise untracked engine.version). Done.
  2. If there is a bin/internal/engine.version file, we write it to engine.version as is. Done.
  3. We use merge-base HEAD upstream/master (or technically, origin/master, if upstream not set)
stateDiagram-v2
    [*] --> CheckEnvVar
    CheckEnvVar: FLUTTER_PREBUILT_ENGINE_VERSION set?
    UseEnvVar: Use FLUTTER_PREBUILT_ENGINE_VERSION
    CheckReleaseFile: bin/internal/engine.version exists?
    UseReleaseFile: Use bin/internal/engine.version
    UseMergeBase: git merge-base HEAD upstream/master

    CheckEnvVar --> UseEnvVar: Yes
    CheckEnvVar --> CheckReleaseFile: No
    UseEnvVar --> [*]: Done
    CheckReleaseFile --> UseReleaseFile: Yes
    CheckReleaseFile --> UseMergeBase: No
    UseReleaseFile --> [*]: Done
    UseMergeBase --> [*]: Done
Loading

Sub-issues

Metadata

Metadata

Assignees

Labels

P1High-priority issues at the top of the work listc: proposalA detailed proposal for a change to Flutterfyi-toolFor the attention of Flutter Tool teaminfra: releaseRelease-related requests and toolingteam-infraOwned by Infrastructure teamtriaged-infraTriaged by Infrastructure team

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions