Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 87d7623

Browse files
authored
feat: macOS and linux tray binaries (#1163)
1 parent 7e064a2 commit 87d7623

19 files changed

Lines changed: 732 additions & 343 deletions

.github/workflows/reusable-release.yml

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ on:
1717

1818
jobs:
1919
goreleaser:
20+
permissions:
21+
contents: read
2022
runs-on: ubuntu-latest
2123
steps:
2224
- uses: actions/checkout@v4
@@ -78,6 +80,8 @@ jobs:
7880
name: Windows installers
7981
needs: [goreleaser]
8082
runs-on: windows-latest
83+
permissions:
84+
contents: write
8185

8286
steps:
8387
- name: Checkout
@@ -157,3 +161,66 @@ jobs:
157161
with:
158162
files: |
159163
./windows_installers/*
164+
165+
macos-bundle:
166+
name: macOS app bundle (${{ matrix.goarch }})
167+
runs-on: macos-latest
168+
permissions:
169+
contents: write
170+
strategy:
171+
matrix:
172+
goarch: [amd64, arm64]
173+
steps:
174+
- uses: actions/checkout@v4
175+
- uses: actions/setup-go@v4
176+
with:
177+
go-version: "1.25"
178+
- uses: actions/setup-node@v4
179+
with:
180+
node-version: "20"
181+
- uses: pnpm/action-setup@v4
182+
with:
183+
version: 9
184+
- name: Build web UI
185+
run: |
186+
cd webui && pnpm install && pnpm run build
187+
- name: Get version
188+
id: version
189+
run: |
190+
if [[ "$GITHUB_REF" == refs/tags/v* ]]; then
191+
echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
192+
else
193+
echo "version=0.0.0-snapshot-${GITHUB_SHA::8}" >> "$GITHUB_OUTPUT"
194+
fi
195+
- name: Build binary
196+
env:
197+
CGO_ENABLED: "1"
198+
GOARCH: ${{ matrix.goarch }}
199+
run: |
200+
go build -tags tray \
201+
-ldflags "-s -w -X main.version=${{ steps.version.outputs.version }} -X main.commit=${{ github.sha }}" \
202+
-o backrest ./cmd/backrest/
203+
- name: Create app bundle
204+
run: ./build/darwin/bundle.sh ./backrest ${{ steps.version.outputs.version }}
205+
- name: Compute arch name
206+
id: arch
207+
run: |
208+
if [ "${{ matrix.goarch }}" = "amd64" ]; then
209+
echo "name=x86_64" >> "$GITHUB_OUTPUT"
210+
else
211+
echo "name=${{ matrix.goarch }}" >> "$GITHUB_OUTPUT"
212+
fi
213+
- name: Package bundle
214+
run: |
215+
zip -r "backrest_Darwin_${{ steps.arch.outputs.name }}.zip" Backrest.app
216+
- name: Upload as artifact
217+
if: ${{ inputs.snapshot }}
218+
uses: actions/upload-artifact@v4
219+
with:
220+
name: backrest-macos-${{ steps.arch.outputs.name }}
221+
path: "backrest_Darwin_${{ steps.arch.outputs.name }}.zip"
222+
- name: Upload to release
223+
if: ${{ !inputs.snapshot && startsWith(github.ref, 'refs/tags/') }}
224+
uses: softprops/action-gh-release@v2
225+
with:
226+
files: "backrest_Darwin_${{ steps.arch.outputs.name }}.zip"

.gitignore

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
backrest
2-
backrest-*
1+
/backrest
2+
/backrest-*
33
dist
44
__debug_bin
55
cmd/backrest/backrest

.goreleaser.yaml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ builds:
2929
binary: backrest
3030
env:
3131
- CGO_ENABLED=0
32+
tags:
33+
- tray
3234
goos:
3335
- linux
3436
goarch:
@@ -63,6 +65,8 @@ builds:
6365
binary: backrest
6466
env:
6567
- CGO_ENABLED=1
68+
tags:
69+
- tray
6670
goos:
6771
- windows
6872
goarch:
@@ -72,7 +76,12 @@ builds:
7276
- -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}} -H windowsgui
7377

7478
archives:
75-
- format: tar.gz
79+
- id: default
80+
builds:
81+
- other
82+
- linux
83+
- windows
84+
format: tar.gz
7685
name_template: >-
7786
{{ .ProjectName }}_
7887
{{- title .Os }}_
@@ -362,6 +371,8 @@ docker_manifests:
362371

363372
brews:
364373
- name: backrest
374+
ids:
375+
- default
365376
homepage: https://github.com/garethgeorge/backrest
366377
description: "Backrest is a web UI and orchestrator for restic backup."
367378

build/darwin/Info.plist

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>CFBundleExecutable</key>
6+
<string>backrest</string>
7+
<key>CFBundleIdentifier</key>
8+
<string>com.garethgeorge.backrest</string>
9+
<key>CFBundleName</key>
10+
<string>Backrest</string>
11+
<key>CFBundleDisplayName</key>
12+
<string>Backrest</string>
13+
<key>CFBundleVersion</key>
14+
<string>__VERSION__</string>
15+
<key>CFBundleShortVersionString</key>
16+
<string>__VERSION__</string>
17+
<key>CFBundlePackageType</key>
18+
<string>APPL</string>
19+
<key>CFBundleIconFile</key>
20+
<string>backrest.icns</string>
21+
<key>NSHighResolutionCapable</key>
22+
<true/>
23+
<key>LSUIElement</key>
24+
<true/>
25+
</dict>
26+
</plist>

build/darwin/bundle.sh

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#!/bin/bash
2+
# bundle.sh - Assembles the macOS .app bundle for Backrest tray mode.
3+
#
4+
# Usage:
5+
# ./build/darwin/bundle.sh [binary_path] [version]
6+
#
7+
# Arguments:
8+
# binary_path Path to the compiled backrest binary (default: ./backrest)
9+
# version Version string for the bundle (default: "unknown")
10+
#
11+
# Output:
12+
# Backrest.app/ in the current directory
13+
14+
set -euo pipefail
15+
16+
BINARY="${1:-./backrest}"
17+
VERSION="${2:-unknown}"
18+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
19+
APP_DIR="Backrest.app"
20+
21+
if [ ! -f "$BINARY" ]; then
22+
echo "Error: binary not found at $BINARY"
23+
echo "Build it first: go build -o backrest ./cmd/backrest/"
24+
exit 1
25+
fi
26+
27+
# Clean previous bundle
28+
rm -rf "$APP_DIR"
29+
30+
# Create bundle structure
31+
mkdir -p "$APP_DIR/Contents/MacOS"
32+
mkdir -p "$APP_DIR/Contents/Resources"
33+
34+
# Copy binary
35+
cp "$BINARY" "$APP_DIR/Contents/MacOS/backrest"
36+
chmod +x "$APP_DIR/Contents/MacOS/backrest"
37+
38+
# Generate Info.plist with version
39+
sed "s|__VERSION__|$VERSION|g" "$SCRIPT_DIR/Info.plist" > "$APP_DIR/Contents/Info.plist"
40+
41+
# Generate .icns from the PNG icon
42+
ICON_PNG="$SCRIPT_DIR/icon.png"
43+
if [ -f "$ICON_PNG" ]; then
44+
ICONSET_DIR=$(mktemp -d)/backrest.iconset
45+
mkdir -p "$ICONSET_DIR"
46+
47+
# Generate required icon sizes
48+
for size in 16 32 64 128 256 512; do
49+
sips -z $size $size "$ICON_PNG" --out "$ICONSET_DIR/icon_${size}x${size}.png" >/dev/null 2>&1
50+
done
51+
# Retina variants
52+
for size in 16 32 128 256 512; do
53+
double=$((size * 2))
54+
sips -z $double $double "$ICON_PNG" --out "$ICONSET_DIR/icon_${size}x${size}@2x.png" >/dev/null 2>&1
55+
done
56+
57+
iconutil -c icns -o "$APP_DIR/Contents/Resources/backrest.icns" "$ICONSET_DIR" 2>/dev/null || {
58+
echo "Warning: iconutil failed, bundling without .icns icon"
59+
}
60+
rm -rf "$(dirname "$ICONSET_DIR")"
61+
else
62+
echo "Warning: icon.png not found at $ICON_PNG, bundling without icon"
63+
fi
64+
65+
# Ad-hoc sign so macOS shows "unverified developer" instead of "damaged"
66+
codesign --force --deep -s - "$APP_DIR"
67+
68+
echo "Created $APP_DIR (version: $VERSION)"
69+
echo "To run: open $APP_DIR"

build/darwin/icon.png

30.7 KB
Loading

cmd/backrest/icon.png

3.15 KB
Loading

cmd/backrest/icon_unix.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
//go:build tray && (linux || darwin)
2+
3+
package main
4+
5+
import _ "embed"
6+
7+
//go:embed icon.png
8+
var icon []byte

cmd/backrest/icon_windows.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
//go:build tray && windows
2+
3+
package main
4+
5+
import _ "embed"
6+
7+
//go:embed icon.ico
8+
var icon []byte

cmd/backrest/main_darwin.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//go:build darwin
2+
3+
package main
4+
5+
import (
6+
"flag"
7+
"os"
8+
"strings"
9+
10+
"go.uber.org/zap"
11+
)
12+
13+
var darwinTray = flag.Bool("tray", false, "run with system tray applet (menu bar)")
14+
15+
func main() {
16+
flag.Parse()
17+
// Auto-enable tray mode when launched from a .app bundle
18+
inBundle := strings.Contains(os.Args[0], ".app/Contents/MacOS/")
19+
if *darwinTray || inBundle {
20+
startTray()
21+
} else {
22+
runApp()
23+
}
24+
}
25+
26+
func reportError(err error) {
27+
zap.S().Errorf("backrest error: %v", err)
28+
}

0 commit comments

Comments
 (0)