From d47fad372cce689ab5f96e29a1ed31d3f93a442a Mon Sep 17 00:00:00 2001 From: Stephen King Date: Fri, 6 Feb 2026 18:17:47 -0700 Subject: [PATCH 1/2] Bug 2015223: Adds Thunderbird Release AppID Initially existing stable channel will continue to be used for ESR. - "app_id" is changed to a dict, "app-ids" to facilitate looking up the app_id by channel. - Thunderbird release channel will use org.mozilla.ThunderbirdRelease Another change down the line will change over the default stable channel "org.mozilla.Thunderbird" to release channel and ESR will use "org.mozilla.ThunderbirdESR". This is being doned in a phased approach to avoid force-switching users to a different release channel. --- pushflatpakscript/docker.d/init_worker.sh | 13 +++++++++++-- pushflatpakscript/docker.d/worker.yml | 12 +++++++++++- pushflatpakscript/examples/config.example.json | 5 ++++- .../src/pushflatpakscript/data/config_schema.json | 9 ++++++--- pushflatpakscript/src/pushflatpakscript/flathub.py | 10 +++++----- pushflatpakscript/src/pushflatpakscript/task.py | 2 +- pushflatpakscript/tests/test_config.py | 4 +++- pushflatpakscript/tests/test_task.py | 6 +++--- 8 files changed, 44 insertions(+), 17 deletions(-) diff --git a/pushflatpakscript/docker.d/init_worker.sh b/pushflatpakscript/docker.d/init_worker.sh index 4a25774dc..356c951d8 100755 --- a/pushflatpakscript/docker.d/init_worker.sh +++ b/pushflatpakscript/docker.d/init_worker.sh @@ -25,6 +25,12 @@ case $ENV in export REPO_TOKEN_STABLE_PATH=$CONFIG_DIR/stable_token.txt echo $REPO_TOKEN_BETA | base64 -d > $REPO_TOKEN_BETA_PATH echo $REPO_TOKEN_STABLE | base64 -d > $REPO_TOKEN_STABLE_PATH + + if [[$COT_PRODUCT == 'thunderbird']]; then + test_var_set 'REPO_TOKEN_ESR' + export REPO_TOKEN_ESR_PATH=$CONFIG_DIR/esr_token.txt + echo $REPO_TOKEN_ESR | base64 -d > $REPO_TOKEN_ESR_PATH + fi ;; *) exit 1 @@ -33,11 +39,14 @@ esac case $COT_PRODUCT in firefox) - export APP_ID="org.mozilla.firefox" + export APP_ID_BETA="org.mozilla.firefox" + export APP_ID_STABLE="org.mozilla.firefox" export TASKCLUSTER_SCOPE_PREFIX="project:releng:flathub:firefox:" ;; thunderbird) - export APP_ID="org.mozilla.Thunderbird" + export APP_ID_BETA="org.mozilla.Thunderbird" + export APP_ID_STABLE="org.mozilla.ThunderbirdRelease" + export APP_ID_ESR="org.mozilla.Thunderbird" export TASKCLUSTER_SCOPE_PREFIX="project:comm:thunderbird:releng:flathub:" ;; *) diff --git a/pushflatpakscript/docker.d/worker.yml b/pushflatpakscript/docker.d/worker.yml index a73f60f61..07c25b725 100644 --- a/pushflatpakscript/docker.d/worker.yml +++ b/pushflatpakscript/docker.d/worker.yml @@ -1,7 +1,13 @@ work_dir: { "$eval": "WORK_DIR" } artifact_dir: { "$eval": "ARTIFACTS_DIR" } verbose: { "$eval": "VERBOSE == 'true'" } -app_id: { "$eval": "APP_ID" } +app_ids: + beta: {"$eval": "APP_ID_BETA" } + stable: {"$eval": "APP_ID_STABLE"} + esr: + $if: 'COT_PRODUCT == "thunderbird"' + then: { "$eval": "APP_ID_ESR"} + else: '' taskcluster_scope_prefix: { "$eval": "TASKCLUSTER_SCOPE_PREFIX" } push_to_flathub: { "$eval": "ENV == 'prod'" } flathub_url: { "$eval": "FLATHUB_URL" } @@ -12,4 +18,8 @@ token_locations: then: beta: { "$eval": "REPO_TOKEN_BETA_PATH" } stable: { "$eval": "REPO_TOKEN_STABLE_PATH" } + esr: + $if: 'COT_PRODUCT == "thunderbird"' + then: { "$eval": "REPO_TOKEN_ESR_PATH" } + else: '' else: {} diff --git a/pushflatpakscript/examples/config.example.json b/pushflatpakscript/examples/config.example.json index 35340aa98..e0d3051a3 100644 --- a/pushflatpakscript/examples/config.example.json +++ b/pushflatpakscript/examples/config.example.json @@ -1,7 +1,10 @@ { "work_dir": "/some/work/dir", "verbose": true, - "app_id": "org.mozilla.firefox", + "app_ids": { + "stable": "org.mozilla.firefox", + "beta": "org.mozilla.firefox" + }, "taskcluster_scope_prefix": "project:releng:flathub:firefox:", "push_to_flathub": true, "flathub_url": "flathub URL location", diff --git a/pushflatpakscript/src/pushflatpakscript/data/config_schema.json b/pushflatpakscript/src/pushflatpakscript/data/config_schema.json index c1a304392..78b4000a9 100644 --- a/pushflatpakscript/src/pushflatpakscript/data/config_schema.json +++ b/pushflatpakscript/src/pushflatpakscript/data/config_schema.json @@ -2,7 +2,7 @@ "title": "pushflatpakscript config schema", "type": "object", "required": [ - "app_id", + "app_ids", "taskcluster_scope_prefix", "push_to_flathub", "token_locations", @@ -11,8 +11,11 @@ "taskcluster_root_url" ], "properties": { - "app_id": { - "type": "string" + "app_ids": { + "type": "object", + "additionalProperties": { + "type": "string" + } }, "taskcluster_scope_prefix": { "type": "string" diff --git a/pushflatpakscript/src/pushflatpakscript/flathub.py b/pushflatpakscript/src/pushflatpakscript/flathub.py index f92bc580e..57fb77efa 100644 --- a/pushflatpakscript/src/pushflatpakscript/flathub.py +++ b/pushflatpakscript/src/pushflatpakscript/flathub.py @@ -142,7 +142,7 @@ def files(tar, path): return os.path.join(flatpak_tar_basedir, flatpak_deflated_dir) -def check_app_id_matches_flatpak(context, flatpak_path): +def check_app_id_matches_flatpak(context, flatpak_path, channel): # Extract all ostree refs from the supplied Flatpak repo flatpak_refs = subprocess.check_output(["ostree", "refs"], cwd=flatpak_path).decode().splitlines() @@ -150,10 +150,10 @@ def check_app_id_matches_flatpak(context, flatpak_path): flatpak_refs = [ref.split("/")[1] for ref in flatpak_refs if ref.startswith("app/")] # Create a list, if any, of all unexpected Flatpak IDs present in repo - invalid_refs = set(flatpak_refs) - {context.config["app_id"]} + invalid_refs = set(flatpak_refs) - {context.config["app_ids"]} - if context.config["app_id"] not in flatpak_refs: - raise TaskVerificationError(f"Supplied app ID ({context.config['app_id']}) is not present in Flatpak!") + if context.config["app_ids"][channel] not in flatpak_refs: + raise TaskVerificationError(f"Supplied app ID ({context.config['app_ids'][channel]}) is not present in Flatpak!") if len(invalid_refs) > 0: raise TaskVerificationError("One or more invalid app IDs are present in Flatpak!") @@ -191,7 +191,7 @@ def push(context, flatpak_file_path, channel): deflated_dir = check_and_extract_tar_archive(context, flatpak_file_path) log.info("Verifying supplied app ID matches flatpak app ID...") - check_app_id_matches_flatpak(context, deflated_dir) + check_app_id_matches_flatpak(context, deflated_dir, channel) log.info(f"Pushing the flatpak to the associated {publish_build_output}") run_flat_manager_client_process(context, token_args + ["push", publish_build_output, deflated_dir]) diff --git a/pushflatpakscript/src/pushflatpakscript/task.py b/pushflatpakscript/src/pushflatpakscript/task.py index 70e566db4..5e93362a9 100644 --- a/pushflatpakscript/src/pushflatpakscript/task.py +++ b/pushflatpakscript/src/pushflatpakscript/task.py @@ -1,6 +1,6 @@ from scriptworker.exceptions import TaskVerificationError -_CHANNELS_AUTHORIZED_TO_REACH_FLATHUB = ("beta", "stable") +_CHANNELS_AUTHORIZED_TO_REACH_FLATHUB = ("beta", "stable", "esr") ALLOWED_CHANNELS = ("mock", *_CHANNELS_AUTHORIZED_TO_REACH_FLATHUB) diff --git a/pushflatpakscript/tests/test_config.py b/pushflatpakscript/tests/test_config.py index 73d6934a1..1952d5a98 100644 --- a/pushflatpakscript/tests/test_config.py +++ b/pushflatpakscript/tests/test_config.py @@ -9,7 +9,9 @@ "WORK_DIR": "", "ARTIFACTS_DIR": "", "VERBOSE": "true", - "APP_ID": "", + "APP_ID_STABLE": "", + "APP_ID_BETA": "", + "COT_PRODUCT": "firefox", "TASKCLUSTER_SCOPE_PREFIX": "", "FLATHUB_URL": "https://flat.example", "FLAT_MANAGER_CLIENT": "/app/bin/flat-manager-client", diff --git a/pushflatpakscript/tests/test_task.py b/pushflatpakscript/tests/test_task.py index 471c7ceac..f76b673fa 100644 --- a/pushflatpakscript/tests/test_task.py +++ b/pushflatpakscript/tests/test_task.py @@ -14,7 +14,7 @@ def test_get_flatpak_channel_without_payload_raises(): @pytest.mark.parametrize("raises, channel", ((False, "stable"), (False, "beta"), (False, "mock"), (False, "beta"), (False, "beta"), (True, "bogus"))) def test_get_flatpak_channel_dep(raises, channel): task = {"scopes": [], "payload": {"channel": channel}} - config = {"app_id": "org.mozilla.firefox", "taskcluster_scope_prefix": "project:releng:flathub:firefox:", "push_to_flathub": False} + config = {"app_ids": {"stable": "org.mozilla.firefox", "beta": "org.mozilla.firefox"}, "taskcluster_scope_prefix": "project:releng:flathub:firefox:", "push_to_flathub": False} if raises: with pytest.raises(TaskVerificationError): get_flatpak_channel(config, task) @@ -35,7 +35,7 @@ def test_get_flatpak_channel_dep(raises, channel): ) def test_get_flatpak_channel_prod(raises, scopes, channel): task = {"scopes": scopes, "payload": {"channel": channel}} - config = {"app_id": "org.mozilla.firefox", "taskcluster_scope_prefix": "project:releng:flathub:firefox:", "push_to_flathub": True} + config = {"app_ids": {"stable": "org.mozilla.firefox", "beta": "org.mozilla.firefox"}, "taskcluster_scope_prefix": "project:releng:flathub:firefox:", "push_to_flathub": True} if raises: with pytest.raises(TaskVerificationError): get_flatpak_channel(config, task) @@ -55,5 +55,5 @@ def test_get_flatpak_channel_prod(raises, scopes, channel): ), ) def test_is_allowed_to_push_to_flathub(channel, push_to_flathub, expected): - config = {"app_id": "org.mozilla.firefox", "taskcluster_scope_prefix": "project:releng:flathub:firefox:", "push_to_flathub": push_to_flathub} + config = {"app_ids": {"stable": "org.mozilla.firefox", "beta": "org.mozilla.firefox"}, "taskcluster_scope_prefix": "project:releng:flathub:firefox:", "push_to_flathub": push_to_flathub} assert is_allowed_to_push_to_flathub(config, channel) == expected From 8ec34a3470643db0948f63aaa82246f13263fde0 Mon Sep 17 00:00:00 2001 From: Stephen King Date: Wed, 11 Feb 2026 12:45:47 -0700 Subject: [PATCH 2/2] Fix PR Findings --- pushflatpakscript/docker.d/init_worker.sh | 23 +++++++++++++------ pushflatpakscript/docker.d/worker.yml | 21 ++++++++++++----- .../src/pushflatpakscript/flathub.py | 16 +++++++++++-- .../src/pushflatpakscript/task.py | 2 +- pushflatpakscript/tests/test_config.py | 5 ++-- pushflatpakscript/tests/test_task.py | 5 +++- tests/test_init.py | 2 ++ 7 files changed, 55 insertions(+), 19 deletions(-) diff --git a/pushflatpakscript/docker.d/init_worker.sh b/pushflatpakscript/docker.d/init_worker.sh index 356c951d8..4e065295f 100755 --- a/pushflatpakscript/docker.d/init_worker.sh +++ b/pushflatpakscript/docker.d/init_worker.sh @@ -26,8 +26,18 @@ case $ENV in echo $REPO_TOKEN_BETA | base64 -d > $REPO_TOKEN_BETA_PATH echo $REPO_TOKEN_STABLE | base64 -d > $REPO_TOKEN_STABLE_PATH - if [[$COT_PRODUCT == 'thunderbird']]; then - test_var_set 'REPO_TOKEN_ESR' + + if [ "$COT_PRODUCT" = thunderbird ]; then + # test_var_set 'REPO_TOKEN_RELEASE' + # must either have REPO_TOKEN_RELEASE or REPO_TOKEN_ESR defined + if [[ -z "$REPO_TOKEN_RELEASE" ]] && [[ -z "$REPO_TOKEN_ESR" ]]; then + echo "error: must have token defined for release or esr channel" + exit 1 + fi + + export REPO_TOKEN_RELEASE_PATH=$CONFIG_DIR/release_token.txt + echo $REPO_TOKEN_RELEASE | base64 -d > $REPO_TOKEN_RELEASE_PATH + export REPO_TOKEN_ESR_PATH=$CONFIG_DIR/esr_token.txt echo $REPO_TOKEN_ESR | base64 -d > $REPO_TOKEN_ESR_PATH fi @@ -39,14 +49,13 @@ esac case $COT_PRODUCT in firefox) - export APP_ID_BETA="org.mozilla.firefox" - export APP_ID_STABLE="org.mozilla.firefox" + export APP_ID="org.mozilla.firefox" export TASKCLUSTER_SCOPE_PREFIX="project:releng:flathub:firefox:" ;; thunderbird) - export APP_ID_BETA="org.mozilla.Thunderbird" - export APP_ID_STABLE="org.mozilla.ThunderbirdRelease" - export APP_ID_ESR="org.mozilla.Thunderbird" + export APP_ID="org.mozilla.Thunderbird" + export APP_ID_RELEASE="org.mozilla.ThunderbirdRelease" + export APP_ID_ESR="org.mozilla.ThunderbirdESR" export TASKCLUSTER_SCOPE_PREFIX="project:comm:thunderbird:releng:flathub:" ;; *) diff --git a/pushflatpakscript/docker.d/worker.yml b/pushflatpakscript/docker.d/worker.yml index 07c25b725..6703be247 100644 --- a/pushflatpakscript/docker.d/worker.yml +++ b/pushflatpakscript/docker.d/worker.yml @@ -2,11 +2,15 @@ work_dir: { "$eval": "WORK_DIR" } artifact_dir: { "$eval": "ARTIFACTS_DIR" } verbose: { "$eval": "VERBOSE == 'true'" } app_ids: - beta: {"$eval": "APP_ID_BETA" } - stable: {"$eval": "APP_ID_STABLE"} + beta: {"$eval": "APP_ID" } + stable: {"$eval": "APP_ID"} + release: + $if: defined("APP_ID_RELEASE") + then: {"$eval": "APP_ID_RELEASE"} + else: '' esr: - $if: 'COT_PRODUCT == "thunderbird"' - then: { "$eval": "APP_ID_ESR"} + $if: defined("APP_ID_ESR") + then: {"$eval": "APP_ID_ESR"} else: '' taskcluster_scope_prefix: { "$eval": "TASKCLUSTER_SCOPE_PREFIX" } push_to_flathub: { "$eval": "ENV == 'prod'" } @@ -18,8 +22,13 @@ token_locations: then: beta: { "$eval": "REPO_TOKEN_BETA_PATH" } stable: { "$eval": "REPO_TOKEN_STABLE_PATH" } + release: + $if: defined("REPO_TOKEN_RELEASE_PATH") + then: {"$eval": "REPO_TOKEN_RELEASE_PATH"} + else: '' esr: - $if: 'COT_PRODUCT == "thunderbird"' - then: { "$eval": "REPO_TOKEN_ESR_PATH" } + $if: defined("REPO_TOKEN_ESR_PATH") + then: {"$eval": "REPO_TOKEN_ESR_PATH"} else: '' + else: {} diff --git a/pushflatpakscript/src/pushflatpakscript/flathub.py b/pushflatpakscript/src/pushflatpakscript/flathub.py index 57fb77efa..84bd137f0 100644 --- a/pushflatpakscript/src/pushflatpakscript/flathub.py +++ b/pushflatpakscript/src/pushflatpakscript/flathub.py @@ -150,7 +150,7 @@ def check_app_id_matches_flatpak(context, flatpak_path, channel): flatpak_refs = [ref.split("/")[1] for ref in flatpak_refs if ref.startswith("app/")] # Create a list, if any, of all unexpected Flatpak IDs present in repo - invalid_refs = set(flatpak_refs) - {context.config["app_ids"]} + invalid_refs = set(flatpak_refs) - set(context.config["app_ids"].values()) if context.config["app_ids"][channel] not in flatpak_refs: raise TaskVerificationError(f"Supplied app ID ({context.config['app_ids'][channel]}) is not present in Flatpak!") @@ -159,6 +159,15 @@ def check_app_id_matches_flatpak(context, flatpak_path, channel): raise TaskVerificationError("One or more invalid app IDs are present in Flatpak!") +def check_config_for_channel(config, channel): + """Verify AppID and token location defined for supplied channel""" + if channel not in config["app_ids"]: + raise TaskVerificationError(f"Supplied channel ({channel}) does not have a configured appID") + + if channel not in config["token_locations"]: + raise TaskVerificationError(f"Supplied channel ({channel}) does not have a configured token") + + def sanitize_buildid(bytes_input): """Flathub API returns bytes to we're decoding that to unicode string""" return bytes_input.decode().strip() @@ -174,10 +183,13 @@ def push(context, flatpak_file_path, channel): # We don't raise an error because we still want green tasks on dev instances return + check_config_for_channel(context.config, channel) + token_args = ["--token-file", context.config["token_locations"][channel]] log.info("Grab a flatpak buildid from Flathub ...") + publish_channel = "beta" if channel == "beta" else "stable" publish_build_output = run_flat_manager_client_process( - context, token_args + ["create", context.config["flathub_url"], channel, "--build-log-url", build_log] + context, token_args + ["create", context.config["flathub_url"], publish_channel, "--build-log-url", build_log] ) log.info("Sanitize the buildid received from Flathub ...") diff --git a/pushflatpakscript/src/pushflatpakscript/task.py b/pushflatpakscript/src/pushflatpakscript/task.py index 5e93362a9..03630aff7 100644 --- a/pushflatpakscript/src/pushflatpakscript/task.py +++ b/pushflatpakscript/src/pushflatpakscript/task.py @@ -1,6 +1,6 @@ from scriptworker.exceptions import TaskVerificationError -_CHANNELS_AUTHORIZED_TO_REACH_FLATHUB = ("beta", "stable", "esr") +_CHANNELS_AUTHORIZED_TO_REACH_FLATHUB = ("beta", "stable", "release", "esr") ALLOWED_CHANNELS = ("mock", *_CHANNELS_AUTHORIZED_TO_REACH_FLATHUB) diff --git a/pushflatpakscript/tests/test_config.py b/pushflatpakscript/tests/test_config.py index 1952d5a98..e6705fc0e 100644 --- a/pushflatpakscript/tests/test_config.py +++ b/pushflatpakscript/tests/test_config.py @@ -9,8 +9,9 @@ "WORK_DIR": "", "ARTIFACTS_DIR": "", "VERBOSE": "true", - "APP_ID_STABLE": "", - "APP_ID_BETA": "", + "APP_ID": "", + "APP_ID_RELEASE": "", + "APP_ID_ESR": "", "COT_PRODUCT": "firefox", "TASKCLUSTER_SCOPE_PREFIX": "", "FLATHUB_URL": "https://flat.example", diff --git a/pushflatpakscript/tests/test_task.py b/pushflatpakscript/tests/test_task.py index f76b673fa..f1368526c 100644 --- a/pushflatpakscript/tests/test_task.py +++ b/pushflatpakscript/tests/test_task.py @@ -35,7 +35,10 @@ def test_get_flatpak_channel_dep(raises, channel): ) def test_get_flatpak_channel_prod(raises, scopes, channel): task = {"scopes": scopes, "payload": {"channel": channel}} - config = {"app_ids": {"stable": "org.mozilla.firefox", "beta": "org.mozilla.firefox"}, "taskcluster_scope_prefix": "project:releng:flathub:firefox:", "push_to_flathub": True} + config = {"app_ids": {"stable": "org.mozilla.firefox", "beta": "org.mozilla.firefox"}, + "token_locations": {"stable": "stable.txt", "beta": "beta.txt"}, + "taskcluster_scope_prefix": "project:releng:flathub:firefox:", + "push_to_flathub": True} if raises: with pytest.raises(TaskVerificationError): get_flatpak_channel(config, task) diff --git a/tests/test_init.py b/tests/test_init.py index ff5af21c1..1bb365ff3 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -78,6 +78,8 @@ "FLATHUB_URL": "https://flathub.example.com", "REPO_TOKEN_BETA": "Zm9vYmFyCg==", "REPO_TOKEN_STABLE": "Zm9vYmFyCg==", + "REPO_TOKEN_RELEASE": "Zm9vYmFyCg==", + "REPO_TOKEN_ESR": "Zm9vYmFyCg==", }, re.compile(r"pushmsix:.*"): { "TENANT_ID": "Zm9vYmFyCg==",