fix(release): sign CEF inner dylibs so macOS notarization passes (#951)

This commit is contained in:
Steven Enamakel
2026-04-26 13:07:21 -07:00
committed by GitHub
parent 2e4f1925f6
commit 1f4e151e59
4 changed files with 77 additions and 23 deletions
+2 -20
View File
@@ -464,7 +464,7 @@ jobs:
CORE_MANIFEST: ${{ steps.core-paths.outputs.core_manifest }}
CORE_BIN_NAME: ${{ steps.core-paths.outputs.core_bin_name }}
OPENHUMAN_APP_ENV: ${{ inputs.build_target == 'staging' && 'staging' || 'production' }}
OPENHUMAN_SENTRY_DSN: ${{ vars.OPENHUMAN_SENTRY_DSN }}
OPENHUMAN_SENTRY_DSN: ${{ vars.OPENHUMAN_CORE_SENTRY_DSN }}
# Sentry release tracking (#405): `option_env!("OPENHUMAN_BUILD_SHA")`
# in src/main.rs bakes the short SHA into the release tag
# (`openhuman@<version>+<sha>`) so core events match the frontend.
@@ -511,7 +511,7 @@ jobs:
# (`vite build`) bakes Sentry + debug flags into the final bundle.
# Vite is invoked via tauri.conf.json's beforeBuildCommand during
# `cargo tauri build`, so these env vars must be present here.
VITE_SENTRY_DSN: ${{ vars.VITE_SENTRY_DSN }}
VITE_SENTRY_DSN: ${{ vars.OPENHUMAN_REACT_SENTRY_DSN }}
VITE_DEBUG: ${{ vars.VITE_DEBUG }}
# Sentry release tracking (#405) — must match the Vite build triggered
# by Tauri so source maps uploaded there resolve correctly against the
@@ -804,24 +804,6 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# TODO: Uncomment this when we have a staging tag
# - name: Build and push staging tag
# uses: docker/build-push-action@v6
# with:
# context: .
# file: Dockerfile
# push: true
# tags: |
# ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:staging-${{ needs.prepare-release.outputs.tag }}
# cache-from: type=gha
# cache-to: type=gha,mode=max
# labels: |
# org.opencontainers.image.title=openhuman-core
# org.opencontainers.image.description=OpenHuman core JSON-RPC server
# org.opencontainers.image.version=${{ needs.prepare-release.outputs.version }}
# org.opencontainers.image.source=https://github.com/tinyhumansai/openhuman
# org.opencontainers.image.revision=${{ needs.prepare-release.outputs.sha }}
# =========================================================================
# Phase 3c: Generate and upload latest.json for the Tauri auto-updater.
# Runs after every platform has uploaded its updater artifact (.sig files
+6
View File
@@ -33,6 +33,12 @@ prompt-dumps/
scripts/ci-secrets.json
scripts/ci-secrets.local.json
# act (local GitHub Actions runner)
.secrets
.vars
.actrc
.github/act-event.json
# Editor directories and files
.idea
.DS_Store
+24 -1
View File
@@ -80,11 +80,34 @@ rm -f "$DMG_RW"
DMG_RW=""
echo "[dmg] Notarizing DMG..."
DMG_SUBMIT_OUT="$(mktemp /tmp/notarize-dmg-XXXXXX.json)"
set +e
xcrun notarytool submit "$DMG_PATH" \
--apple-id "$APPLE_ID" \
--password "$APPLE_PASSWORD" \
--team-id "$APPLE_TEAM_ID" \
--wait
--output-format json \
--wait > "$DMG_SUBMIT_OUT"
DMG_SUBMIT_RC=$?
set -e
cat "$DMG_SUBMIT_OUT"
DMG_SUBMISSION_ID="$(/usr/bin/python3 -c 'import json,sys; print(json.load(open(sys.argv[1])).get("id",""))' "$DMG_SUBMIT_OUT" 2>/dev/null || true)"
DMG_SUBMISSION_STATUS="$(/usr/bin/python3 -c 'import json,sys; print(json.load(open(sys.argv[1])).get("status",""))' "$DMG_SUBMIT_OUT" 2>/dev/null || true)"
rm -f "$DMG_SUBMIT_OUT"
if [ -n "$DMG_SUBMISSION_ID" ]; then
echo "[dmg] Fetching notarytool developer log for $DMG_SUBMISSION_ID:"
xcrun notarytool log "$DMG_SUBMISSION_ID" \
--apple-id "$APPLE_ID" \
--password "$APPLE_PASSWORD" \
--team-id "$APPLE_TEAM_ID" || true
fi
if [ "$DMG_SUBMISSION_STATUS" != "Accepted" ] || [ "$DMG_SUBMIT_RC" -ne 0 ]; then
echo "[dmg] ERROR: DMG notarization did not succeed (status=$DMG_SUBMISSION_STATUS, rc=$DMG_SUBMIT_RC)" >&2
exit 1
fi
xcrun stapler staple "$DMG_PATH"
echo "[dmg] DMG notarization complete: $DMG_PATH"
+45 -2
View File
@@ -78,8 +78,23 @@ codesign_framework() {
# ── Nested Frameworks/ (CEF + Helper apps) ──────────────────────────────────
# Must be signed from the inside out, before the outer .app bundle.
if [ -d "$APP_PATH/Contents/Frameworks" ]; then
# 1. Sign each *.framework as a single bundle.
# 1. For each *.framework: pre-sign loose dylibs/.so files inside it
# (CEF puts libEGL, libGLESv2, libvk_swiftshader, libcef_sandbox in
# `Libraries/` next to the main binary, NOT under Versions/A/, so the
# bundle signature doesn't reach them and notarization rejects them as
# ad-hoc signed without a secure timestamp). Then seal the framework
# bundle so its CodeResources covers the freshly-signed dylibs.
while IFS= read -r -d '' fw; do
FW_NAME="$(basename "$fw" .framework)"
echo "[sign] Pre-signing inner Mach-O files in: $(basename "$fw")"
while IFS= read -r -d '' inner; do
# Skip the framework's main binary (sealed by the bundle pass below).
case "$inner" in
"$fw/$FW_NAME"|"$fw/Versions/"*"/$FW_NAME") continue ;;
esac
echo "[sign] $(basename "$inner")"
codesign_framework "$inner"
done < <(find "$fw" \( -name '*.dylib' -o -name '*.so' \) -type f -print0)
echo "[sign] Signing framework bundle: $(basename "$fw")"
codesign_framework "$fw"
done < <(find "$APP_PATH/Contents/Frameworks" -maxdepth 1 -type d -name '*.framework' -print0)
@@ -121,16 +136,44 @@ echo "[sign] Notarizing..."
NOTARIZE_ZIP="$(mktemp /tmp/OpenHuman-notarize-XXXXXX.zip)"
ditto -c -k --keepParent "$APP_PATH" "$NOTARIZE_ZIP"
SUBMIT_OUT="$(mktemp /tmp/notarize-submit-XXXXXX.json)"
set +e
xcrun notarytool submit "$NOTARIZE_ZIP" \
--apple-id "$APPLE_ID" \
--password "$APPLE_PASSWORD" \
--team-id "$APPLE_TEAM_ID" \
--wait
--output-format json \
--wait > "$SUBMIT_OUT"
SUBMIT_RC=$?
set -e
cat "$SUBMIT_OUT"
rm -f "$NOTARIZE_ZIP"
SUBMISSION_ID="$(/usr/bin/plutil -convert json -o - "$SUBMIT_OUT" 2>/dev/null \
| /usr/bin/python3 -c 'import json,sys; print(json.load(sys.stdin).get("id",""))' 2>/dev/null || true)"
SUBMISSION_STATUS="$(/usr/bin/plutil -convert json -o - "$SUBMIT_OUT" 2>/dev/null \
| /usr/bin/python3 -c 'import json,sys; print(json.load(sys.stdin).get("status",""))' 2>/dev/null || true)"
rm -f "$SUBMIT_OUT"
echo "[sign] notarytool exit=$SUBMIT_RC id=$SUBMISSION_ID status=$SUBMISSION_STATUS"
if [ -n "$SUBMISSION_ID" ]; then
echo "[sign] Fetching notarytool developer log for $SUBMISSION_ID:"
xcrun notarytool log "$SUBMISSION_ID" \
--apple-id "$APPLE_ID" \
--password "$APPLE_PASSWORD" \
--team-id "$APPLE_TEAM_ID" || true
fi
if [ "$SUBMISSION_STATUS" != "Accepted" ] || [ "$SUBMIT_RC" -ne 0 ]; then
echo "[sign] ERROR: notarization did not succeed (status=$SUBMISSION_STATUS, rc=$SUBMIT_RC)" >&2
exit 1
fi
# ── Staple ───────────────────────────────────────────────────────────────────
echo "[sign] Stapling..."
xcrun stapler staple "$APP_PATH"
echo "[sign] Notarization complete"