build: designed macOS DMG

This commit is contained in:
zhom committed 2026-10-17 22:31:16 +04:00
1 parent 2346bbf2ba
commit e2f449dfdf
8 files changed
+190

No files matched your search

+31
View File
@@ -203,6 +203,14 @@ jobs:
rm -f $CERT_PATH $KEY_PATH $PEM_PATH $P12_PATH
- name: Set up Python for the DMG layout
if: matrix.platform == 'macos-latest'
id: python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 #v7.0.0
with:
python-version: "3.13"
update-environment: false
- name: Build Tauri app
uses: tauri-apps/tauri-action@1deb371b0cd8bd54025b384f1cd735e725c4060f #v1.0.0
env:
@@ -228,6 +236,29 @@ jobs:
prerelease: false
args: ${{ matrix.args }}
# Tauri's DMG has no layout in CI: its Finder script needs a desktop
# session. Rebuild the DMG from the notarized app with a layout written
# directly, sign it, and replace the asset that tauri-action uploaded.
- name: Rebuild macOS DMG with the install layout
if: matrix.platform == 'macos-latest'
shell: bash
env:
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PYTHON: ${{ steps.python.outputs.python-path }}
TAG: ${{ github.ref_name }}
run: |
BUNDLE="src-tauri/target/${{ matrix.target }}/release/bundle"
shopt -s nullglob
DMGS=("$BUNDLE"/dmg/*.dmg)
if [ "${#DMGS[@]}" -ne 1 ]; then
echo "Expected one DMG in $BUNDLE/dmg, found ${#DMGS[@]}"
exit 1
fi
xcrun stapler validate "$BUNDLE/macos/Donut.app"
scripts/build-macos-dmg.sh "$BUNDLE/macos/Donut.app" "${DMGS[0]}"
gh release upload "$TAG" "${DMGS[0]}" --clobber --repo "$GITHUB_REPOSITORY"
- name: Create portable Windows ZIP
if: matrix.platform == 'windows-latest'
shell: bash
+31
View File
@@ -232,6 +232,14 @@ jobs:
rm -f "$CERT_PATH" "$KEY_PATH" "$PEM_PATH" "$P12_PATH"
- name: Set up Python for the DMG layout
if: matrix.platform == 'macos-latest'
id: python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 #v7.0.0
with:
python-version: "3.13"
update-environment: false
- name: Build Tauri app
uses: tauri-apps/tauri-action@1deb371b0cd8bd54025b384f1cd735e725c4060f #v1.0.0
env:
@@ -256,6 +264,29 @@ jobs:
prerelease: true
args: ${{ matrix.args }}
# Tauri's DMG has no layout in CI: its Finder script needs a desktop
# session. Rebuild the DMG from the notarized app with a layout written
# directly, sign it, and replace the asset that tauri-action uploaded.
- name: Rebuild macOS DMG with the install layout
if: matrix.platform == 'macos-latest'
shell: bash
env:
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PYTHON: ${{ steps.python.outputs.python-path }}
TAG: "nightly-${{ steps.timestamp.outputs.timestamp }}"
run: |
BUNDLE="src-tauri/target/${{ matrix.target }}/release/bundle"
shopt -s nullglob
DMGS=("$BUNDLE"/dmg/*.dmg)
if [ "${#DMGS[@]}" -ne 1 ]; then
echo "Expected one DMG in $BUNDLE/dmg, found ${#DMGS[@]}"
exit 1
fi
xcrun stapler validate "$BUNDLE/macos/Donut.app"
scripts/build-macos-dmg.sh "$BUNDLE/macos/Donut.app" "${DMGS[0]}"
gh release upload "$TAG" "${DMGS[0]}" --clobber --repo "$GITHUB_REPOSITORY"
- name: Create portable Windows ZIP
if: matrix.platform == 'windows-latest'
shell: bash
Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

+25
View File
@@ -0,0 +1,25 @@
<svg xmlns="http://www.w3.org/2000/svg" width="660" height="440" viewBox="0 0 660 440">
<!-- Source of dmg-background.png (1x) and dmg-background@2x.png (2x). Text is outlined Geist. -->
<defs>
<radialGradient id="wash" cx="330.0" cy="222" r="470" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="#ffffff"/>
<stop offset="0.55" stop-color="#fafafa"/>
<stop offset="1" stop-color="#ededef"/>
</radialGradient>
</defs>
<rect width="660" height="440" fill="url(#wash)"/>
<path d="M268.96 80V65.09H271.69V80ZM274.72 80V68.79H277.15L277.22 70.7Q277.68 69.54 278.57 69.04Q279.46 68.53 280.58 68.53Q282.42 68.53 283.41 69.72Q284.4 70.91 284.4 72.8V80H281.71V73.66Q281.71 72.23 281.28 71.47Q280.85 70.72 279.76 70.72Q278.67 70.72 278.04 71.47Q277.41 72.23 277.41 73.66V80ZM291.37 80.25Q288.81 80.25 287.55 79.18Q286.29 78.11 286.16 76.47L288.91 76.35Q289.06 77.23 289.62 77.71Q290.17 78.19 291.39 78.19Q292.34 78.19 292.83 77.89Q293.32 77.58 293.32 76.93Q293.32 76.56 293.14 76.3Q292.97 76.05 292.45 75.86Q291.94 75.67 290.95 75.48Q289.25 75.19 288.28 74.76Q287.32 74.33 286.93 73.68Q286.54 73.03 286.54 72.06Q286.54 70.51 287.75 69.52Q288.96 68.53 291.29 68.53Q292.9 68.53 293.94 69.05Q294.98 69.56 295.52 70.41Q296.05 71.26 296.14 72.31L293.41 72.44Q293.37 71.64 292.86 71.12Q292.36 70.59 291.24 70.59Q290.3 70.59 289.81 70.97Q289.31 71.35 289.31 71.98Q289.31 72.65 289.78 72.98Q290.26 73.3 291.52 73.51Q293.24 73.76 294.25 74.2Q295.26 74.64 295.69 75.31Q296.12 75.97 296.12 76.89Q296.12 78.51 294.83 79.38Q293.53 80.25 291.37 80.25ZM302.08 80Q300.4 80 299.61 79.23Q298.83 78.47 298.83 76.79V70.86H297.06V68.79H298.83V66.16H301.51V68.79H304.47V70.86H301.51V76.53Q301.51 77.33 301.86 77.63Q302.21 77.92 302.9 77.92H304.47V80ZM309.39 80.25Q307.62 80.25 306.55 79.45Q305.48 78.66 305.48 77.19Q305.48 75.74 306.39 74.92Q307.29 74.1 309.14 73.74L312.85 73.01Q312.85 70.61 310.69 70.61Q309.72 70.61 309.16 71.06Q308.59 71.52 308.4 72.36L305.67 72.23Q306.01 70.47 307.31 69.5Q308.61 68.53 310.69 68.53Q313.08 68.53 314.31 69.74Q315.54 70.95 315.54 73.2V77.27Q315.54 77.71 315.7 77.88Q315.86 78.05 316.17 78.05H316.53V80Q316.17 80.08 315.54 80.08Q314.64 80.08 314.01 79.71Q313.38 79.33 313.21 78.3V78.28Q312.79 79.16 311.77 79.71Q310.75 80.25 309.39 80.25ZM309.93 78.3Q311.28 78.3 312.07 77.52Q312.85 76.75 312.85 75.46V74.83L309.96 75.42Q309.05 75.61 308.66 75.98Q308.28 76.35 308.28 76.93Q308.28 78.3 309.93 78.3ZM320.54 80Q319.3 80 318.58 79.37Q317.85 78.74 317.85 77.35V65.09H320.54V77.08Q320.54 77.92 321.38 77.92H322.2V80ZM326.31 80Q325.08 80 324.35 79.37Q323.63 78.74 323.63 77.35V65.09H326.31V77.08Q326.31 77.92 327.15 77.92H327.97V80ZM334.53 80V65.09H339.48Q343.05 65.09 344.97 67.03Q346.89 68.97 346.89 72.57Q346.89 76.14 345 78.07Q343.11 80 339.61 80ZM337.26 77.63H339.48Q344.08 77.63 344.08 72.57Q344.08 67.46 339.48 67.46H337.26ZM353.99 80.25Q352.33 80.25 351.08 79.53Q349.83 78.8 349.15 77.49Q348.47 76.18 348.47 74.39Q348.47 72.61 349.15 71.3Q349.83 69.98 351.08 69.26Q352.33 68.53 353.99 68.53Q355.65 68.53 356.89 69.26Q358.13 69.98 358.81 71.3Q359.49 72.61 359.49 74.39Q359.49 76.18 358.81 77.49Q358.13 78.8 356.89 79.53Q355.65 80.25 353.99 80.25ZM353.99 78.07Q355.27 78.07 355.99 77.1Q356.7 76.14 356.7 74.39Q356.7 72.65 355.99 71.68Q355.27 70.72 353.99 70.72Q352.69 70.72 351.98 71.68Q351.26 72.65 351.26 74.39Q351.26 76.14 351.98 77.1Q352.69 78.07 353.99 78.07ZM361.32 80V68.79H363.76L363.82 70.7Q364.28 69.54 365.18 69.04Q366.07 68.53 367.18 68.53Q369.03 68.53 370.02 69.72Q371 70.91 371 72.8V80H368.31V73.66Q368.31 72.23 367.88 71.47Q367.45 70.72 366.36 70.72Q365.27 70.72 364.64 71.47Q364.01 72.23 364.01 73.66V80ZM377.11 80.25Q375.39 80.25 374.4 79.14Q373.42 78.03 373.42 76.01V68.79H376.11V75.34Q376.11 76.77 376.58 77.42Q377.05 78.07 378.02 78.07Q379.09 78.07 379.7 77.34Q380.31 76.62 380.31 75.23V68.79H382.99V80H380.54L380.49 78.17Q379.61 80.25 377.11 80.25ZM389.71 80Q388.03 80 387.25 79.23Q386.46 78.47 386.46 76.79V70.86H384.69V68.79H386.46V66.16H389.15V68.79H392.11V70.86H389.15V76.53Q389.15 77.33 389.49 77.63Q389.84 77.92 390.53 77.92H392.11V80Z" fill="#09090b"/>
<path d="M211.39 104V94.77H214.25Q216.39 94.77 217.54 95.97Q218.69 97.17 218.69 99.4Q218.69 101.61 217.56 102.8Q216.43 104 214.33 104ZM212.51 102.91H214.25Q217.52 102.91 217.52 99.4Q217.52 95.86 214.25 95.86H212.51ZM220.26 104V97.11H221.22L221.26 98.38Q221.61 97.11 222.9 97.11H223.58V98.15H222.91Q221.35 98.15 221.35 99.84V104ZM226.53 104.16Q225.46 104.16 224.83 103.66Q224.2 103.17 224.2 102.28Q224.2 101.4 224.72 100.89Q225.24 100.39 226.37 100.18L228.81 99.72Q228.81 97.99 227.18 97.99Q226.46 97.99 226.05 98.31Q225.63 98.63 225.47 99.23L224.32 99.14Q224.51 98.16 225.26 97.56Q226.01 96.95 227.18 96.95Q228.5 96.95 229.2 97.7Q229.91 98.45 229.91 99.76V102.61Q229.91 103.04 230.27 103.04H230.54V104Q230.39 104.03 230.13 104.03Q229.53 104.03 229.22 103.79Q228.92 103.55 228.84 103L228.83 102.93Q228.57 103.47 227.93 103.81Q227.29 104.16 226.53 104.16ZM226.63 103.19Q227.67 103.19 228.24 102.61Q228.81 102.02 228.81 101.17V100.67L226.58 101.09Q225.88 101.22 225.61 101.48Q225.34 101.75 225.34 102.18Q225.34 102.66 225.69 102.93Q226.03 103.19 226.63 103.19ZM234.37 106.11Q233.26 106.11 232.48 105.56Q231.7 105.01 231.48 104.1L232.62 104.03Q232.78 104.51 233.18 104.79Q233.57 105.07 234.37 105.07Q235.3 105.07 235.8 104.69Q236.3 104.31 236.3 103.56V102.44Q236.06 102.99 235.51 103.31Q234.96 103.64 234.29 103.64Q233.42 103.64 232.73 103.21Q232.05 102.78 231.67 102.02Q231.28 101.27 231.28 100.3Q231.28 99.31 231.66 98.56Q232.04 97.81 232.71 97.38Q233.38 96.95 234.24 96.95Q234.96 96.95 235.54 97.29Q236.12 97.63 236.35 98.2V97.11H237.39V103.53Q237.39 104.74 236.6 105.42Q235.8 106.11 234.37 106.11ZM234.34 102.6Q235.22 102.6 235.76 101.98Q236.29 101.36 236.3 100.3Q236.33 99.23 235.78 98.61Q235.24 97.99 234.34 97.99Q233.43 97.99 232.93 98.61Q232.43 99.23 232.43 100.3Q232.43 101.36 232.94 101.98Q233.46 102.6 234.34 102.6ZM242.88 104V94.77H245.74Q247.87 94.77 249.02 95.97Q250.17 97.17 250.17 99.4Q250.17 101.61 249.04 102.8Q247.91 104 245.82 104ZM244 102.91H245.74Q249 102.91 249 99.4Q249 95.86 245.74 95.86H244ZM254.62 104.16Q253.67 104.16 252.96 103.71Q252.24 103.27 251.85 102.46Q251.46 101.65 251.46 100.56Q251.46 99.45 251.85 98.64Q252.24 97.84 252.96 97.4Q253.67 96.95 254.62 96.95Q255.57 96.95 256.28 97.4Q256.99 97.84 257.38 98.64Q257.77 99.45 257.77 100.56Q257.77 101.65 257.38 102.46Q256.99 103.27 256.28 103.71Q255.57 104.16 254.62 104.16ZM254.62 103.12Q255.57 103.12 256.1 102.43Q256.62 101.75 256.62 100.56Q256.62 99.36 256.1 98.68Q255.57 97.99 254.62 97.99Q253.67 97.99 253.14 98.68Q252.6 99.36 252.6 100.56Q252.6 101.75 253.14 102.43Q253.67 103.12 254.62 103.12ZM259.25 104V97.11H260.25L260.27 98.34Q260.55 97.63 261.11 97.29Q261.68 96.95 262.39 96.95Q263.19 96.95 263.7 97.31Q264.21 97.66 264.47 98.25Q264.72 98.84 264.72 99.57V104H263.63V99.88Q263.63 98.92 263.28 98.42Q262.94 97.92 262.16 97.92Q261.37 97.92 260.85 98.42Q260.34 98.92 260.34 99.88V104ZM268.87 104.16Q267.84 104.16 267.22 103.46Q266.61 102.77 266.61 101.54V97.11H267.7V101.24Q267.7 102.25 268.06 102.72Q268.41 103.19 269.15 103.19Q269.97 103.19 270.44 102.67Q270.91 102.14 270.91 101.22V97.11H272V104H270.96V102.88Q270.39 104.16 268.87 104.16ZM276.24 104Q275.3 104 274.85 103.57Q274.41 103.14 274.41 102.23V98.07H273.39V97.11H274.41V95.5H275.5V97.11H277.33V98.07H275.5V102.21Q275.5 102.67 275.71 102.86Q275.91 103.04 276.34 103.04H277.33V104ZM282.06 104V97.11H283.15V104ZM282.04 96.03V94.76H283.18V96.03ZM285.31 104V97.11H286.31L286.34 98.34Q286.61 97.63 287.18 97.29Q287.74 96.95 288.46 96.95Q289.25 96.95 289.76 97.31Q290.28 97.66 290.53 98.25Q290.79 98.84 290.79 99.57V104H289.69V99.88Q289.69 98.92 289.35 98.42Q289 97.92 288.22 97.92Q287.43 97.92 286.92 98.42Q286.4 98.92 286.4 99.88V104ZM294.87 104Q293.93 104 293.48 103.57Q293.03 103.14 293.03 102.23V98.07H292.02V97.11H293.03V95.5H294.13V97.11H295.96V98.07H294.13V102.21Q294.13 102.67 294.33 102.86Q294.54 103.04 294.97 103.04H295.96V104ZM299.92 104.16Q298.98 104.16 298.26 103.71Q297.55 103.27 297.16 102.46Q296.77 101.65 296.77 100.56Q296.77 99.45 297.16 98.64Q297.55 97.84 298.26 97.4Q298.98 96.95 299.92 96.95Q300.87 96.95 301.58 97.4Q302.29 97.84 302.68 98.64Q303.07 99.45 303.07 100.56Q303.07 101.65 302.68 102.46Q302.29 103.27 301.58 103.71Q300.87 104.16 299.92 104.16ZM299.92 103.12Q300.87 103.12 301.4 102.43Q301.93 101.75 301.93 100.56Q301.93 99.36 301.4 98.68Q300.87 97.99 299.92 97.99Q298.98 97.99 298.44 98.68Q297.91 99.36 297.91 100.56Q297.91 101.75 298.44 102.43Q298.98 103.12 299.92 103.12ZM308.23 105.95V104.99H309.02Q309.39 104.99 309.56 104.88Q309.74 104.77 309.83 104.52L310.08 103.87H309.7L307.18 97.11H308.37L310.43 102.86L312.39 97.11H313.59L310.79 104.87Q310.6 105.43 310.21 105.69Q309.82 105.95 309.13 105.95ZM317.27 104.16Q316.32 104.16 315.6 103.71Q314.89 103.27 314.5 102.46Q314.11 101.65 314.11 100.56Q314.11 99.45 314.5 98.64Q314.89 97.84 315.6 97.4Q316.32 96.95 317.27 96.95Q318.22 96.95 318.92 97.4Q319.63 97.84 320.02 98.64Q320.41 99.45 320.41 100.56Q320.41 101.65 320.02 102.46Q319.63 103.27 318.92 103.71Q318.22 104.16 31Line truncated
<circle cx="262.00" cy="222" r="1.35" fill="#52525b" fill-opacity="0.22"/>
<circle cx="273.00" cy="222" r="1.40" fill="#52525b" fill-opacity="0.27"/>
<circle cx="284.00" cy="222" r="1.45" fill="#52525b" fill-opacity="0.32"/>
<circle cx="295.00" cy="222" r="1.50" fill="#52525b" fill-opacity="0.37"/>
<circle cx="306.00" cy="222" r="1.55" fill="#52525b" fill-opacity="0.42"/>
<circle cx="317.00" cy="222" r="1.60" fill="#52525b" fill-opacity="0.47"/>
<circle cx="328.00" cy="222" r="1.65" fill="#52525b" fill-opacity="0.52"/>
<circle cx="339.00" cy="222" r="1.70" fill="#52525b" fill-opacity="0.57"/>
<circle cx="350.00" cy="222" r="1.75" fill="#52525b" fill-opacity="0.62"/>
<circle cx="361.00" cy="222" r="1.80" fill="#52525b" fill-opacity="0.67"/>
<circle cx="372.00" cy="222" r="1.85" fill="#52525b" fill-opacity="0.72"/>
<path d="M378 214 L386 222 L378 230" fill="none" stroke="#3f3f46" stroke-width="2.25" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 198 KiB

+3
View File
@@ -0,0 +1,3 @@
dmgbuild==1.6.7 --hash=sha256:37ee5771c377beb3203d9164aae8046ffed8531c06edf9227f5788b3c599b1bf
ds-store==1.3.3 --hash=sha256:b92a371efbf1b4ccce2a04d1ed13fceacc4736c81ba09cf5aefb74c088160a35
mac-alias==2.2.3 --hash=sha256:7362b521d2132ef92f606a37abfed5fcd849ceb2f28b6f9743e014b02af92f0d
+52
View File
@@ -0,0 +1,52 @@
# dmgbuild settings for the macOS disk image. scripts/build-macos-dmg.sh runs
# dmgbuild with them. dmgbuild writes the .DS_Store directly, so the layout
# needs no Finder session and is the same on every build.
#
# Icon locations are icon centres, in points from the top-left of the window
# content. The window origin is measured from the bottom-left of the screen,
# and its size includes the title bar. Finder on macOS 26 also shows a tab
# bar, which leaves about 362 points of content height. The background is
# drawn for this layout: change dmg-background.svg with it and render it
# again at 1x and 2x.
import os.path
app = defines["app"]
app_name = os.path.basename(app.rstrip("/"))
format = "UDZO"
compression_level = 9
filesystem = "HFS+"
files = [app]
symlinks = {"Applications": "/Applications"}
# No hide_extensions: its Finder flag on the bundle fails codesign --strict.
icon = defines["volume_icon"]
# dmgbuild joins dmg-background@2x.png with it into one HiDPI TIFF.
background = defines["background"]
window_rect = ((400, 400), (660, 430))
default_view = "icon-view"
show_toolbar = False
show_tab_view = False
show_status_bar = False
show_pathbar = False
show_sidebar = False
arrange_by = None
icon_size = 128
text_size = 13
label_pos = "bottom"
icon_locations = {
app_name: (170, 222),
"Applications": (490, 222),
}
# Items that Finder shows when hidden files are visible. They sit to the right
# of the window, so they stay out of view.
for i, name in enumerate(
(".background.tiff", ".VolumeIcon.icns", ".fseventsd", ".Trashes")
):
icon_locations[name] = (900 + 160 * i, 222)
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/env bash
# Builds the macOS disk image from a built (and, in CI, notarized) Donut.app,
# with the background and the Finder layout in packaging/macos.
#
# scripts/build-macos-dmg.sh <Donut.app> <output.dmg>
#
# When APPLE_SIGNING_IDENTITY is set, the image is signed with it.
# PYTHON selects the interpreter (3.10 or newer); the default is python3.
set -euo pipefail
if [[ $# -ne 2 ]]; then
echo "usage: $0 <Donut.app> <output.dmg>" >&2
exit 2
fi
app="$(cd "$(dirname "$1")" && pwd)/$(basename "$1")"
out="$(cd "$(dirname "$2")" && pwd)/$(basename "$2")"
root="$(cd "$(dirname "$0")/.." && pwd)"
assets="$root/packaging/macos"
python="${PYTHON:-python3}"
[[ -d "$app" ]] || { echo "app bundle not found: $app" >&2; exit 1; }
"$python" -c 'import sys; sys.exit(sys.version_info < (3, 10))' ||
{ echo "dmgbuild needs Python 3.10 or newer; set PYTHON" >&2; exit 1; }
work="$(mktemp -d)"
trap 'rm -rf "$work"' EXIT
dmg="$work/$(basename "$out")"
"$python" -m venv "$work/venv"
PIP_DISABLE_PIP_VERSION_CHECK=1 "$work/venv/bin/pip" install --quiet \
--require-hashes --no-deps --only-binary :all: -r "$assets/dmg-requirements.txt"
"$work/venv/bin/dmgbuild" \
-s "$assets/dmg-settings.py" \
-D app="$app" \
-D background="$assets/dmg-background.png" \
-D volume_icon="$root/src-tauri/icons/icon.icns" \
"Donut" "$dmg"
if [[ -n "${APPLE_SIGNING_IDENTITY:-}" ]]; then
codesign --force --sign "$APPLE_SIGNING_IDENTITY" --timestamp "$dmg"
codesign --verify --strict "$dmg"
fi
hdiutil verify -quiet "$dmg"
mv -f "$dmg" "$out"
echo "Built $out"