From b04f07f2d162fcf629d0fdaedf4be5c0dba3ed3e Mon Sep 17 00:00:00 2001 From: Lawrence Chen <54008264+lawrencecchen@users.noreply.github.com> Date: Wed, 30 Sep 2026 15:46:08 -0700 Subject: [PATCH 1/2] test(ci): cmux-tui artifact publishing must run in the artifacts environment #16171 put the cmux-tui publish job in the release environment, whose policy allows only main and v* tags, so helper-branch pin publishes fail before any step runs. Co-Authored-By: Claude Opus 5.5 (1M context) --- ...est_ci_production_secrets_protected_env.py | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/tests/test_ci_production_secrets_protected_env.py b/tests/test_ci_production_secrets_protected_env.py index ba7d6865788f..d633efc8c7d7 100755 --- a/tests/test_ci_production_secrets_protected_env.py +++ b/tests/test_ci_production_secrets_protected_env.py @@ -5,7 +5,7 @@ ref the dispatcher picks, so any condition written in the workflow can be edited away on a branch. GitHub enforces an environment's deployment branch policy outside the workflow: these jobs declare the `release` environment -(policy: branch main, tags v*), or a cloud-vm environment with its own +(policy: branch main, tags v*), the artifacts environment, or a cloud-vm environment with its own policy, and their production secrets live in that environment. The iroh release gate checks out a requested ref; its job with production @@ -13,6 +13,7 @@ """ import os +import re import sys import yaml @@ -21,6 +22,15 @@ WORKFLOWS = os.path.join(ROOT, ".github", "workflows") FAILURES = [] +# Publishing a commit-addressed cmux-tui build is not a production release: +# cmux-next pins daemon builds from helper branches (cmux-tui-pin-*). That job +# runs in the `artifacts` environment (policy: main, feat-cmux-next, +# cmux-tui-pin-*), which holds only the R2 upload credentials. +ARTIFACT_JOBS = { + "cmux-tui-artifacts.yml": ["publish"], +} +ARTIFACT_SECRETS = {"CF_R2_ACCESS_KEY_ID", "CF_R2_SECRET_ACCESS_KEY", "CF_R2_ACCOUNT_ID"} + RELEASE_JOBS = { "release.yml": ["build-sign-notarize"], "nightly.yml": ["build-sign-notarize-nightly", "publish-nightly"], @@ -29,7 +39,6 @@ "ios-appstore-upload.yml": ["set-testflight-notes", "assign-internal"], "repair-v0-64-25-helper-rpaths.yml": ["repair"], "iroh-release-gate.yml": ["simulator-e2e"], - "cmux-tui-artifacts.yml": ["publish"], "repair-nightly-appcast-content-types.yml": ["repair"], "update-homebrew.yml": ["update-cask"], } @@ -49,6 +58,14 @@ def main(): for job in jobs: definition = document["jobs"].get(job, {}) _check(definition.get("environment") == "release", f"{name} {job} runs in the release environment") + for name, jobs in ARTIFACT_JOBS.items(): + text = open(os.path.join(WORKFLOWS, name), encoding="utf-8").read() + document = yaml.load(text, Loader=yaml.BaseLoader) + for job in jobs: + definition = document["jobs"].get(job, {}) + _check(definition.get("environment") == "artifacts", f"{name} {job} runs in the artifacts environment") + used = set(re.findall(r"secrets\.([A-Za-z0-9_]+)", yaml.dump(definition))) + _check(used <= ARTIFACT_SECRETS, f"{name} {job} uses only R2 upload secrets (found {sorted(used)})") gate = yaml.load(open(os.path.join(WORKFLOWS, "iroh-release-gate.yml"), encoding="utf-8"), Loader=yaml.BaseLoader) condition = " ".join(str(gate["jobs"]["simulator-e2e"].get("if", "")).split()) _check( From fa3bedbab5e22779b651407ec2b4798ddb9e1862 Mon Sep 17 00:00:00 2001 From: Lawrence Chen <54008264+lawrencecchen@users.noreply.github.com> Date: Wed, 30 Sep 2026 15:46:10 -0700 Subject: [PATCH 2/2] fix(ci): cmux-tui artifact publishing runs in the artifacts environment The artifacts environment holds only the R2 upload credentials and allows main, feat-cmux-next and cmux-tui-pin-* helper branches, so daemon pin publishes work again while signing, Sparkle, Homebrew and Apple secrets stay in release (main and v* tags only). Co-Authored-By: Claude Opus 5.5 (1M context) --- .github/workflows/cmux-tui-artifacts.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/cmux-tui-artifacts.yml b/.github/workflows/cmux-tui-artifacts.yml index df3db9a7c632..4e1ac62a93f3 100644 --- a/.github/workflows/cmux-tui-artifacts.yml +++ b/.github/workflows/cmux-tui-artifacts.yml @@ -89,9 +89,12 @@ jobs: macos_runner: ${{ inputs.macos_runner || vars.MACOS_RUNNER_BACKGROUND || 'macos-15' }} publish: - # Production secrets: GitHub releases them only to protected refs (the - # environment's deployment branch policy: main, tags v*). - environment: release + # R2 upload credentials only. A commit-addressed cmux-tui build is not a + # production release: cmux-next pins daemon builds from helper branches. + # The artifacts environment's deployment branch policy allows main, + # feat-cmux-next and cmux-tui-pin-*; signing, Sparkle, Homebrew and Apple + # secrets stay in the release environment. + environment: artifacts name: publish to R2 # PR runs of this workflow only validate the build; publishing is # main-push or manual dispatch.