Merge origin/main into pr-ssh-stack-main

This commit is contained in:
Lawrence Chen 2026-03-13 06:25:08 -07:00
commit 965965c879
12 changed files with 1077 additions and 83 deletions

View file

@ -13,10 +13,9 @@ on:
concurrency:
group: nightly-build-${{ github.ref_name }}
# Queue main pushes instead of hard-canceling older runs. The decide job
# already coalesces to the current main HEAD, and we re-check HEAD before
# publishing so stale queued runs exit cleanly instead of showing up red.
cancel-in-progress: false
# Only the newest nightly matters. Cancel older runs so a fresh main push
# does not sit behind an outdated build that would be discarded anyway.
cancel-in-progress: true
permissions:
contents: write
@ -102,7 +101,7 @@ jobs:
build-sign-notarize-nightly:
needs: decide
if: needs.decide.outputs.should_build == 'true'
runs-on: macos-15
runs-on: depot-macos-latest
steps:
- name: Checkout build ref
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
@ -110,7 +109,29 @@ jobs:
ref: ${{ needs.decide.outputs.head_sha }}
submodules: recursive
- name: Check whether build commit is still current main HEAD before build
if: needs.decide.outputs.should_publish == 'true'
id: current_head_prebuild
run: |
set -euo pipefail
CURRENT_MAIN_SHA="$(git ls-remote origin refs/heads/main | awk '{print $1}')"
BUILD_SHA="${{ needs.decide.outputs.head_sha }}"
if [ "$CURRENT_MAIN_SHA" = "$BUILD_SHA" ]; then
STILL_CURRENT=true
else
STILL_CURRENT=false
fi
echo "still_current=${STILL_CURRENT}" >> "$GITHUB_OUTPUT"
{
echo "### Pre-build publish guard"
echo
echo "- build sha: \`$BUILD_SHA\`"
echo "- current main sha: \`$CURRENT_MAIN_SHA\`"
echo "- continue build/sign/publish: \`$STILL_CURRENT\`"
} >> "$GITHUB_STEP_SUMMARY"
- name: Select Xcode
if: needs.decide.outputs.should_publish != 'true' || steps.current_head_prebuild.outputs.still_current == 'true'
run: |
set -euo pipefail
if [ -d "/Applications/Xcode.app/Contents/Developer" ]; then
@ -130,14 +151,17 @@ jobs:
xcrun --sdk macosx --show-sdk-path
- name: Install build deps
if: needs.decide.outputs.should_publish != 'true' || steps.current_head_prebuild.outputs.still_current == 'true'
run: |
npm install --global "create-dmg@${CREATE_DMG_VERSION}"
- name: Download pre-built GhosttyKit.xcframework
if: needs.decide.outputs.should_publish != 'true' || steps.current_head_prebuild.outputs.still_current == 'true'
run: |
./scripts/download-prebuilt-ghosttykit.sh
- name: Cache Swift packages
if: needs.decide.outputs.should_publish != 'true' || steps.current_head_prebuild.outputs.still_current == 'true'
uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4
with:
path: .spm-cache
@ -150,6 +174,7 @@ jobs:
go-version-file: daemon/remote/go.mod
- name: Derive Sparkle public key from private key
if: needs.decide.outputs.should_publish != 'true' || steps.current_head_prebuild.outputs.still_current == 'true'
env:
SPARKLE_PRIVATE_KEY: ${{ secrets.SPARKLE_PRIVATE_KEY }}
run: |
@ -162,6 +187,7 @@ jobs:
echo "SPARKLE_PUBLIC_KEY=$DERIVED_PUBLIC_KEY" >> "$GITHUB_ENV"
- name: Build universal nightly app (Release)
if: needs.decide.outputs.should_publish != 'true' || steps.current_head_prebuild.outputs.still_current == 'true'
run: |
xcodebuild -scheme cmux -configuration Release -derivedDataPath build-universal \
-destination 'generic/platform=macOS' \
@ -171,6 +197,7 @@ jobs:
CODE_SIGNING_ALLOWED=NO ASSETCATALOG_COMPILER_APPICON_NAME=AppIcon-Nightly build
- name: Verify nightly binary architectures
if: needs.decide.outputs.should_publish != 'true' || steps.current_head_prebuild.outputs.still_current == 'true'
run: |
set -euo pipefail
APP_BINARY="build-universal/Build/Products/Release/cmux.app/Contents/MacOS/cmux"
@ -183,15 +210,16 @@ jobs:
[[ "$CLI_ARCHS" == *arm64* && "$CLI_ARCHS" == *x86_64* ]]
- name: Run CLI version memory guard regression
if: needs.decide.outputs.should_publish != 'true' || steps.current_head_prebuild.outputs.still_current == 'true'
run: |
set -euo pipefail
CLI_BINARY="build-universal/Build/Products/Release/cmux.app/Contents/Resources/bin/cmux"
[ -x "$CLI_BINARY" ] || { echo "cmux CLI binary not found at $CLI_BINARY" >&2; exit 1; }
CMUX_CLI_BIN="$CLI_BINARY" python3 tests/test_cli_version_memory_guard.py
- name: Check whether build commit is still current main HEAD
if: needs.decide.outputs.should_publish == 'true'
id: current_head
- name: Check whether build commit is still current main HEAD after build
if: needs.decide.outputs.should_publish == 'true' && steps.current_head_prebuild.outputs.still_current == 'true'
id: current_head_postbuild
run: |
set -euo pipefail
CURRENT_MAIN_SHA="$(git ls-remote origin refs/heads/main | awk '{print $1}')"
@ -203,7 +231,7 @@ jobs:
fi
echo "still_current=${STILL_CURRENT}" >> "$GITHUB_OUTPUT"
{
echo "### Publish guard"
echo "### Post-build publish guard"
echo
echo "- build sha: \`$BUILD_SHA\`"
echo "- current main sha: \`$CURRENT_MAIN_SHA\`"
@ -211,7 +239,7 @@ jobs:
} >> "$GITHUB_STEP_SUMMARY"
- name: Inject nightly identities and metadata
if: needs.decide.outputs.should_publish != 'true' || steps.current_head.outputs.still_current == 'true'
if: needs.decide.outputs.should_publish != 'true' || (steps.current_head_prebuild.outputs.still_current == 'true' && steps.current_head_postbuild.outputs.still_current == 'true')
run: |
set -euo pipefail
SHORT_SHA="${{ needs.decide.outputs.short_sha }}"
@ -285,7 +313,7 @@ jobs:
done
- name: Import signing cert
if: needs.decide.outputs.should_publish != 'true' || steps.current_head.outputs.still_current == 'true'
if: needs.decide.outputs.should_publish != 'true' || (steps.current_head_prebuild.outputs.still_current == 'true' && steps.current_head_postbuild.outputs.still_current == 'true')
env:
APPLE_CERTIFICATE_BASE64: ${{ secrets.APPLE_CERTIFICATE_BASE64 }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
@ -309,7 +337,7 @@ jobs:
security list-keychains -d user -s build.keychain
- name: Codesign apps
if: needs.decide.outputs.should_publish != 'true' || steps.current_head.outputs.still_current == 'true'
if: needs.decide.outputs.should_publish != 'true' || (steps.current_head_prebuild.outputs.still_current == 'true' && steps.current_head_postbuild.outputs.still_current == 'true')
env:
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
run: |
@ -330,7 +358,7 @@ jobs:
done
- name: Notarize apps and dmgs
if: needs.decide.outputs.should_publish != 'true' || steps.current_head.outputs.still_current == 'true'
if: needs.decide.outputs.should_publish != 'true' || (steps.current_head_prebuild.outputs.still_current == 'true' && steps.current_head_postbuild.outputs.still_current == 'true')
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
@ -395,7 +423,7 @@ jobs:
"$NIGHTLY_DMG_IMMUTABLE"
- name: Upload dSYMs to Sentry
if: needs.decide.outputs.should_publish != 'true' || steps.current_head.outputs.still_current == 'true'
if: needs.decide.outputs.should_publish != 'true' || (steps.current_head_prebuild.outputs.still_current == 'true' && steps.current_head_postbuild.outputs.still_current == 'true')
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_ORG: manaflow
@ -410,7 +438,7 @@ jobs:
build-universal/Build/Products/Release/
- name: Generate Sparkle appcasts (nightly)
if: needs.decide.outputs.should_publish != 'true' || steps.current_head.outputs.still_current == 'true'
if: needs.decide.outputs.should_publish != 'true' || (steps.current_head_prebuild.outputs.still_current == 'true' && steps.current_head_postbuild.outputs.still_current == 'true')
env:
SPARKLE_PRIVATE_KEY: ${{ secrets.SPARKLE_PRIVATE_KEY }}
run: |
@ -419,6 +447,9 @@ jobs:
exit 1
fi
./scripts/sparkle_generate_appcast.sh "$NIGHTLY_DMG_IMMUTABLE" nightly appcast.xml
# Keep the legacy universal feed alive long enough for older nightly
# installs to migrate onto the unified nightly appcast.
cp appcast.xml appcast-universal.xml
- name: Attest remote daemon nightly assets
if: needs.decide.outputs.should_publish != 'true' || steps.current_head.outputs.still_current == 'true'
@ -440,16 +471,20 @@ jobs:
path: |
cmux-nightly-macos*.dmg
appcast.xml
<<<<<<< HEAD
remote-daemon-assets/cmuxd-remote-darwin-arm64
remote-daemon-assets/cmuxd-remote-darwin-amd64
remote-daemon-assets/cmuxd-remote-linux-arm64
remote-daemon-assets/cmuxd-remote-linux-amd64
remote-daemon-assets/cmuxd-remote-checksums.txt
remote-daemon-assets/cmuxd-remote-manifest.json
=======
appcast-universal.xml
>>>>>>> origin/main
if-no-files-found: error
- name: Move nightly tag to built commit
if: needs.decide.outputs.should_publish == 'true' && steps.current_head.outputs.still_current == 'true'
if: needs.decide.outputs.should_publish == 'true' && steps.current_head_prebuild.outputs.still_current == 'true' && steps.current_head_postbuild.outputs.still_current == 'true'
run: |
set -euo pipefail
git config user.name "github-actions[bot]"
@ -458,7 +493,7 @@ jobs:
git push origin refs/tags/nightly --force
- name: Publish nightly release assets
if: needs.decide.outputs.should_publish == 'true' && steps.current_head.outputs.still_current == 'true'
if: needs.decide.outputs.should_publish == 'true' && steps.current_head_prebuild.outputs.still_current == 'true' && steps.current_head_postbuild.outputs.still_current == 'true'
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2
with:
tag_name: nightly
@ -471,18 +506,23 @@ jobs:
**cmux NIGHTLY** is published as a universal app:
- bundle ID `com.cmuxterm.app.nightly`
- feed `appcast.xml`
- compatibility feed `appcast-universal.xml` for older universal nightlies
[Download cmux-nightly-macos.dmg](https://github.com/manaflow-ai/cmux/releases/download/nightly/cmux-nightly-macos.dmg)
files: |
cmux-nightly-macos-${{ github.run_id }}*.dmg
cmux-nightly-macos.dmg
appcast.xml
<<<<<<< HEAD
remote-daemon-assets/cmuxd-remote-darwin-arm64
remote-daemon-assets/cmuxd-remote-darwin-amd64
remote-daemon-assets/cmuxd-remote-linux-arm64
remote-daemon-assets/cmuxd-remote-linux-amd64
remote-daemon-assets/cmuxd-remote-checksums.txt
remote-daemon-assets/cmuxd-remote-manifest.json
=======
appcast-universal.xml
>>>>>>> origin/main
overwrite_files: true
- name: Cleanup keychain