From 774a0e5191f62e2bdf6d9dc2214aa50331573c13 Mon Sep 17 00:00:00 2001 From: kryoseu Date: Mon, 6 Jul 2026 14:33:08 -0700 Subject: [PATCH 1/2] feat: include partial_versions in get_release_config Port the partial_versions handling from `gecko_taskgraph`s `get_release_config` so gecko and comm can share a single implementation. When the `PARTIAL_UPDATES` environment variable is set (as done by the release_promotion action), a `partial_versions` entry describing the partial updates is added to the release config. The set of kinds that consume partials is project-specific, so rather than hardcoding gecko's kind names in shared code (which is how it's currently done in gecko_taskgraph) they are sourced from a new `partial-updates-kinds` list in the graph-config. `get_release_config` reads it from the graph config and only injects `partial_versions` for tasks whose kind is listed. --- src/mozilla_taskgraph/config.py | 13 ++++++ src/mozilla_taskgraph/worker_types.py | 28 ++++++++++-- test/test_worker_types.py | 63 +++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 3 deletions(-) diff --git a/src/mozilla_taskgraph/config.py b/src/mozilla_taskgraph/config.py index 4ac6ae7..06b536e 100644 --- a/src/mozilla_taskgraph/config.py +++ b/src/mozilla_taskgraph/config.py @@ -32,6 +32,10 @@ class MozillaGraphConfigSchema(tg.graph_config_schema): # named branches. Consumed by # ``mozilla_taskgraph.util.attributes:release_level``. release_branches: Optional[dict[str, Union[bool, list[str]]]] = None + # Kinds whose tasks consume partial updates. When the ``PARTIAL_UPDATES`` + # environment variable is set, ``get_release_config`` injects a + # ``partial_versions`` entry for tasks of these kinds. + partial_updates_kinds: Optional[list[str]] = None else: # Legacy voluptuous-based graph_config_schema (e.g. gecko_taskgraph override). @@ -63,6 +67,15 @@ class MozillaGraphConfigSchema(tg.graph_config_schema): releases to the named branches. """.lstrip()), ): {str: object}, + Vol_Optional( + "partial-updates-kinds", + description=dedent(""" + Kinds whose tasks consume partial updates. When the + ``PARTIAL_UPDATES`` environment variable is set, + ``get_release_config`` injects a ``partial_versions`` entry + for tasks of these kinds. + """.lstrip()), + ): [str], } ) diff --git a/src/mozilla_taskgraph/worker_types.py b/src/mozilla_taskgraph/worker_types.py index 812f311..57829c7 100644 --- a/src/mozilla_taskgraph/worker_types.py +++ b/src/mozilla_taskgraph/worker_types.py @@ -1,4 +1,6 @@ import binascii +import json +import os from base64 import b64decode from typing import Literal, Optional, Union @@ -447,17 +449,37 @@ def get_release_config(config): Args: config (TransformConfig): The configuration for the kind being transformed. + When the `PARTIAL_UPDATES` environment variable is set (as done by the + `release_promotion` action) and the current kind is listed in the + `partial-updates-kinds` graph config, a `partial_versions` entry describing + the partial updates is also included. + Returns: - dict: containing both `build_number` and `version`. This can be used to - update `task.payload`. + dict: containing at least `build_number` and `version`. This can be + used to update `task.payload`. """ - return { + release_config = { "version": config.params["version"], "appVersion": config.params["app_version"], "next_version": config.params["next_version"], "build_number": config.params["build_number"], } + partial_updates = os.environ.get("PARTIAL_UPDATES", "") + partial_updates_kinds = config.graph_config.get("partial-updates-kinds") or [] + if partial_updates != "" and config.kind in partial_updates_kinds: + partial_updates = json.loads(partial_updates) + release_config["partial_versions"] = ", ".join( + [ + "{}build{}".format(v, info["buildNumber"]) + for v, info in partial_updates.items() + ] + ) + if release_config["partial_versions"] == "{}": + del release_config["partial_versions"] + + return release_config + def process_l10n_bump_info(info): l10n_bump_info = [] diff --git a/test/test_worker_types.py b/test/test_worker_types.py index 03cec75..b34bb90 100644 --- a/test/test_worker_types.py +++ b/test/test_worker_types.py @@ -1,12 +1,15 @@ import inspect +import json from pprint import pprint from typing import Optional import pytest +from taskgraph.transforms.base import TransformConfig from taskgraph.transforms.task import payload_builders from taskgraph.util.schema import validate_schema import mozilla_taskgraph.worker_types # noqa - trigger payload_builder registration +from mozilla_taskgraph.worker_types import get_release_config @pytest.fixture @@ -1478,3 +1481,63 @@ def test_beetmover_upload_data_bad_encoding(build_payload): assert False, "should've raised an exception" except Exception as e: assert "data must be base64 encoded" in e.args[0] + + +@pytest.fixture +def make_release_config(monkeypatch, make_graph_config, parameters): + def inner(kind, partial_updates=None, partial_updates_kinds=None): + if partial_updates is None: + monkeypatch.delenv("PARTIAL_UPDATES", raising=False) + else: + monkeypatch.setenv("PARTIAL_UPDATES", partial_updates) + + extra_config = {} + if partial_updates_kinds is not None: + extra_config["partial-updates-kinds"] = partial_updates_kinds + graph_config = make_graph_config(extra_config=extra_config) + + config = TransformConfig( + kind, "test", {}, parameters, {}, graph_config, write_artifacts=False + ) + return get_release_config(config) + + return inner + + +def test_get_release_config_base(make_release_config): + assert make_release_config("release-beetmover") == { + "version": "99.0", + "appVersion": "99.0", + "next_version": "100.0", + "build_number": 1, + } + + +def test_get_release_config_partials(make_release_config): + partial_updates = json.dumps( + {"70.0": {"buildNumber": 1}, "69.0": {"buildNumber": 3}} + ) + release_config = make_release_config( + "release-update-verify-config", + partial_updates=partial_updates, + partial_updates_kinds=["release-update-verify-config"], + ) + assert release_config["partial_versions"] == "70.0build1, 69.0build3" + + +def test_get_release_config_partials_ignored_for_unlisted_kinds(make_release_config): + partial_updates = json.dumps({"70.0": {"buildNumber": 1}}) + release_config = make_release_config( + "release-beetmover", + partial_updates=partial_updates, + partial_updates_kinds=["release-update-verify-config"], + ) + assert "partial_versions" not in release_config + + +def test_get_release_config_partials_no_kinds_configured(make_release_config): + partial_updates = json.dumps({"70.0": {"buildNumber": 1}}) + release_config = make_release_config( + "release-update-verify-config", partial_updates=partial_updates + ) + assert "partial_versions" not in release_config From 8ca12623d922a70b72172def9b0879017440d97a Mon Sep 17 00:00:00 2001 From: kryoseu Date: Tue, 7 Jul 2026 09:14:45 -0700 Subject: [PATCH 2/2] refactor: always inject partial_versions when PARTIAL_UPDATES is set Drop the `partial-updates-kinds` graph config gating from `get_release_config`. A `partial_versions` entry is now added for any kind whenever the `PARTIAL_UPDATES` environment variable is set, rather than only for kinds listed in `partial-updates-kinds`. --- src/mozilla_taskgraph/config.py | 13 ------------- src/mozilla_taskgraph/worker_types.py | 10 +++------- test/test_worker_types.py | 26 ++------------------------ 3 files changed, 5 insertions(+), 44 deletions(-) diff --git a/src/mozilla_taskgraph/config.py b/src/mozilla_taskgraph/config.py index 06b536e..4ac6ae7 100644 --- a/src/mozilla_taskgraph/config.py +++ b/src/mozilla_taskgraph/config.py @@ -32,10 +32,6 @@ class MozillaGraphConfigSchema(tg.graph_config_schema): # named branches. Consumed by # ``mozilla_taskgraph.util.attributes:release_level``. release_branches: Optional[dict[str, Union[bool, list[str]]]] = None - # Kinds whose tasks consume partial updates. When the ``PARTIAL_UPDATES`` - # environment variable is set, ``get_release_config`` injects a - # ``partial_versions`` entry for tasks of these kinds. - partial_updates_kinds: Optional[list[str]] = None else: # Legacy voluptuous-based graph_config_schema (e.g. gecko_taskgraph override). @@ -67,15 +63,6 @@ class MozillaGraphConfigSchema(tg.graph_config_schema): releases to the named branches. """.lstrip()), ): {str: object}, - Vol_Optional( - "partial-updates-kinds", - description=dedent(""" - Kinds whose tasks consume partial updates. When the - ``PARTIAL_UPDATES`` environment variable is set, - ``get_release_config`` injects a ``partial_versions`` entry - for tasks of these kinds. - """.lstrip()), - ): [str], } ) diff --git a/src/mozilla_taskgraph/worker_types.py b/src/mozilla_taskgraph/worker_types.py index 57829c7..fab5b7e 100644 --- a/src/mozilla_taskgraph/worker_types.py +++ b/src/mozilla_taskgraph/worker_types.py @@ -450,9 +450,8 @@ def get_release_config(config): config (TransformConfig): The configuration for the kind being transformed. When the `PARTIAL_UPDATES` environment variable is set (as done by the - `release_promotion` action) and the current kind is listed in the - `partial-updates-kinds` graph config, a `partial_versions` entry describing - the partial updates is also included. + `release_promotion` action), a `partial_versions` entry describing the + partial updates is also included. Returns: dict: containing at least `build_number` and `version`. This can be @@ -466,8 +465,7 @@ def get_release_config(config): } partial_updates = os.environ.get("PARTIAL_UPDATES", "") - partial_updates_kinds = config.graph_config.get("partial-updates-kinds") or [] - if partial_updates != "" and config.kind in partial_updates_kinds: + if partial_updates != "": partial_updates = json.loads(partial_updates) release_config["partial_versions"] = ", ".join( [ @@ -475,8 +473,6 @@ def get_release_config(config): for v, info in partial_updates.items() ] ) - if release_config["partial_versions"] == "{}": - del release_config["partial_versions"] return release_config diff --git a/test/test_worker_types.py b/test/test_worker_types.py index b34bb90..f4b330a 100644 --- a/test/test_worker_types.py +++ b/test/test_worker_types.py @@ -1485,16 +1485,13 @@ def test_beetmover_upload_data_bad_encoding(build_payload): @pytest.fixture def make_release_config(monkeypatch, make_graph_config, parameters): - def inner(kind, partial_updates=None, partial_updates_kinds=None): + def inner(kind, partial_updates=None): if partial_updates is None: monkeypatch.delenv("PARTIAL_UPDATES", raising=False) else: monkeypatch.setenv("PARTIAL_UPDATES", partial_updates) - extra_config = {} - if partial_updates_kinds is not None: - extra_config["partial-updates-kinds"] = partial_updates_kinds - graph_config = make_graph_config(extra_config=extra_config) + graph_config = make_graph_config() config = TransformConfig( kind, "test", {}, parameters, {}, graph_config, write_artifacts=False @@ -1520,24 +1517,5 @@ def test_get_release_config_partials(make_release_config): release_config = make_release_config( "release-update-verify-config", partial_updates=partial_updates, - partial_updates_kinds=["release-update-verify-config"], ) assert release_config["partial_versions"] == "70.0build1, 69.0build3" - - -def test_get_release_config_partials_ignored_for_unlisted_kinds(make_release_config): - partial_updates = json.dumps({"70.0": {"buildNumber": 1}}) - release_config = make_release_config( - "release-beetmover", - partial_updates=partial_updates, - partial_updates_kinds=["release-update-verify-config"], - ) - assert "partial_versions" not in release_config - - -def test_get_release_config_partials_no_kinds_configured(make_release_config): - partial_updates = json.dumps({"70.0": {"buildNumber": 1}}) - release_config = make_release_config( - "release-update-verify-config", partial_updates=partial_updates - ) - assert "partial_versions" not in release_config