ci: add better view on macos installation (#1019)

This commit is contained in:
delewer
2026-06-23 13:36:20 +03:00
committed by GitHub
parent ce6a456bd1
commit ee6c34e065
5 changed files with 166 additions and 58 deletions
+30 -36
View File
@@ -272,30 +272,10 @@ jobs:
python3.12 -m pip install . python3.12 -m pip install .
python3.12 -m pip install pyinstaller==6.13.0 python3.12 -m pip install pyinstaller==6.13.0
- name: Create macOS icon from ICO - name: Create macOS icon
run: | run: |
set -euo pipefail set -euo pipefail
python3.12 - <<'PY' python3.12 macos.py --render-app-icon icon.icns
from PIL import Image
image = Image.open('icon.ico')
image = image.resize((1024, 1024), Image.LANCZOS)
image.save('icon_1024.png', 'PNG')
PY
mkdir -p icon.iconset
sips -z 16 16 icon_1024.png --out icon.iconset/icon_16x16.png
sips -z 32 32 icon_1024.png --out icon.iconset/icon_16x16@2x.png
sips -z 32 32 icon_1024.png --out icon.iconset/icon_32x32.png
sips -z 64 64 icon_1024.png --out icon.iconset/icon_32x32@2x.png
sips -z 128 128 icon_1024.png --out icon.iconset/icon_128x128.png
sips -z 256 256 icon_1024.png --out icon.iconset/icon_128x128@2x.png
sips -z 256 256 icon_1024.png --out icon.iconset/icon_256x256.png
sips -z 512 512 icon_1024.png --out icon.iconset/icon_256x256@2x.png
sips -z 512 512 icon_1024.png --out icon.iconset/icon_512x512.png
sips -z 1024 1024 icon_1024.png --out icon.iconset/icon_512x512@2x.png
iconutil -c icns icon.iconset -o icon.icns
rm -rf icon.iconset icon_1024.png
- name: Build app with PyInstaller - name: Build app with PyInstaller
run: python3.12 -m PyInstaller packaging/macos.spec --noconfirm run: python3.12 -m PyInstaller packaging/macos.spec --noconfirm
@@ -303,6 +283,11 @@ jobs:
- name: Validate universal2 app bundle - name: Validate universal2 app bundle
run: | run: |
set -euo pipefail set -euo pipefail
ICON_FILE="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleIconFile' \
'dist/TG WS Proxy.app/Contents/Info.plist')"
test -n "$ICON_FILE"
test -f "dist/TG WS Proxy.app/Contents/Resources/$ICON_FILE"
found=0 found=0
while IFS= read -r -d '' file; do while IFS= read -r -d '' file; do
if file "$file" | grep -q "Mach-O"; then if file "$file" | grep -q "Mach-O"; then
@@ -326,22 +311,31 @@ jobs:
- name: Create DMG - name: Create DMG
run: | run: |
set -euo pipefail set -euo pipefail
APP_NAME="TG WS Proxy" packaging/dmg/build_dmg.sh \
DMG_TEMP="dist/dmg_temp" "dist/TG WS Proxy.app" \
"TG WS Proxy" \
rm -rf "$DMG_TEMP"
mkdir -p "$DMG_TEMP"
cp -R "dist/${APP_NAME}.app" "$DMG_TEMP/"
ln -s /Applications "$DMG_TEMP/Applications"
hdiutil create \
-volname "$APP_NAME" \
-srcfolder "$DMG_TEMP" \
-ov \
-format UDZO \
"dist/TgWsProxy_macos_universal.dmg" "dist/TgWsProxy_macos_universal.dmg"
rm -rf "$DMG_TEMP" - name: Validate DMG
run: |
set -euo pipefail
for DMG in "dist/TgWsProxy_macos_universal.dmg"; do
MOUNT_DIR="$(mktemp -d)"
DEVICE="$(hdiutil attach \
-readonly \
-nobrowse \
-mountpoint "$MOUNT_DIR" \
"$DMG" \
| awk '/^\/dev\// { print $1; exit }')"
test -d "$MOUNT_DIR/TG WS Proxy.app"
test -L "$MOUNT_DIR/Applications"
test "$(readlink "$MOUNT_DIR/Applications")" = "/Applications"
test -f "$MOUNT_DIR/.background/background.tiff"
test -f "$MOUNT_DIR/.DS_Store"
hdiutil detach "$DEVICE"
rmdir "$MOUNT_DIR"
done
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v7 uses: actions/upload-artifact@v7
+43 -22
View File
@@ -9,16 +9,53 @@ import webbrowser
from pathlib import Path from pathlib import Path
from typing import Optional from typing import Optional
try:
import rumps
except ImportError:
rumps = None
try: try:
from PIL import Image, ImageDraw, ImageFont from PIL import Image, ImageDraw, ImageFont
except ImportError: except ImportError:
Image = ImageDraw = ImageFont = None Image = ImageDraw = ImageFont = None
def render_app_icon(size: int):
scale = size / 1024
image = Image.new("RGBA", (size, size), (0, 0, 0, 0))
draw = ImageDraw.Draw(image)
outer = tuple(round(value * scale) for value in (92, 92, 932, 932))
draw.ellipse(outer, fill=(0, 151, 221, 255))
try:
font = ImageFont.truetype(
"/System/Library/Fonts/Helvetica.ttc",
round(430 * scale),
)
except Exception:
font = ImageFont.load_default()
box = draw.textbbox((0, 0), "T", font=font)
width = box[2] - box[0]
height = box[3] - box[1]
draw.text(
(
(size - width) / 2 - box[0],
(size - height) / 2 - box[1] - round(10 * scale),
),
"T",
font=font,
fill=(255, 255, 255, 255),
)
return image
if __name__ == "__main__" and len(sys.argv) > 1 and sys.argv[1] == "--render-app-icon":
if Image is None:
raise SystemExit("Pillow is required to render the macOS app icon")
output_path = sys.argv[2] if len(sys.argv) > 2 else "icon.icns"
render_app_icon(1024).save(output_path, format="ICNS")
raise SystemExit(0)
try:
import rumps
except ImportError:
rumps = None
try: try:
import pyperclip import pyperclip
except ImportError: except ImportError:
@@ -144,26 +181,10 @@ def _ask_cfworker_domain(default: str) -> Optional[str]:
def _make_menubar_icon(size: int = 44): def _make_menubar_icon(size: int = 44):
if Image is None: if Image is None:
return None return None
img = Image.new("RGBA", (size, size), (0, 0, 0, 0)) return render_app_icon(size)
draw = ImageDraw.Draw(img)
margin = size // 11
draw.ellipse([margin, margin, size - margin, size - margin], fill=(0, 0, 0, 255))
try:
font = ImageFont.truetype("/System/Library/Fonts/Helvetica.ttc", size=int(size * 0.55))
except Exception:
font = ImageFont.load_default()
bbox = draw.textbbox((0, 0), "T", font=font)
tw, th = bbox[2] - bbox[0], bbox[3] - bbox[1]
draw.text(
((size - tw) // 2 - bbox[0], (size - th) // 2 - bbox[1]),
"T", fill=(255, 255, 255, 255), font=font,
)
return img
def _ensure_menubar_icon() -> None: def _ensure_menubar_icon() -> None:
if MENUBAR_ICON_PATH.exists():
return
ensure_dirs() ensure_dirs()
img = _make_menubar_icon(44) img = _make_menubar_icon(44)
if img: if img:
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

+93
View File
@@ -0,0 +1,93 @@
#!/usr/bin/env bash
set -euo pipefail
APP_PATH="${1:?Usage: build_dmg.sh <App.app> <Volume Name> <output.dmg> [assets_dir]}"
VOL_NAME="${2:?missing volume name}"
OUT_DMG="${3:?missing output dmg path}"
ASSETS_DIR="${4:-$(cd "$(dirname "${BASH_SOURCE[0]}")/assets" && pwd)}"
WIN_W=660
WIN_H=440
ICON_SIZE=128
APP_X=145
APPS_X=515
ICON_Y=220
APP_NAME="$(basename "$APP_PATH")"
WORK="$(mktemp -d)"
STAGE="$WORK/stage"
RW_DMG="$WORK/rw.dmg"
MOUNT="/Volumes/$VOL_NAME"
DEVICE=""
cleanup() {
if [ -n "$DEVICE" ]; then
hdiutil detach "$DEVICE" -force >/dev/null 2>&1 || true
fi
rm -rf "$WORK"
}
trap cleanup EXIT
mkdir -p "$STAGE/.background"
cp -R "$APP_PATH" "$STAGE/"
ln -s /Applications "$STAGE/Applications"
tiffutil -cathidpicheck \
"$ASSETS_DIR/background-light.png" \
"$ASSETS_DIR/background-light@2x.png" \
-out "$STAGE/.background/background.tiff"
hdiutil create \
-volname "$VOL_NAME" \
-srcfolder "$STAGE" \
-fs HFS+ \
-format UDRW \
-ov \
"$RW_DMG"
DEVICE="$(hdiutil attach \
-readwrite \
-noverify \
-noautoopen \
-mountpoint "$MOUNT" \
"$RW_DMG" \
| awk '/^\/dev\// { print $1; exit }')"
test -n "$DEVICE"
test -d "$MOUNT/$APP_NAME"
sleep 2
osascript <<APPLESCRIPT
tell application "Finder"
tell disk "$VOL_NAME"
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, 140, 200 + $WIN_W, 140 + $WIN_H}
set theViewOptions to the icon view options of container window
set arrangement of theViewOptions to not arranged
set icon size of theViewOptions to $ICON_SIZE
set text size of theViewOptions to 13
set background picture of theViewOptions to file ".background:background.tiff"
set position of item "$APP_NAME" of container window to {$APP_X, $ICON_Y}
set position of item "Applications" of container window to {$APPS_X, $ICON_Y}
close
open
update
delay 2
end tell
end tell
APPLESCRIPT
SetFile -a C "$MOUNT" 2>/dev/null || true
sync
hdiutil detach "$DEVICE" -force >/dev/null 2>&1 \
|| { sleep 3; hdiutil detach "$DEVICE" -force; }
DEVICE=""
rm -f "$OUT_DMG"
hdiutil convert "$RW_DMG" -format UDZO -imagekey zlib-level=9 -ov -o "$OUT_DMG"
echo "Created $OUT_DMG"