Skip to content

Failed releases don't block flutter/packages repo #194870

Open

Description

@bparrishMines

It currently looks like the flutter/packages doesn't block when the release action fails, regardless if the commit even needed to publish to pub.dev or not.

This has been a reoccurring issue for awhile, but was rare enough that we haven't investigated or made changes to CI to block the tree because of it. Now it seems to occur at least once a day causing gaps in version releases.

Below is the error from the release action when flutter/packages#13341 failed to publish in post-submit. (I reran the job and then it published). Note that rerunning the action seems to works everytime, it just happens to fail the first time and then go unnoticed.

Output:

Matching checks have not been found yet, will check again in 30 seconds. (Limit: 60s)
  Matching checks have not been found yet, will check again in 30 seconds. (Limit: 60s)
  The requested check was never run against this ref, exiting...

Activity

  1. added
    packageflutter/packages repository. See also p: labels.
    fyi-infraFor the attention of Infrastructure team
    on Oct 20, 2026
  2. bparrishMines commented on Oct 20, 2026

    @bparrishMines
    ContributorAuthor
  3. Piinks commented on Oct 20, 2026

    @Piinks
    Contributor

    We should definitely not fail silently

  4. added
    P1High-priority issues at the top of the work list
    on Oct 20, 2026
  5. Piinks commented on Oct 21, 2026

    @Piinks
    Contributor

    I went down the rabbit hole on this to see if I could find out why this was flaking to begin with.
    I found things...

    TL;DR

    release.yml is failing almost daily because it gives LUCI checks ~2m45s to show up on a merged commit, while Cocoon routinely takes ~3–4 minutes to mirror the commit to Git-on-Borg and register those checks. When release.yml fails—either from that race or from a post-submit LUCI flake—Cocoon's tree-status stays green because it only tracks .ci.yaml LUCI tasks, not GitHub Actions. The next commit only checks HEAD~..HEAD, so the missed version is silently skipped on pub.dev.


    Why release.yml Is Failing So Often

    Looking at the last 10 failed release.yml runs on main, there are two failure modes:

    Failure Mode A: A ~3-minute race with Git-on-Borg mirroring (9 of 10 failures)

    In release.yml (L34–L52), the workflow runs ~40s of setup, sleeps 60s, and then uses lewagon/wait-on-check-action to wait for Linux ci_yaml packages roller to appear. Since #11388 bumped wait-on-check-action to v1.6.0+ (upstream e183d72), checks-discovery-timeout defaults to 60s—giving checks ~2m45s total to register before the step exits with (Limit: 60s).

    On the Cocoon side (webhook_subscription.dart L37, L144–L152), post-submit LUCI checks can't be scheduled until the commit mirrors from GitHub to Git-on-Borg (GoB). The initial merge webhook arrives before GoB has synced, so Cocoon intentionally fails it and relies on Cloud Pub/Sub exponential backoff (up to 15 minutes, with a 6-hour vacuum-github-commits cron as fallback).

    In practice, Cocoon often registers all 93 LUCI checks just seconds after release.yml gives up:

    Failure Mode B: Post-submit LUCI flakes (1 of 10 failures)

    release.yml waits 30–85 minutes for all LUCI shards to pass (Wait on all tests). On #13243 (0563606e), run 38976753824 failed after 1h35m because Linux_web web_dart_unit_test_shard_1 master flaked two minutes after a newer commit (e01c3432) had already landed. Cocoon skips auto-retries for non-tip-of-tree commits (postsubmit_luci_subscription.dart L200–L211), and once e01c3432 passed Linux_web, tree-status went right back to green while 0563606e's release stayed dead.

    Other recent failed / manually re-run release.yml runs

    Why Failures Go Unnoticed & Create Version Gaps

    1. Cocoon is blind to GitHub Actions: PushBuildStatusToGithub and BuildStatusService.calculateCumulativeStatus only check .ci.yaml LUCI tasks in Firestore. A red release.yml never turns tree-status red.
    2. Each commit only publishes HEAD~..HEAD: release.yml (L71) runs PublishCommand with --all-changed --base-sha=HEAD~ (and tags HEAD), so the next commit ignores any missed release before it.
    3. Presubmit version checks compare against git, not pub.dev: VersionAndChangelogValidator checks the previous version on main in git. That's how #13341 (run 39464016871) was able to bump and publish in_app_purchase_storekit right over #13301's unpublished version, creating a version gap until #13301's release job was manually re-run.

    What About Batch-Released Packages?

    cupertino_ui, go_router, and material_ui (batch: true) publish weekly from release-<pkg>-<version> branches via release_from_branches.yml → reusable_release.yml.


    How We Should Fix It

    Step 1: Stop the daily timeout & deduplicate release.yml (flutter/packages)

    • Set checks-discovery-timeout: 900 (15m, matching Cocoon's GoB sync window) in reusable_release.yml, and guard sleep 60s with if: inputs.branch-name == 'main'.
    • Have release.yml call reusable_release.yml instead of maintaining two copies.

    Step 2: Block merges when a release fails

    Unlike normal LUCI test columns, C2's release passing doesn't fix C1's failed release—so any recent commit whose latest release attempt failed needs to block merges until re-run, except commits that were reverted on main (whose broken LUCI checks can't pass and shouldn't be published).

    • Option A — In flutter/packages now (no Cocoon changes needed):
      auto-submit already treats the 'submit-queue' commit status on flutter/packages PRs just like 'tree-status' (ci_successful.dart L17–L20, L176–L204): when failure, it holds autosubmit PRs without stripping the label and respects emergency.
      • Add a small workflow on workflow_run (release, Batch Release) + pull_request_target that checks the last ~20 main commits (ignoring reverted commits) and active release-* branches.
      • When everything is green, it posts nothing. When a release fails, it sets submit-queue: failure (linking straight to the failed run) on open PRs, and flips them back to success once re-run.
    • Option B — Longer-term in flutter/cocoon:
      Teach BuildStatusService.calculateCumulativeStatus to check per-commit release check-runs for flutter/packages (and add packagesSlug to reposWithTreeStatus). This turns tree-status itself red and posts to #tree-status on Discord, though flutter-dashboard will also need a way to surface the GitHub Action link since gardeners can't re-run Actions from the LUCI grid.

    Step 3: Close the version-gap holes in repo tooling (flutter/packages)

    • Batch sync guard: In reusable_sync_to_main.yml, check that tag <pkg>-v<version> exists on origin before creating a Sync release-* to main PR, and fail loudly if it doesn't.
    • publish-check guard: In PublishCheckCommand (which already queries pub.dev in Linux repo_checks), verify that a package's previous version (base-sha) is already on pub.dev before allowing a new version bump—and for batch sync-back PRs (override: batch-<pkg> into main), verify the synced version itself is on pub.dev.
  6. changed the title [-]Failed releases doesn't block flutter/packages repo[/-] [+]Failed releases don't block flutter/packages repo[/+] on Nov 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P1High-priority issues at the top of the work listpackageflutter/packages repository. See also p: labels.team-ecosystemOwned by Ecosystem teamtriaged-ecosystemTriaged by Ecosystem team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions