mirror of
https://github.com/anomalyco/opencode.git
synced 2026-11-09 22:25:02 +03:00
89 lines
3.9 KiB
Bash
Executable File
89 lines
3.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# sign-desktop-macos.sh <out dir> <app tarball>...: signs each unsigned .app inside-out with hardened runtime,
|
|
# notarizes them in one submission, staples them, and only then builds opencode-desktop-mac-<arch>.{zip,dmg,app.tar.gz}
|
|
# from the stapled apps. Dry runs sign ad-hoc and skip notarization. Dev and beta trade larger files for faster
|
|
# packaging (zip and dmg at zlib level 1) and skip the .app.tar.gz, which only the retired Tauri updater feed read.
|
|
# Notarization reads APPLE_NOTARY_KEY (the .p8 contents), APPLE_NOTARY_KEY_ID and APPLE_NOTARY_ISSUER_ID.
|
|
. "$(dirname "$0")/lib.sh"
|
|
|
|
out=$1
|
|
shift
|
|
mkdir -p "$out"
|
|
apps=$(mktemp -d)
|
|
identity=- timestamp=--timestamp=none
|
|
zip_level=() dmg_level=() preview=false
|
|
case "$OPENCODE_CHANNEL" in dev | beta) preview=true ;; esac
|
|
if [ "$preview" = true ]; then zip_level=(--zlibCompressionLevel 1) dmg_level=(-imagekey zlib-level=1); fi
|
|
if ! dry_run; then
|
|
identity=$(security find-identity -v -p codesigning build.keychain | sed -n 's/.*"\(Developer ID Application:.*\)"/\1/p' | head -n 1)
|
|
[ -n "$identity" ] || die "Developer ID Application identity not found"
|
|
timestamp=--timestamp
|
|
fi
|
|
sign() {
|
|
codesign --force "$timestamp" --options runtime --entitlements "$2" --sign "$identity" "$1"
|
|
}
|
|
bundle() {
|
|
find "$apps/$1" -mindepth 1 -maxdepth 1 -name '*.app' -type d
|
|
}
|
|
|
|
for tarball in "$@"; do
|
|
arch=$(basename "$tarball" .app.tar)
|
|
arch=${arch#opencode-desktop-mac-}
|
|
[ "$arch" = arm64 ] || [ "$arch" = x64 ] || die "Unexpected app tarball: $tarball"
|
|
mkdir -p "$apps/$arch"
|
|
tar -xf "$tarball" -C "$apps/$arch"
|
|
if [ "$(find "$apps/$arch" -mindepth 1 -maxdepth 1 | wc -l | tr -d ' ')" != 1 ] || [ -z "$(bundle "$arch")" ]; then
|
|
die "Expected exactly one .app bundle in $tarball"
|
|
fi
|
|
app=$(bundle "$arch")
|
|
|
|
# Every nested Mach-O file and bundle, deepest first, then the app itself.
|
|
list=$(mktemp)
|
|
{
|
|
find "$app/Contents" -type f -print0 | while IFS= read -r -d '' file; do
|
|
case "$(file -b --mime-type "$file")" in application/x-mach-binary*) printf '%s\n' "$file" ;; esac
|
|
done
|
|
find "$app/Contents" -type d \( -name '*.app' -o -name '*.framework' \) -print
|
|
} | awk -F/ '{ print NF "\t" $0 }' | sort -t "$(printf '\t')" -k1,1nr | cut -f2- > "$list"
|
|
echo "Signing $(wc -l < "$list" | tr -d ' ') items in $app"
|
|
while IFS= read -r item; do
|
|
if [ "$item" = "$app/Contents/Resources/opencode-cli" ]; then
|
|
# The bundled Bun CLI loads bun-pty's native library; Electron and its helpers do not need this exception.
|
|
sign "$item" "$release_dir/entitlements/desktop-cli.plist"
|
|
else
|
|
sign "$item" "$release_dir/entitlements/desktop.plist"
|
|
fi
|
|
done < "$list"
|
|
sign "$app" "$release_dir/entitlements/desktop.plist"
|
|
codesign --verify --deep --strict --verbose=2 "$app"
|
|
done
|
|
|
|
if ! dry_run; then
|
|
key=$(mktemp)
|
|
printf '%s\n' "$APPLE_NOTARY_KEY" > "$key"
|
|
ditto -c -k --sequesterRsrc "$apps" "$apps.zip"
|
|
xcrun notarytool submit "$apps.zip" --key "$key" --key-id "$APPLE_NOTARY_KEY_ID" --issuer "$APPLE_NOTARY_ISSUER_ID" \
|
|
--wait --timeout 60m --output-format json > "$apps.json"
|
|
rm -f "$key"
|
|
cat "$apps.json"
|
|
[ "$(jq -r .status "$apps.json")" = Accepted ] || die "Notarization was not accepted"
|
|
fi
|
|
|
|
for dir in "$apps"/*; do
|
|
arch=$(basename "$dir")
|
|
app=$(bundle "$arch")
|
|
name=$(basename "$app")
|
|
if ! dry_run; then
|
|
xcrun stapler staple "$app"
|
|
xcrun stapler validate "$app"
|
|
spctl --assess --type execute --verbose=2 "$app"
|
|
fi
|
|
ditto -c -k ${zip_level[@]+"${zip_level[@]}"} --sequesterRsrc --keepParent "$app" "$out/opencode-desktop-mac-$arch.zip"
|
|
staging=$(mktemp -d)
|
|
ditto "$app" "$staging/$name"
|
|
ln -s /Applications "$staging/Applications"
|
|
hdiutil create -volname "${name%.app}" -srcfolder "$staging" -fs HFS+ -format UDZO ${dmg_level[@]+"${dmg_level[@]}"} -ov "$out/opencode-desktop-mac-$arch.dmg"
|
|
if [ "$preview" = true ]; then continue; fi
|
|
COPYFILE_DISABLE=1 tar --no-mac-metadata -czf "$out/opencode-desktop-mac-$arch.app.tar.gz" -C "$dir" "$name"
|
|
done
|