Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,57 @@ jobs:
releaseId: ${{ needs.draft.outputs.id }}
args: --target ${{ matrix.target }} --config src-tauri/tauri.release.conf.json

# Ad-hoc signing the executable is not the same as sealing the bundle
# around it. Without a `_CodeSignature` covering the sidecars, macOS
# calls the app damaged and offers only the Trash — and that is invisible
# here, where the app is never opened, until somebody downloads it.
#
# The sidecars are required beside the executable rather than anywhere
# inside the bundle, because that is the only place the app looks:
# tools::locate resolves them against the directory holding the running
# binary and otherwise falls back to a bare name on the PATH. A copy
# sealed somewhere else would pass a laxer check and ship an app that
# tells its user ffmpeg is missing.
- name: Check the bundle is sealed around its sidecars
if: runner.os == 'macOS'
shell: bash
run: |
set -euo pipefail

# Searched under the folder the upload step already reads, not all
# of target: a stray Transcrate.app anywhere else is whichever one
# find reaches first, and the wrong bundle would be the one checked.
#
# `-print -quit` rather than piping into `head`, because under
# pipefail head leaving early sends find SIGPIPE and the step fails
# on a bundle that is fine. `|| true` so an absent folder is reported
# by the line below rather than by find.
bundle="target/${{ matrix.target }}/release/bundle"
app="$(find "$bundle" -maxdepth 3 -name 'Transcrate.app' -print -quit 2>/dev/null || true)"
if [ -z "$app" ]; then
echo "no Transcrate.app was built" >&2
exit 1
fi

# Contents/MacOS is where the bundle format puts the executable, so
# it is what current_exe().parent() returns and what the app joins a
# tool name onto.
for tool in ffmpeg ffprobe; do
if [ ! -f "$app/Contents/MacOS/$tool" ]; then
echo "$tool is not beside the executable in the bundle" >&2

stray="$(find "$app" -type f -name "$tool" -print -quit 2>/dev/null || true)"
if [ -n "$stray" ]; then
echo " it is at ${stray#"$app"/}, where the app will not look" >&2
fi
exit 1
fi
done

# --deep reaches the nested executables, --strict refuses a seal that
# does not match what is actually in the bundle.
codesign --verify --deep --strict --verbose=2 "$app"

# Kept whether or not there is a release to attach them to. The size of
# the download is the reason ffmpeg is built here rather than fetched, and
# a manual run is where that gets weighed.
Expand Down
Loading