ci(cmux-next): key the compiled DEV Release app by its content
Leo: "the incrementally, you know, tracking the latest commit or whatever, building it off the right way, building the right things, like reusing as much as you can"
What
Part 1 of 2 for reusing the compiled cmux NEXT DEV Release app. This part adds only the key; nothing uses it yet. Part 2 (stacked on this branch) adds the lookup and record steps around the DEV Release compile.
job_input_fingerprint.py dev-release-product hashes the git object ids of every tree path that can reach the DEV Release app. That is the whole tree minus PRODUCT_EXCLUDES: docs and plan prose, tests (including each package's Tests/), other workflows, agent config, benchmarks, and the iOS, web, backend and agent-chat products. On top of that it hashes the whole cmux-next.yml, Xcode, the SDK, the arch, a recipe version and the bundled cmux-tui tree. The key is content only, with no branch, commit or path in it. The tree that gets hashed is the one the job checked out and builds, which is the pushed or dispatched commit (the DEV compile never runs on pull requests).
How the closure is built (broad on purpose):
- A path no rule names counts as an input, so a new directory invalidates reuse by default.
- Some paths inside excluded areas stay inputs:
- every path another input list already names (the Release compile's list and the web bundle inputs: this workflow,
.github/actions,docs/mdm,tests/fixtures/classic-to-next,web/data/model-catalog); - every path in
cmux-tui-tree-inputs.txt, which includes the fixtures underbackend/andPackages/.../Teststhat the bundled cmux-tui is built from; - every file
cmux.xcodeprojnames relative to the repository root. That is howTHIRD_PARTY_LICENSES.mdstays an input: the app bundles it, so top-level Markdown is not excluded.
- every path another input list already names (the Release compile's list and the web bundle inputs: this workflow,
- Tests that hold this in CI: every Xcode-project root reference is an input; no package target under
Tests/is shipped (CmuxNextTestExitTraceandCmuxHomeCoreTestSupportare test support only, and any new one fails the test); and each product input changes the key while each excluded path does not.
Replayed over the last 199 feat-cmux-next merges, 49 (25%) keep the key of the merge before them. Those are the merges that will skip the Mac compile.
Success / failure
- Success: the same tree gives the same key under any commit, and every path that reaches the app changes it (tests/test_dev_release_product_key.py).
- Failure: a path that reaches the app is outside the key, which would ship a stale app. That is why the closure defaults to including everything.
Risk
Low. This PR adds a key with no consumer. The risk is in the exclusion list, which part 2 relies on. The list is short, and the tests above pin it.
Tests: tests/test_dev_release_product_key.py, run in the cmux-next checks job.
Agent session: cosmic-gray
š¤ Generated with Claude Code
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.