Skip to content

firefox_version.py: resolve the Firefox build revision from TaskCluster, not the hg release tag #1221

Description

@vringar

Problem

scripts/firefox_version.py resolves "the latest Firefox release" from the hg tag list: it reads https://hg.mozilla.org/releases/mozilla-release/json-tags, picks the highest FIREFOX_X_Y_Z_RELEASE tag, and pins that tag's node in scripts/install-firefox.sh.

That assumes the revision a release is tagged at is the revision its builds were produced from. That assumption does not always hold, and when it breaks we silently skip a shipped Firefox release.

Evidence (Firefox 153.0.3)

FIREFOX_153_0_3_RELEASE tags node 5ea6f25c57d411c3dea06f0405775b4066302e09. There is no unbranded (add-on-devel) build indexed against that node:

404  gecko.v2.mozilla-release.revision.5ea6f25c...firefox.linux64-add-on-devel

But 153.0.3 unbranded builds do exist. They were built from mozilla-release revision 0cbbe673f58f3b809b3b6313ab0b1495a53af347, which carries no FIREFOX_*_RELEASE tag:

200  gecko.v2.mozilla-release.revision.0cbbe673...firefox.linux64-add-on-devel
200  gecko.v2.mozilla-release.revision.0cbbe673...firefox.macosx64-add-on-devel

and that revision self-identifies as the same release:

$ curl -sL https://hg.mozilla.org/releases/mozilla-release/raw-file/0cbbe673.../browser/config/version.txt
153.0.3

gecko.v2.mozilla-release.latest.firefox.linux64-add-on-devel points at that build (task IgBMUW2YTtGQ6GzEJ2RqRg, created 2026-08-03), confirming it is the newest unbranded release build available — not 153.0.1's.

Separately worth recording, since it looked like the cause at first: the tagged 153.0.3 revision also has a visibly trimmed task graph (162 indexed firefox.* tasks vs 195 for 153.0.1), missing all *-add-on-devel, linux64-debug, linux64-asan-opt/tsan-opt, and every sm-* SpiderMonkey job. So both things are true: that node was built with a reduced graph, and the full build happened at a later untagged revision.

Impact

We pin one release behind the true latest stable whenever this happens. OpenWPM's stated requirement is to track the latest stable Firefox, so this quietly violates it. In #1216-adjacent terms it is a correctness-of-tooling issue, not a crawl-data issue.

Today this is masked rather than silent: firefox_version.py now verifies unbranded builds exist for a tag's revision before pinning it (added alongside the v0.36.0 release prep), and logs Skipping <tag>: no unbranded build on TaskCluster. Before that check, the bad node was pinned happily and only failed with a 404 at install-firefox.sh download time — the failure mode from #964.

Proposed fix

Treat the TaskCluster index, not the hg tag list, as the source of truth for "the latest installable Firefox":

  1. Resolve gecko.v2.mozilla-release.latest.firefox.<platform>-add-on-devel for every platform install-firefox.sh supports.
  2. Read payload.env.GECKO_HEAD_REV from the resolved task to get the build revision.
  3. Confirm the platforms agree on that revision, and read browser/config/version.txt at it to get the human-facing version for the # FIREFOX_..._RELEASE-style comment and for strict_min_version.
  4. Pin that revision.

This makes the pin "the newest revision that actually has unbranded builds on every supported platform", which is exactly the property install-firefox.sh needs, and it removes the tag-node assumption entirely.

Trade-offs to weigh

  • The comment in install-firefox.sh currently names a tag (# FIREFOX_153_0_1_RELEASE). With index-based resolution the pinned revision may have no tag, so the comment would have to carry a version string plus revision instead. That is a small readability regression in exchange for correctness.
  • It trusts TaskCluster index retention. Builds expire (the current ones expire ~1 year out), so a long-untouched checkout could reference an expired task — same exposure as today, since install-firefox.sh already downloads from that index.
  • mozilla-central does not expose latest.firefox.*-add-on-devel under the same namespace, so this logic is mozilla-release-specific. That is fine — we only ever track release.

Workaround in the meantime

fetch_latest() walks back up to _MAX_TAG_LOOKBACK tags and picks the newest one whose tagged revision does have unbranded builds, so releases like this degrade to "one version behind" with a printed reason rather than a broken install.

Activity

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions