feat(desktop): ship macOS DMG with drag-to-Applications install (#554)

* fix(deskop): update DMG packaging instructions for macOS to clarify drag-and-drop installation

* feat(darwin): enhance DMG installer with custom background and layout adjustments

Added a custom background image for the DMG installer and adjusted the layout settings for better visual presentation. The background image is copied to the staging area if it exists, and the window dimensions and icon positions have been updated for improved aesthetics.

* chore(workflows): update upload and download artifact actions to latest versions

Updated the GitHub Actions in the octop-desktop workflow to use the latest versions of the upload-artifact and download-artifact actions, improving compatibility and security.

* refactor(darwin): remove old DMG creation script and update Taskfile for new background image

Deleted the outdated create-installer-dmg.sh script and replaced it with an inline script in Taskfile.yml that utilizes dmg-background.png for the DMG installer. This change streamlines the DMG creation process and enhances the visual presentation with the new background image.

* chore(.gitignore): clean up ignored files and directories

Updated the .gitignore file to remove unnecessary entries and ensure that build artifacts are properly ignored, while preserving the build directory for the desktop application. This change enhances the clarity and organization of ignored files.

* feat(darwin): replace DMG background image and enhance detachment logic

Introduced a new JPEG background image for the DMG installer, replacing the previous PNG file. Updated the Taskfile to improve the device detachment process with a dedicated function, ensuring smoother handling during DMG creation. Adjusted layout settings for better visual presentation in the installer window.
This commit is contained in:
liukewia
2026-09-03 20:42:08 +08:00
committed by GitHub
parent b67a124598
commit d10df912a6
5 changed files with 102 additions and 16 deletions
+2 -2
View File
@@ -71,7 +71,7 @@ jobs:
- name: Build frontend → src/octop/dashboard
run: make build-frontend
- uses: actions/upload-artifact@v5
- uses: actions/upload-artifact@v7
with:
name: dashboard-dist
path: src/octop/dashboard/
@@ -150,7 +150,7 @@ jobs:
echo "OCTOP_VERSION=${VER}" >> "$GITHUB_ENV"
echo "version=${VER}"
- uses: actions/download-artifact@v5
- uses: actions/download-artifact@v8
with:
name: dashboard-dist
path: src/octop/dashboard
+6 -4
View File
@@ -1,3 +1,9 @@
# Build
build/
!desktop/src/build/
!desktop/src/build/**
dist/
# OS
.DS_Store
.DS_Store?
@@ -19,10 +25,6 @@ __pycache__/
*$py.class
*.so
.Python
build/
!desktop/src/build/
!desktop/src/build/**
dist/
*.egg-info/
*.egg
.eggs/
+4 -3
View File
@@ -77,9 +77,10 @@ Wails shell never downloads Octop. For local runtime debugging, set
GitHub Release names follow `Octop-<kind>-<os>-<arch>-<version>.<ext>`:
- Desktop GUI: `Octop-desktop-<plat>-<version>.dmg` (macOS),
`.exe` (Windows NSIS installer — copies into `Program Files\Octop`
and creates Start Menu + desktop shortcuts), `.tar.gz` (Linux)
- Desktop GUI: `Octop-desktop-<plat>-<version>.dmg` (macOS; open and drag
`Octop.app` into Applications), `.exe` (Windows NSIS installer — copies
into `Program Files\Octop` and creates Start Menu + desktop shortcuts),
`.tar.gz` (Linux)
- Green runtime zip: `Octop-portable-<plat>-<version>.zip`
- PyPI wheels stay `octop-<version>-py3-none-any.whl` (PEP 427)
+90 -7
View File
@@ -26,7 +26,7 @@ tasks:
PRODUCTION: '{{.PRODUCTION | default "false"}}'
package:
summary: Packages a production .app into an uncompressed DMG
summary: Packages a production .app into a drag-to-Applications DMG
deps:
- task: build
vars:
@@ -36,16 +36,99 @@ tasks:
vars:
PORTABLE_ZIP: "{{.PORTABLE_ZIP}}"
ARCH: "{{.ARCH}}"
- rm -rf {{.DMG_ROOT}} {{.ARCHIVE}} {{.BIN_DIR}}/{{.APP_NAME}}-Desktop-darwin-{{.ARCH}}.zip {{.BIN_DIR}}/{{.APP_NAME}}-Desktop-darwin-{{.ARCH}}.dmg
- mkdir -p {{.DMG_ROOT}}
- ditto {{.BIN_DIR}}/{{.APP_NAME}}.app {{.DMG_ROOT}}/{{.APP_NAME}}.app
- hdiutil create -volname {{.APP_NAME}} -srcfolder {{.DMG_ROOT}} -ov -format UDRO {{.ARCHIVE}}
- rm -rf {{.DMG_ROOT}}
- rm -f {{.ARCHIVE}} {{.BIN_DIR}}/{{.APP_NAME}}-Desktop-darwin-{{.ARCH}}.zip {{.BIN_DIR}}/{{.APP_NAME}}-Desktop-darwin-{{.ARCH}}.dmg
- |
set -euo pipefail
app_path="{{.BIN_DIR}}/{{.APP_NAME}}.app"
output="{{.ARCHIVE}}"
volname="{{.APP_NAME}}"
app_name="{{.APP_NAME}}.app"
work="$(mktemp -d "${TMPDIR:-/tmp}/octop-dmg.XXXXXX")"
staging="${work}/root"
rw_dmg="${work}/rw.dmg"
device=""
# hdiutil detach exits 16 while the volume is still busy (Spotlight, Finder).
detach_device() {
local dev="$1" i
for i in 1 2 3 4 5; do
if hdiutil detach "$dev" -quiet >/dev/null 2>&1; then
return 0
fi
sleep 3
done
hdiutil detach "$dev" -force -quiet >/dev/null 2>&1
}
cleanup() {
if [[ -n "$device" ]]; then
detach_device "$device" || true
fi
rm -rf "$work"
}
trap cleanup EXIT
mkdir -p "${staging}/.background"
ditto "$app_path" "${staging}/${app_name}"
ln -s /Applications "${staging}/Applications"
# Finder renders a background picture at its DPI-derived point size, so
# 1200x800 @144dpi lands exactly on the 600x400pt container window.
sips -s format png -z 800 1200 -s dpiWidth 144 -s dpiHeight 144 \
build/darwin/dmg-background.jpeg --out "${staging}/.background/background.png" >/dev/null
if [[ -d "/Volumes/${volname}" ]]; then
hdiutil detach "/Volumes/${volname}" -quiet >/dev/null 2>&1 || \
hdiutil detach "/Volumes/${volname}" -force -quiet >/dev/null 2>&1 || true
fi
hdiutil create -volname "$volname" -srcfolder "$staging" -ov -format UDRW "$rw_dmg" >/dev/null
attach_out="$(hdiutil attach -readwrite -noverify -noautoopen "$rw_dmg" || true)"
device="$(awk '/^\/dev\// { print $1; exit }' <<<"$attach_out")"
mount_point="$(awk -F'\t' '/\/Volumes\// { print $NF; exit }' <<<"$attach_out")"
if [[ -z "$device" || ! -d "$mount_point" ]]; then
echo "warning: could not mount writable DMG; writing a plain image" >&2
hdiutil create -volname "$volname" -srcfolder "$staging" -ov -format UDRO "$output"
exit 0
fi
osascript - "$volname" "$app_name" <<'APPLESCRIPT' || \
echo "warning: could not set Finder icon layout; Applications drop link is still present" >&2
on run argv
set volName to item 1 of argv
set appName to item 2 of argv
tell application "Finder"
tell disk volName
open
set current view of container window to icon view
set toolbar visible of container window to false
set statusbar visible of container window to false
set the bounds of container window to {200, 120, 800, 552}
set viewOptions to the icon view options of container window
set arrangement of viewOptions to not arranged
set icon size of viewOptions to 128
try
set background picture of viewOptions to file ".background:background.png"
end try
set position of item appName of container window to {154, 237}
set position of item "Applications" of container window to {454, 237}
close
open
update without registering applications
delay 1
end tell
end tell
end run
APPLESCRIPT
sync
if ! detach_device "$device"; then
echo "warning: could not detach ${device}; writing a plain image" >&2
device=""
hdiutil create -volname "$volname" -srcfolder "$staging" -ov -format UDRO "$output" >/dev/null
test -s "$output"
exit 0
fi
device=""
rm -f "$output"
hdiutil convert "$rw_dmg" -ov -format UDRO -o "$output" >/dev/null
test -s "$output"
vars:
ARCH: "{{.ARCH | default ARCH}}"
VERSION: '{{.VERSION | default "dev"}}'
PORTABLE_ZIP: '{{.PORTABLE_ZIP | default (printf "../portable/release/Octop-portable-darwin-%s-%s.zip" .ARCH .VERSION)}}'
DMG_ROOT: '{{.BIN_DIR}}/dmg-darwin-{{.ARCH}}'
ARCHIVE: '{{.BIN_DIR}}/{{.APP_NAME}}-desktop-darwin-{{.ARCH}}-{{.VERSION}}.dmg'
create:app:bundle:
Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB