From 629af67d82c489082c58b10f3d5bd18740dd5475 Mon Sep 17 00:00:00 2001 From: Bruno Alexandre Rosa <1791393+brunoalr@users.noreply.github.com> Date: Sat, 14 Mar 2026 15:55:55 -0300 Subject: [PATCH 1/5] chore: add script to enable running unsigned macOS builds from CI locally --- .github/workflows/desktop-build.yml | 2 + scripts/macos_fix_codesign.sh | 97 +++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100755 scripts/macos_fix_codesign.sh diff --git a/.github/workflows/desktop-build.yml b/.github/workflows/desktop-build.yml index f99c91abb..85f4c88ed 100644 --- a/.github/workflows/desktop-build.yml +++ b/.github/workflows/desktop-build.yml @@ -17,6 +17,7 @@ on: - '!.husky/**' - '!.tx/**' - '!doc/**' + - '!scripts/**' - '!webclient/**' - '.github/workflows/desktop-build.yml' - 'CMakeLists.txt' @@ -32,6 +33,7 @@ on: - '!.husky/**' - '!.tx/**' - '!doc/**' + - '!scripts/**' - '!webclient/**' - '.github/workflows/desktop-build.yml' - 'CMakeLists.txt' diff --git a/scripts/macos_fix_codesign.sh b/scripts/macos_fix_codesign.sh new file mode 100755 index 000000000..5ca9a7063 --- /dev/null +++ b/scripts/macos_fix_codesign.sh @@ -0,0 +1,97 @@ +#!/bin/bash +# Fix code signing for unsigned macOS app bundles (mainly used to test packages from PRs on CI). +# Run from project root: ./scripts/macos_fix_codesign.sh [path/to/app.app ...] +# +# Steps: +# 1. Remove quarantine extended attribute +# 2. Ad-hoc sign all dylibs, frameworks and executables inside the bundle +# 3. Deep sign the app bundle +# +# Use after installing an unsigned build to /Applications. +# With no args, fixes cockatrice, oracle, and servatrice in /Applications. + +set -eo pipefail + +DEFAULT_APPS=( + /Applications/cockatrice.app + /Applications/oracle.app + /Applications/servatrice.app +) + +is_safe_app_bundle() { + local resolved_app="$1" + + [[ "$resolved_app" == *.app ]] || { echo "Error: Path must end with .app (got '$resolved_app')" >&2; return 1; } + + case "$resolved_app" in + / | /Applications/ | /System | /Users | /usr | /Library) + echo "Error: Path '$resolved_app' is a system-critical directory" >&2 + return 1 + ;; + /System/* | /usr/* | /Library/*) + echo "Error: Path '$resolved_app' is under a system-critical directory" >&2 + return 1 + ;; + *) + # Not a system-critical directory; continue validation + ;; + esac + + [[ -d "$resolved_app/Contents" ]] || { echo "Error: Path '$resolved_app' lacks Contents/ (not a valid app bundle)" >&2; return 1; } + + return 0 +} + +fix_app() { + local app="$1" + if [[ ! -d "$app" ]]; then + echo "Skipping (not found): $app" + return 0 + fi + + if [[ -L "$app" ]]; then + echo "Error: Symlinks are not allowed (got '$app'). Use a real path to the app bundle." >&2 + return 1 + fi + + local resolved_app + resolved_app="$(cd -P -- "$app" && pwd -P)" || { + echo "Error: Failed to resolve path '$app'" >&2 + return 1 + } + + if ! is_safe_app_bundle "$resolved_app"; then + echo "Error: '$app' is not a valid app bundle path. Use a path ending in .app (e.g. /Applications/MyApp.app)." >&2 + return 1 + fi + + echo "Fixing code signing for: $app" + + # 1. Remove quarantine + echo " Removing quarantine..." + xattr -dr com.apple.quarantine "$resolved_app" + + # 2. Ad-hoc sign all binaries and dylibs + echo " Signing dylibs, frameworks and executables..." + # find .dylib files by name and executable files (binaries, frameworks, etc.) by permission via `-perm +111` + find "$resolved_app" -type f \( -name "*.dylib" -o -perm +111 \) -print0 | \ + xargs -0 -I {} codesign -s - -f {} + + # 3. Deep sign the app bundle + echo " Deep signing app bundle..." + codesign -s - --force --deep "$resolved_app" + + echo " Done." +} + +if [[ $# -gt 0 ]]; then + for app in "$@"; do + fix_app "$app" + done +else + for app in "${DEFAULT_APPS[@]}"; do + fix_app "$app" + done +fi + +echo "All done. Try: open /Applications/cockatrice.app" From 8b95c10bac85f3cc9c4a809ab44ff3f2982cc5c6 Mon Sep 17 00:00:00 2001 From: Bruno Alexandre Rosa <1791393+brunoalr@users.noreply.github.com> Date: Sat, 14 Mar 2026 17:27:57 -0300 Subject: [PATCH 2/5] be extremely defensive against malformed input --- scripts/macos_fix_codesign.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/macos_fix_codesign.sh b/scripts/macos_fix_codesign.sh index 5ca9a7063..141e85a46 100755 --- a/scripts/macos_fix_codesign.sh +++ b/scripts/macos_fix_codesign.sh @@ -69,17 +69,17 @@ fix_app() { # 1. Remove quarantine echo " Removing quarantine..." - xattr -dr com.apple.quarantine "$resolved_app" + xattr -dr com.apple.quarantine -- "$resolved_app" # 2. Ad-hoc sign all binaries and dylibs echo " Signing dylibs, frameworks and executables..." # find .dylib files by name and executable files (binaries, frameworks, etc.) by permission via `-perm +111` - find "$resolved_app" -type f \( -name "*.dylib" -o -perm +111 \) -print0 | \ - xargs -0 -I {} codesign -s - -f {} + find -- "$resolved_app" -type f \( -name "*.dylib" -o -perm +111 \) -print0 | \ + xargs -0 -I {} codesign -s - -f -- {} # 3. Deep sign the app bundle echo " Deep signing app bundle..." - codesign -s - --force --deep "$resolved_app" + codesign -s - --force --deep -- "$resolved_app" echo " Done." } From e89236142ed9ceefbd673ad7a6729435efd2e91b Mon Sep 17 00:00:00 2001 From: Bruno Alexandre Rosa <1791393+brunoalr@users.noreply.github.com> Date: Sat, 14 Mar 2026 17:29:39 -0300 Subject: [PATCH 3/5] rename to utils --- .github/workflows/desktop-build.yml | 4 ++-- {scripts => utils}/macos_fix_codesign.sh | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename {scripts => utils}/macos_fix_codesign.sh (97%) diff --git a/.github/workflows/desktop-build.yml b/.github/workflows/desktop-build.yml index 85f4c88ed..3c3fe6dfd 100644 --- a/.github/workflows/desktop-build.yml +++ b/.github/workflows/desktop-build.yml @@ -17,7 +17,7 @@ on: - '!.husky/**' - '!.tx/**' - '!doc/**' - - '!scripts/**' + - '!utils/**' - '!webclient/**' - '.github/workflows/desktop-build.yml' - 'CMakeLists.txt' @@ -33,7 +33,7 @@ on: - '!.husky/**' - '!.tx/**' - '!doc/**' - - '!scripts/**' + - '!utils/**' - '!webclient/**' - '.github/workflows/desktop-build.yml' - 'CMakeLists.txt' diff --git a/scripts/macos_fix_codesign.sh b/utils/macos_fix_codesign.sh similarity index 97% rename from scripts/macos_fix_codesign.sh rename to utils/macos_fix_codesign.sh index 141e85a46..6ff3305a4 100755 --- a/scripts/macos_fix_codesign.sh +++ b/utils/macos_fix_codesign.sh @@ -1,6 +1,6 @@ #!/bin/bash # Fix code signing for unsigned macOS app bundles (mainly used to test packages from PRs on CI). -# Run from project root: ./scripts/macos_fix_codesign.sh [path/to/app.app ...] +# Run from project root: ./utils/macos_fix_codesign.sh [path/to/app.app ...] # # Steps: # 1. Remove quarantine extended attribute From be24bd5d7d5dbaac3d8a2d242830e0f969852112 Mon Sep 17 00:00:00 2001 From: Bruno Alexandre Rosa <1791393+brunoalr@users.noreply.github.com> Date: Sat, 14 Mar 2026 17:33:42 -0300 Subject: [PATCH 4/5] add readme, improve comment --- utils/macos_fix_codesign.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/utils/macos_fix_codesign.sh b/utils/macos_fix_codesign.sh index 6ff3305a4..38089c357 100755 --- a/utils/macos_fix_codesign.sh +++ b/utils/macos_fix_codesign.sh @@ -1,7 +1,11 @@ #!/bin/bash -# Fix code signing for unsigned macOS app bundles (mainly used to test packages from PRs on CI). +# Fixes code signing for unsigned macOS app bundles. Use after installing an unsigned build (e.g. from a PR artifact) to `/Applications` so the apps can be opened without Gatekeeper blocking them. # Run from project root: ./utils/macos_fix_codesign.sh [path/to/app.app ...] # +# Example usage: +# ./utils/macos_fix_codesign.sh # fixes cockatrice, oracle, and servatrice in /Applications +# ./utils/macos_fix_codesign.sh /Applications/cockatrice.app # fixes only cockatrice +# # Steps: # 1. Remove quarantine extended attribute # 2. Ad-hoc sign all dylibs, frameworks and executables inside the bundle From dc5c49118ffa2b16156a558f380496eea02d39e3 Mon Sep 17 00:00:00 2001 From: Bruno Alexandre Rosa <1791393+brunoalr@users.noreply.github.com> Date: Sat, 14 Mar 2026 17:50:16 -0300 Subject: [PATCH 5/5] add readme --- utils/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 utils/README.md diff --git a/utils/README.md b/utils/README.md new file mode 100644 index 000000000..84cd4f176 --- /dev/null +++ b/utils/README.md @@ -0,0 +1,3 @@ +# Utils + +Helper scripts for local development and testing (not used by CI).