ci: publish a feat-cmux-next PR's cmux-tui merge tree from main (cx-73f2)

Merged
TE
25d ago
+457-0

Summary

cmux-next's same-tree cmux-tui check failed 55 times on 33 feat-cmux-next PRs in one day (2026-10-10/11), all with the same reason: no cmux-tui artifacts run can publish tree <key>.

  • A PR that changes a cmux-tui tree input has a merge tree that no push has published.
  • Its own pull_request run can't start that publish: its token gets 403 on the cmux-tui-pin-<sha12> ref and on the dispatch.
  • cmux-tui-artifacts.yml's pull_request_target trigger never fires, because GitHub reads pull_request_target workflows only from main.

This adds a small publisher on main, cmux-next-pr-merge-tree.yml. It runs as pull_request_target on feat-cmux-next PRs, from the same-repository author only, filtered to the tree-input paths.

What it runs (no PR code with secrets):

  • It checks out main only: the default branch, a sparse checkout of the publisher script, no credentials kept.
  • scripts/ci/publish_pr_merge_tree.py uses only the API:
    • waits for GitHub to compute the merge commit;
    • does nothing on a conflict or a newer head;
    • skips the dispatch when an artifacts run for that commit already ran or is running;
    • otherwise points cmux-tui-pin-<sha12> at the merge commit and dispatches cmux-tui-artifacts.yml there.
  • That dispatched run is the same one a push of that branch starts, which the author can already start by hand (pin-cmux-tui.sh --help). Fork PRs start nothing.
  • It runs on a GitHub-hosted runner, as test_ci_fork_runner_routing requires for pull_request_target. Permissions are contents: write, actions: write and pull-requests: read, all scoped to this job. An API failure fails the job loudly with ::error.

The feat-cmux-next side is the companion PR (linked below). There, the probe waits a bounded time for this publisher instead of failing on its own 403.

Testing

python3 tests/test_cmux_next_pr_merge_tree.py, 9 cases:

  • Red at 7260ce0c584f: no publisher.
  • Green after.
  • The publisher runs against a fake GitHub API and covers:
    • the merge commit appearing only after a few polls;
    • an active or already-successful run (no new dispatch);
    • a failed run (dispatched again);
    • an existing pin at the merge commit (reused) or at another commit (error);
    • a conflict or a newer head (nothing published);
    • a refused dispatch (::error).
  • Checks on the workflow itself: pull_request_target only, same repository only, the one checkout is the default branch, no PR refs.

Also run: test_ci_workflow_guards_are_wired, test_ci_fork_runner_routing, test_ci_linux_guard_routing and actionlint, all green. scripts/verify-local.py: 16 of 17 checks pass. The failing one is swift-syntax, on scripts/generate-computer-use-helper-icon.swift, which this PR doesn't touch, so it's already failing on main.

Changelog

none

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Summary by cubic

Fixes the same-tree cmux-tui check for feat-cmux-next pull requests, which failed 55 times on 33 PRs in a day because no run could start publishing a changed merge tree. Adds a pull_request_target workflow that does that publish from main.

  • Runs only for same-repository feat-cmux-next PRs changing a cmux-tui tree input; it checks out main and never runs the PR's code.
  • Waits for GitHub's merge commit and points cmux-tui-pin-<sha12> at it with the FFI release App's token (GITHUB_TOKEN gets 403 on refs at feat-cmux-next commits), dispatching cmux-tui-artifacts.yml unless a run for that commit is already active or succeeded.
  • Does nothing on conflicts or newer heads; fork PRs start nothing and API failures fail loudly.
  • Runs on a GitHub-hosted runner and is recorded as a github-hosted-required guard exception, since pull_request_target with a write token cannot use a self-hosted runner.
  • Adds scripts/ci/publish_pr_merge_tree.py with 9 tests against a fake GitHub API, plus CI-guard wiring.

Summary by CodeRabbit

  • Chores
    • Added automated merge-build artifact handling for eligible cmux-next pull requests from the same repository.
    • Existing successful or in-progress builds are reused when the merge commit matches; conflicting pull requests and pull requests whose source changes during processing are skipped.
    • Added coverage for the automation and included it in CI guard checks.