mirror of
https://github.com/yusufipk/dikte.git
synced 2026-09-11 10:56:10 +00:00
Installing meant cloning the repository and running a shell script, which is a fair ask of somebody who already has a terminal open and no ask at all of anybody else. The releases page now carries an AppImage and a disk image per Mac architecture: a push to master rebuilds a rolling "latest", a v* tag publishes a version and leaves it there, and the Run button in the Actions tab raises the number by running scripts/release.sh, which is the same script and not a second copy of what it does. Two things in the application had to give for that. A build has no __main__.py on disk, and an AppImage is mounted somewhere new every run, so the command a shortcut is registered with cannot go on being this interpreter and this file; ipc.launcher() answers with the AppImage or the bundle instead. And a build carries its own libstdc++, which every process it starts inherits through LD_LIBRARY_PATH and none of them can live with: ffmpeg, ydotool and wl-copy are the distribution's binaries built against the distribution's libraries, and AppImageLauncher, which is what starting the AppImage again goes through, refuses outright. integrate.py puts that variable back before anything else runs. Nothing installs itself over an installation that is already there. install.sh's menu entry, install-mac.sh's login item and the desktop file AppImageLauncher writes are each recognised and left alone, so trying a download once does not quietly move the machine onto it. `dikte integrate` is how you ask for it outright, and --remove takes it back. The disk image carries an ffmpeg, pinned and checksummed, because macOS records through one and ships nothing like it. It is signed ad-hoc and not with an Apple certificate, so a first launch is refused until Open Anyway and the permissions are asked for again after each update; both READMEs and the release notes say so.
89 lines
4.1 KiB
Bash
Executable File
89 lines
4.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# The macOS download: a disk image with Dikte.app in it and the usual arrow at
|
|
# /Applications to drag it onto.
|
|
#
|
|
# Run from anywhere; it works in build/ at the top of the checkout and leaves
|
|
# the finished .dmg in dist/. One image per architecture, because PyQt6 has no
|
|
# universal wheel to build a universal binary out of, so the workflow runs this
|
|
# once on an Apple silicon runner and once on an Intel one.
|
|
set -euo pipefail
|
|
|
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
BUILD="$ROOT/build"
|
|
OUT="$ROOT/dist"
|
|
ARCH="$(uname -m)"
|
|
BUNDLE_ID="io.github.yusufipk.dikte"
|
|
|
|
VERSION="$(cd "$ROOT" && python3 -c 'import dikte; print(dikte.__version__)')"
|
|
APP="$BUILD/dist/Dikte.app"
|
|
|
|
# A pinned tag and a checksum rather than "whatever is newest": this binary
|
|
# goes out inside something people run, so what it is has to be decided here
|
|
# and not by whoever pushes to that repository next. GPL, which is what Dikte
|
|
# is licensed under too. 6.1.1 is behind the current release and stays there
|
|
# until something Dikte asks of it needs a newer one.
|
|
FFMPEG_TAG="b6.1.1"
|
|
case "$ARCH" in
|
|
arm64) FFMPEG_ASSET="ffmpeg-darwin-arm64.gz"
|
|
FFMPEG_SHA="8923876afa8db5585022d7860ec7e589af192f441c56793971276d450ed3bbfa" ;;
|
|
x86_64) FFMPEG_ASSET="ffmpeg-darwin-x64.gz"
|
|
FFMPEG_SHA="929b375c1182d956c51f7ac25e0b2b0411fb01f6f407aa15c9758efeb4242106" ;;
|
|
*) echo "no ffmpeg pinned for $ARCH" >&2; exit 1 ;;
|
|
esac
|
|
|
|
rm -rf "$BUILD" "$OUT"
|
|
mkdir -p "$BUILD" "$OUT"
|
|
|
|
# 1. The icon --------------------------------------------------------------
|
|
# Before the application, because the bundle is built with it rather than
|
|
# having it copied in afterwards. Drawn by Dikte itself, offscreen, which is
|
|
# why there is no image file in the repository.
|
|
iconset="$BUILD/Dikte.iconset"
|
|
QT_QPA_PLATFORM=offscreen PYTHONPATH="$ROOT" python3 -m dikte.trayicon "$iconset"
|
|
iconutil -c icns "$iconset" -o "$BUILD/Dikte.icns"
|
|
export DIKTE_ICNS="$BUILD/Dikte.icns"
|
|
|
|
# 2. The application -------------------------------------------------------
|
|
python3 -m PyInstaller "$ROOT/packaging/dikte.spec" \
|
|
--distpath "$BUILD/dist" --workpath "$BUILD/work" --noconfirm --clean
|
|
|
|
# 3. ffmpeg ----------------------------------------------------------------
|
|
# Recording on a Mac goes through ffmpeg, and macOS ships nothing like it, so
|
|
# without this the disk image would be an application that cannot record until
|
|
# the person who downloaded it installs Homebrew. Resources/bin because
|
|
# Contents/MacOS is for the executable the bundle names, and integrate.py puts
|
|
# this directory in front of PATH at startup.
|
|
bin="$APP/Contents/Resources/bin"
|
|
mkdir -p "$bin"
|
|
curl -fsSL -o "$BUILD/$FFMPEG_ASSET" \
|
|
"https://github.com/eugeneware/ffmpeg-static/releases/download/$FFMPEG_TAG/$FFMPEG_ASSET"
|
|
echo "$FFMPEG_SHA $BUILD/$FFMPEG_ASSET" | shasum -a 256 -c -
|
|
gunzip -c "$BUILD/$FFMPEG_ASSET" > "$bin/ffmpeg"
|
|
chmod +x "$bin/ffmpeg"
|
|
|
|
# 4. Signing ---------------------------------------------------------------
|
|
# Ad-hoc, because there is no Developer ID to sign with. It is not decoration:
|
|
# macOS files a microphone or Accessibility permission against a code
|
|
# signature, and an arm64 binary carrying none is refused by the kernel outright
|
|
# rather than merely warned about. What it does not buy is Gatekeeper, which is
|
|
# why the README tells people how to get past the first-launch refusal.
|
|
#
|
|
# --deep is the wrong tool for a real signature and the right one here: every
|
|
# dylib PyInstaller collected plus the ffmpeg added above all need one, and
|
|
# adding ffmpeg invalidated the signature PyInstaller left.
|
|
codesign --force --deep --sign - --identifier "$BUNDLE_ID" "$APP"
|
|
codesign --verify --deep "$APP"
|
|
|
|
# 5. The disk image --------------------------------------------------------
|
|
# A staging directory rather than the bundle on its own, so that the window
|
|
# that opens has the arrow to drag it onto. UDZO is the compressed read-only
|
|
# format every Mac has understood for twenty years.
|
|
stage="$BUILD/stage"
|
|
mkdir -p "$stage"
|
|
cp -a "$APP" "$stage/"
|
|
ln -s /Applications "$stage/Applications"
|
|
hdiutil create -volname "Dikte $VERSION" -srcfolder "$stage" \
|
|
-ov -format UDZO -quiet "$OUT/Dikte-$VERSION-$ARCH.dmg"
|
|
|
|
echo "dist/Dikte-$VERSION-$ARCH.dmg"
|