diff --git a/scripts/render-builds-table.py b/scripts/render-builds-table.py index 9289a9cd11..f75df96e2d 100644 --- a/scripts/render-builds-table.py +++ b/scripts/render-builds-table.py @@ -53,7 +53,7 @@ from urllib.parse import quote # Direct-script invocation starts with scripts/, not the repository root. sys.path.insert(0, str(Path(__file__).resolve().parents[1])) -from scripts.releases import handoff, r2, semver, stable # noqa: E402 +from scripts.releases import handoff, r2, semver, stable, versioning # noqa: E402 MARKER = "" END_MARKER = "" @@ -409,6 +409,13 @@ def render_page(tag: str, assets_by_app: dict, base_url: str, f"

Release {_link(tag_url)}{html.escape(tag)}. Only objects this release " "actually staged in the bucket are listed.

", ] + attempt = versioning.parse_attempt_ref(tag) + if attempt is not None: + version = attempt[0] + body.append("

" + + html.escape(f"Attempt builds are not upgrade-safe: every attempt of {version} has the same " + f"package version, so an installed attempt is not replaced by the published {version}.") + + "

") if incomplete_jobs: body.append("

Build incomplete. Jobs not successful: " + html.escape(", ".join(incomplete_jobs)) diff --git a/tests/scripts/test_render_builds_publication.py b/tests/scripts/test_render_builds_publication.py index 2c9b11625c..df70800731 100644 --- a/tests/scripts/test_render_builds_publication.py +++ b/tests/scripts/test_render_builds_publication.py @@ -118,6 +118,16 @@ def test_incomplete_tag_keeps_channel_and_links_diagnostics(monkeypatch, r2_serv assert r2_server.store['releases/canary/index.html'][0] == b'previous good page' +def test_attempt_page_warns_and_canary_page_does_not(): + base = 'https://cdn.example' + sentence = ('Attempt builds are not upgrade-safe: every attempt of 1.2.3 has the same ' + 'package version, so an installed attempt is not replaced by the published 1.2.3.') + page = rbt.render_page('rc.1-v1.2.3', {}, base) + assert sentence in page + for tag in ('v1.2.3', 'v1.2.3+canary.20260818T101010Z', 'abandoned-rc.1-v1.2.3'): + assert sentence not in rbt.render_page(tag, {}, base) + + @pytest.mark.parametrize('version,name', [ ('1.2.3', 'HermesBundled-1.2.3-win-x64.msix'), ('1.2.3+canary.20260818T000000Z', 'HermesBundled-1.2.3+canary.20260818T000000Z-win-x64.msix'),