diff --git a/prepare_assets.sh b/prepare_assets.sh index ec1aaa80..72112ca9 100755 --- a/prepare_assets.sh +++ b/prepare_assets.sh @@ -12,6 +12,9 @@ if [[ "${OS_NAME}" == "osx" ]]; then if [[ "${CI_BUILD}" == "no" ]]; then RUNNER_TEMP="${TMPDIR}" fi + # Identity-based code-signing + Apple notarization path. + # Active when CERTIFICATE_OSX_P12_DATA is present (paid Apple Developer + # Program membership available). Produces Gatekeeper-clean builds. CERTIFICATE_P12="${APP_NAME}.p12" KEYCHAIN="${RUNNER_TEMP}/buildagent.keychain" @@ -203,6 +206,61 @@ if [[ "${OS_NAME}" == "osx" ]]; then rm "${ZIP_FILE}" + cd .. + else + # Ad-hoc signing fallback. + # Active when CERTIFICATE_OSX_P12_DATA is absent (no paid Apple Developer + # Program membership). Signs the bundle with the ad-hoc identity ("-") so + # the .app is structurally valid (nested Helpers verify, dyld accepts + # hardened binaries on Apple Silicon) without requiring a Developer ID + # cert or paying Apple's notarization fee. Notarization and stapling are + # skipped — users will see a Gatekeeper "unverified developer" prompt on + # first launch and need to right-click → Open (or run xattr -cr on the + # .app). This matches what VSCodium, MacVim, and most open-source macOS + # apps ship. + echo "+ APPLE_ID not set — using ad-hoc signing, skipping notarization. Users will need to bypass Gatekeeper on first launch." + + cd "VSCode-darwin-${VSCODE_ARCH}" + + APP_BUNDLE=$( find . -maxdepth 1 -name "*.app" -type d | head -n 1 ) + if [[ -z "${APP_BUNDLE}" ]]; then + echo "Error: No .app bundle found in VSCode-darwin-${VSCODE_ARCH}" + ls -la + exit 1 + fi + APP_BUNDLE="${APP_BUNDLE#./}" + + # Sign every nested Mach-O first (helpers, frameworks, dylibs, language + # binaries), then sign the outer .app bundle. `--deep` on the outer call + # is not sufficient on its own because some nested signables (e.g. the + # Electron Framework helpers, embedded node binaries) need to be signed + # bottom-up to satisfy the runtime loader on Apple Silicon. + echo "+ ad-hoc signing nested binaries" + find "${APP_BUNDLE}" \ + \( -name '*.dylib' -o -name '*.framework' -o -name '*.node' \ + -o -name '*.app' \) \ + -print0 | + while IFS= read -r -d '' nested; do + # Skip the outer .app itself; we sign it last. + if [[ "${nested}" == "${APP_BUNDLE}" ]]; then + continue + fi + codesign --force --sign - --timestamp=none "${nested}" || { + echo "Warning: ad-hoc sign failed for ${nested}" + } + done + + echo "+ ad-hoc signing app bundle (deep)" + codesign --force --deep --sign - --timestamp=none "${APP_BUNDLE}" + + echo "+ verifying ad-hoc signature" + if ! codesign --verify --deep --strict --verbose=2 "${APP_BUNDLE}" 2>&1; then + echo "Error: Ad-hoc signature verification failed" + codesign -dv --verbose=4 "${APP_BUNDLE}" 2>&1 + exit 1 + fi + echo "✓ Ad-hoc signature is valid (Gatekeeper will still prompt users on first launch)" + cd .. fi