mirror of
https://github.com/black-ant/Ant-Browser.git
synced 2026-07-14 18:48:55 +08:00
chore(build): complete unsigned macOS packaging
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
name: Publish macOS Packages
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- arch: amd64
|
||||
runner: macos-15-intel
|
||||
- arch: arm64
|
||||
runner: macos-15
|
||||
|
||||
runs-on: ${{ matrix.runner }}
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: go.mod
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
cache-dependency-path: frontend/package-lock.json
|
||||
|
||||
- name: Install Wails CLI
|
||||
run: go install github.com/wailsapp/wails/v2/cmd/wails@v2.11.0
|
||||
|
||||
- name: Add Go bin to PATH
|
||||
run: echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH"
|
||||
|
||||
- name: Build unsigned macOS package
|
||||
run: bash publish/mac/publish-mac.sh --arch ${{ matrix.arch }}
|
||||
|
||||
- name: Validate app bundle
|
||||
run: |
|
||||
set -euo pipefail
|
||||
app_path="$(ls -1d publish/output/AntBrowser-*-macos-${{ matrix.arch }}.app | head -n 1)"
|
||||
zip_path="$(ls -1 publish/output/AntBrowser-*-macos-${{ matrix.arch }}.zip | head -n 1)"
|
||||
echo "Validating: $app_path"
|
||||
test -x "$app_path/Contents/MacOS/ant-chrome"
|
||||
test -x "$app_path/Contents/MacOS/bin/xray"
|
||||
test -x "$app_path/Contents/MacOS/bin/sing-box"
|
||||
plutil -lint "$app_path/Contents/Info.plist"
|
||||
ditto -x -k "$zip_path" /tmp/ant-browser-macos-validate
|
||||
test -x "/tmp/ant-browser-macos-validate/$(basename "$app_path")/Contents/MacOS/ant-chrome"
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ant-browser-macos-${{ matrix.arch }}
|
||||
path: |
|
||||
publish/output/AntBrowser-*-macos-${{ matrix.arch }}.app
|
||||
publish/output/AntBrowser-*-macos-${{ matrix.arch }}.zip
|
||||
@@ -46,6 +46,12 @@ chrome/*
|
||||
!/bin/linux-arm64/
|
||||
!/bin/linux-arm64/xray
|
||||
!/bin/linux-arm64/sing-box
|
||||
!/bin/darwin-amd64/
|
||||
!/bin/darwin-amd64/xray
|
||||
!/bin/darwin-amd64/sing-box
|
||||
!/bin/darwin-arm64/
|
||||
!/bin/darwin-arm64/xray
|
||||
!/bin/darwin-arm64/sing-box
|
||||
|
||||
# Publish artifacts
|
||||
publish/staging/
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
## 1.1.0 - 2026-03-19
|
||||
|
||||
- 完善 Linux 支持:补齐 Linux 环境下的开发、打包、安装、启动与运行链路,并持续修复安装版启动与退出稳定性问题。
|
||||
- 补齐 macOS unsigned 内测支持:新增原生 macOS `.app` / `.zip` 打包、Darwin 运行时校验、Application Support 用户状态目录和 macOS 发布工作流。
|
||||
- 新增 SOCKS 代理测试支持:SOCKS 代理能力已进入测试阶段,后续会继续验证稳定性与兼容性。
|
||||
- 实验性支持接口触发浏览器:支持通过接口启动浏览器实例,便于后续接入自动化流程。
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# Ant Browser
|
||||
|
||||
> 面向多账号隔离、代理绑定和本地环境管理的桌面浏览器工具(Windows / Linux)。
|
||||
> 面向多账号隔离、代理绑定和本地环境管理的桌面浏览器工具(Windows / Linux / macOS unsigned)。
|
||||
|
||||
[](https://github.com/black-ant/Ant-Browser/releases)
|
||||
[](https://github.com/black-ant/Ant-Browser/releases)
|
||||
[](https://github.com/black-ant/Ant-Browser/releases)
|
||||
[](https://github.com/black-ant/Ant-Browser/issues)
|
||||
|
||||
## 推荐内核项目
|
||||
@@ -54,6 +54,7 @@ Ant Browser 适合以下场景:
|
||||
### 1.1.0 · 2026-03-19
|
||||
|
||||
- 完善 Linux 支持:补齐 Linux 环境下的开发、打包、安装、启动与运行链路,并持续修复安装版启动与退出稳定性问题
|
||||
- 补齐 macOS unsigned 内测构建链路:支持在原生 macOS 主机上打包 `.app` / `.zip`,并将用户状态目录放到 `~/Library/Application Support/ant-browser`
|
||||
- 新增 SOCKS 代理测试支持:SOCKS 代理能力已进入测试阶段,后续会继续验证稳定性与兼容性
|
||||
- 实验性支持接口触发浏览器:支持通过接口启动浏览器实例,便于后续接入自动化流程
|
||||
|
||||
@@ -126,6 +127,7 @@ Ant Browser 适合以下场景:
|
||||
- 操作系统:
|
||||
- Windows 10 / 11(64 位)
|
||||
- Linux(amd64 / arm64)
|
||||
- macOS(amd64 / arm64,当前为 unsigned 内测包)
|
||||
- 建议内存:8 GB 及以上
|
||||
- 建议磁盘空间:2 GB 以上
|
||||
|
||||
@@ -135,15 +137,16 @@ Ant Browser 适合以下场景:
|
||||
2. 安装版直接运行 `AntBrowser-Setup-*.exe`
|
||||
3. 便携版解压后运行 `ant-chrome.exe`
|
||||
4. Linux 包下载后可直接安装 `ant-browser_<version>_<arch>.deb`,或解压 `tar.gz` 后运行 `ant-chrome`
|
||||
5. macOS unsigned 包解压后运行 `AntBrowser-<version>-macos-<arch>.app`;如被 Gatekeeper 拦截,请对本机测试包执行 `xattr -dr com.apple.quarantine <app路径>` 后再打开
|
||||
|
||||
### 从源码运行
|
||||
|
||||
1. 开发默认使用 `master` 分支;该分支不带测试用户数据,适合作为日常开发基线。
|
||||
2. 如需带测试库的演示环境,请切换到 `user_data` 分支。
|
||||
3. Windows 统一执行 `bat\dev.bat`;默认是稳定模式,如需前端 HMR 联调使用 `bat\dev.bat live`,如需受限内存复现使用 `bat\dev.bat limited`。
|
||||
4. Windows 运行时使用 `bin/xray.exe`、`bin/sing-box.exe`;Linux 运行时使用 `bin/linux-<arch>/xray`、`bin/linux-<arch>/sing-box`。
|
||||
4. Windows 运行时使用 `bin/xray.exe`、`bin/sing-box.exe`;Linux 运行时使用 `bin/linux-<arch>/xray`、`bin/linux-<arch>/sing-box`;macOS 运行时使用 `bin/darwin-<arch>/xray`、`bin/darwin-<arch>/sing-box`。
|
||||
5. 运行时文件采用“仓库固定 + 哈希校验”,校验清单在 `publish/runtime-manifest.json`,固定来源清单在 `publish/runtime-sources.json`。
|
||||
6. 如需刷新 Linux 运行时,执行 `python3 tools/runtime/sync-runtime.py`(会按固定来源下载、校验归档并更新 manifest)。
|
||||
6. 如需刷新 Linux / macOS 运行时,执行 `python3 tools/runtime/sync-runtime.py --target <target>`(会按固定来源下载、校验归档并更新 manifest)。
|
||||
|
||||
开发模式说明:
|
||||
|
||||
@@ -163,6 +166,17 @@ bash publish/linux/publish-linux.sh --arch arm64
|
||||
|
||||
详细说明见 [publish/linux/README.md](publish/linux/README.md)。
|
||||
|
||||
### macOS unsigned 发布打包(源码)
|
||||
|
||||
macOS 发布脚本位于 `publish/mac/`,必须在原生 macOS 主机上执行,且目标架构需与主机架构一致。
|
||||
|
||||
```bash
|
||||
bash publish/mac/publish-mac.sh --arch amd64
|
||||
bash publish/mac/publish-mac.sh --arch arm64
|
||||
```
|
||||
|
||||
脚本会生成 unsigned `.app` 和 `.zip`,适合 PR 验证与内部测试。详细说明见 [publish/mac/README.md](publish/mac/README.md)。
|
||||
|
||||
### 准备浏览器内核
|
||||
|
||||
代理运行时已经随仓库提供,你只需要准备浏览器内核。
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
goruntime "runtime"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
@@ -406,7 +407,7 @@ func DefaultConfig() *Config {
|
||||
},
|
||||
Browser: BrowserConfig{
|
||||
UserDataRoot: "data",
|
||||
DefaultFingerprintArgs: []string{"--fingerprint-brand=Chrome", "--fingerprint-platform=windows"},
|
||||
DefaultFingerprintArgs: defaultFingerprintArgsForOS(goruntime.GOOS),
|
||||
DefaultLaunchArgs: []string{"--disable-sync", "--no-first-run"},
|
||||
DefaultProxy: "",
|
||||
StartReadyTimeoutMs: 3000,
|
||||
@@ -445,6 +446,17 @@ func DefaultConfig() *Config {
|
||||
}
|
||||
}
|
||||
|
||||
func defaultFingerprintArgsForOS(goos string) []string {
|
||||
platform := "windows"
|
||||
switch strings.ToLower(strings.TrimSpace(goos)) {
|
||||
case "darwin":
|
||||
platform = "mac"
|
||||
case "linux":
|
||||
platform = "linux"
|
||||
}
|
||||
return []string{"--fingerprint-brand=Chrome", "--fingerprint-platform=" + platform}
|
||||
}
|
||||
|
||||
// Save 保存配置到文件
|
||||
func (c *Config) Save(configPath string) error {
|
||||
data, err := yaml.Marshal(c)
|
||||
|
||||
@@ -3,6 +3,7 @@ package config
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -74,6 +75,42 @@ browser: {}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefaultFingerprintArgsForOS(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := map[string]string{
|
||||
"windows": "--fingerprint-platform=windows",
|
||||
"linux": "--fingerprint-platform=linux",
|
||||
"darwin": "--fingerprint-platform=mac",
|
||||
"freebsd": "--fingerprint-platform=windows",
|
||||
}
|
||||
|
||||
for goos, want := range tests {
|
||||
got := defaultFingerprintArgsForOS(goos)
|
||||
if len(got) != 2 {
|
||||
t.Fatalf("%s: unexpected args length: got=%v", goos, got)
|
||||
}
|
||||
if got[1] != want {
|
||||
t.Fatalf("%s: platform arg mismatch: got=%q want=%q", goos, got[1], want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDefaultConfigUsesCurrentOSFingerprintPlatform(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cfg := DefaultConfig()
|
||||
want := defaultFingerprintArgsForOS(runtime.GOOS)
|
||||
if len(cfg.Browser.DefaultFingerprintArgs) != len(want) {
|
||||
t.Fatalf("默认指纹参数数量不符: got=%v want=%v", cfg.Browser.DefaultFingerprintArgs, want)
|
||||
}
|
||||
for i := range want {
|
||||
if cfg.Browser.DefaultFingerprintArgs[i] != want[i] {
|
||||
t.Fatalf("默认指纹参数不符: got=%v want=%v", cfg.Browser.DefaultFingerprintArgs, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadPreservesExplicitConfig(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
+8
-1
@@ -12,6 +12,13 @@ Linux (new):
|
||||
- `bin/linux-arm64/xray`
|
||||
- `bin/linux-arm64/sing-box`
|
||||
|
||||
macOS (unsigned internal builds):
|
||||
|
||||
- `bin/darwin-amd64/xray`
|
||||
- `bin/darwin-amd64/sing-box`
|
||||
- `bin/darwin-arm64/xray`
|
||||
- `bin/darwin-arm64/sing-box`
|
||||
|
||||
Runtime hashes are pinned in `publish/runtime-manifest.json`.
|
||||
Pinned upstream archive sources are tracked in `publish/runtime-sources.json`.
|
||||
Use `python3 tools/runtime/sync-runtime.py` to refresh Linux runtimes safely.
|
||||
Use `python3 tools/runtime/sync-runtime.py --target <target>` to refresh runtime files safely.
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>{{.OutputFilename}}</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.wails.{{.Name}}</string>
|
||||
<string>com.antbrowser.desktop</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>{{.Info.ProductVersion}}</string>
|
||||
<key>CFBundleGetInfoString</key>
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# Browser Core Placeholder
|
||||
|
||||
Place downloaded browser cores under this directory when running from source.
|
||||
|
||||
Published macOS and Linux packages include this placeholder only. Actual browser core binaries are user-managed and should live under the writable `chrome/` directory in the runtime state root.
|
||||
+91
-324
@@ -1,360 +1,127 @@
|
||||
# macOS Publish Plan
|
||||
# macOS Publish
|
||||
|
||||
## Purpose
|
||||
This directory contains the unsigned macOS packaging flow for Ant Browser.
|
||||
|
||||
This document defines the macOS packaging plan for Ant Browser.
|
||||
The macOS package is intended for internal testing and PR validation first. It deliberately does not perform Apple Developer ID signing or notarization.
|
||||
|
||||
The goal is to turn the current codebase into a macOS build that can:
|
||||
## Targets
|
||||
|
||||
- build on a native macOS machine
|
||||
- launch from `/Applications`
|
||||
- keep user-writable state outside the `.app` bundle
|
||||
- bundle required proxy runtime binaries
|
||||
- avoid breaking existing Windows and Linux packaging flows
|
||||
- `darwin/amd64`
|
||||
- `darwin/arm64`
|
||||
|
||||
## Current Entry Command
|
||||
Output artifacts:
|
||||
|
||||
The initial internal-build script can be invoked on a real Mac with:
|
||||
- `publish/output/AntBrowser-<version>-macos-<arch>.app`
|
||||
- `publish/output/AntBrowser-<version>-macos-<arch>.zip`
|
||||
|
||||
## Runtime Policy
|
||||
|
||||
macOS publish uses repository-pinned runtime files and hash verification.
|
||||
|
||||
Pinned upstream source lock file:
|
||||
|
||||
- `publish/runtime-sources.json`
|
||||
|
||||
Required files:
|
||||
|
||||
- `bin/darwin-amd64/xray`
|
||||
- `bin/darwin-amd64/sing-box`
|
||||
- `bin/darwin-arm64/xray`
|
||||
- `bin/darwin-arm64/sing-box`
|
||||
|
||||
Hashes are validated by:
|
||||
|
||||
- `tools/runtime/verify-runtime.sh`
|
||||
- `publish/runtime-manifest.json`
|
||||
|
||||
Recommended way to refresh runtime files:
|
||||
|
||||
```bash
|
||||
python3 tools/runtime/sync-runtime.py --target darwin-amd64
|
||||
python3 tools/runtime/sync-runtime.py --target darwin-arm64
|
||||
```
|
||||
|
||||
If you replace runtime files manually, update manifest hashes:
|
||||
|
||||
```bash
|
||||
python3 tools/runtime/update-runtime-manifest.py --target darwin-amd64
|
||||
python3 tools/runtime/update-runtime-manifest.py --target darwin-arm64
|
||||
```
|
||||
|
||||
If runtime file or hash is missing/mismatched, publish will fail.
|
||||
|
||||
## Commands
|
||||
|
||||
Build on a native macOS host that matches the target architecture:
|
||||
|
||||
```bash
|
||||
bash publish/mac/publish-mac.sh --arch amd64
|
||||
bash publish/mac/publish-mac.sh --arch arm64
|
||||
```
|
||||
|
||||
For the first iteration, `arm64` is the recommended target.
|
||||
The first command is for Intel Macs. The second command is for Apple Silicon Macs.
|
||||
|
||||
This is a plan document only. It does not mean macOS packaging is already implemented.
|
||||
The script:
|
||||
|
||||
## Current Status
|
||||
1. verifies the host OS and architecture
|
||||
2. verifies pinned Darwin runtime hashes
|
||||
3. installs frontend dependencies
|
||||
4. builds frontend assets
|
||||
5. runs `wails build -platform darwin/<arch>`
|
||||
6. assembles an unsigned `.app`
|
||||
7. bundles `xray` and `sing-box` under `Contents/MacOS/bin`
|
||||
8. writes a `.zip` artifact with the app bundle as the top-level item
|
||||
|
||||
The repository already has:
|
||||
## Writable State Layout
|
||||
|
||||
- Windows packaging flow
|
||||
- Linux packaging flow
|
||||
- partial Darwin runtime compatibility in backend code
|
||||
- initial `publish/mac/publish-mac.sh` scaffold for internal test builds
|
||||
- initial `publish/config.init.mac.yaml` template
|
||||
- committed Darwin runtime binaries under `bin/darwin-amd64/` and `bin/darwin-arm64/`
|
||||
- Darwin runtime entries in `publish/runtime-manifest.json`
|
||||
- Darwin runtime source lock entries in `publish/runtime-sources.json`
|
||||
Installed `.app` bundles should be treated as read-only. When Ant Browser runs from:
|
||||
|
||||
The repository does not yet have:
|
||||
- `Ant Browser.app/Contents/MacOS`
|
||||
- `Ant Browser.app/Contents/Resources`
|
||||
|
||||
- signing / notarization flow
|
||||
|
||||
The repository now includes the first macOS writable-state implementation for app bundle roots:
|
||||
|
||||
- when the app root is inside `.app/Contents/MacOS` or `.app/Contents/Resources`
|
||||
- writable state is redirected to `~/Library/Application Support/ant-browser`
|
||||
- `bin/` stays in the app bundle
|
||||
- config, chrome, and data move to the user state root
|
||||
|
||||
## Current Implementation Note
|
||||
|
||||
The current initial macOS packaging scaffold intentionally places helper binaries and seed files under:
|
||||
|
||||
- `Ant Browser.app/Contents/MacOS/bin`
|
||||
- `Ant Browser.app/Contents/MacOS/config.yaml`
|
||||
- `Ant Browser.app/Contents/MacOS/chrome/README.md`
|
||||
|
||||
This is not the prettiest final bundle layout, but it matches the current runtime path resolution and avoids a larger refactor in Phase 1.
|
||||
|
||||
After the first internal build is stable, the bundle layout can be reviewed and moved toward `Contents/Resources` if needed.
|
||||
|
||||
## Why macOS Looks More Complex
|
||||
|
||||
macOS is not difficult because of Wails alone. The real complexity comes from four areas:
|
||||
|
||||
1. Installed `.app` bundles under `/Applications` should be treated as read-only.
|
||||
2. User data must not be written inside the `.app` bundle.
|
||||
3. External helper binaries such as `xray` and `sing-box` must exist for Darwin and must be bundled correctly.
|
||||
4. Public distribution usually requires code signing and notarization, otherwise Gatekeeper may block launch.
|
||||
|
||||
## Recommended Scope
|
||||
|
||||
### Phase 1: Internal Test Build
|
||||
|
||||
Target:
|
||||
|
||||
- `darwin/arm64` first
|
||||
- output `.app` and `.zip`
|
||||
- unsigned build is acceptable for internal testing
|
||||
|
||||
Why:
|
||||
|
||||
- Apple Silicon is the mainstream macOS target now
|
||||
- it keeps the first version smaller and easier to verify
|
||||
- it avoids spending time on Intel support before the runtime path is stable
|
||||
|
||||
### Phase 2: Public Distribution Build
|
||||
|
||||
Target:
|
||||
|
||||
- signed `.app`
|
||||
- notarized `.zip` or `.dmg`
|
||||
- optional `darwin/amd64` or universal build
|
||||
|
||||
Why:
|
||||
|
||||
- end users expect double-click install and normal launch
|
||||
- unsigned apps and embedded helper binaries are more likely to be blocked
|
||||
|
||||
## Recommended Runtime Layout
|
||||
|
||||
### App Bundle
|
||||
|
||||
Recommended structure inside the built app:
|
||||
|
||||
- `Ant Browser.app/Contents/MacOS/ant-chrome`
|
||||
- `Ant Browser.app/Contents/Resources/bin/xray`
|
||||
- `Ant Browser.app/Contents/Resources/bin/sing-box`
|
||||
- optional placeholder `chrome/README.md` if you want to keep behavior aligned with Linux
|
||||
|
||||
### User-Writable State
|
||||
|
||||
Recommended macOS state root:
|
||||
runtime state is redirected to:
|
||||
|
||||
- `~/Library/Application Support/ant-browser`
|
||||
|
||||
Recommended contents under the state root:
|
||||
Bundled runtime files remain in the app bundle:
|
||||
|
||||
- `Ant Browser.app/Contents/MacOS/bin/xray`
|
||||
- `Ant Browser.app/Contents/MacOS/bin/sing-box`
|
||||
|
||||
Writable files live in the user state root:
|
||||
|
||||
- `config.yaml`
|
||||
- `proxies.yaml`
|
||||
- `proxies.yaml` if present
|
||||
- `data/`
|
||||
- `chrome/`
|
||||
|
||||
Rule:
|
||||
## Local Launch
|
||||
|
||||
- runtime binaries stay in the app bundle
|
||||
- config, database, browser cores, logs, and profile data stay in the user state root
|
||||
After a successful build:
|
||||
|
||||
## Code Changes Required
|
||||
```bash
|
||||
open "publish/output/AntBrowser-<version>-macos-<arch>.app"
|
||||
```
|
||||
|
||||
### 1. Add macOS Writable State Handling
|
||||
For an unsigned local build copied to `/Applications`, remove quarantine if macOS blocks launch:
|
||||
|
||||
Current Linux detached-state logic only activates on Linux:
|
||||
```bash
|
||||
xattr -dr com.apple.quarantine "/Applications/Ant Browser.app"
|
||||
open "/Applications/Ant Browser.app"
|
||||
```
|
||||
|
||||
- `backend/internal/apppath/apppath.go`
|
||||
|
||||
Required change:
|
||||
|
||||
- extend path detection so installed macOS apps also use a detached writable state root
|
||||
- recommended trigger: when `GOOS=darwin` and app root is not writable, or when running from an `.app` bundle
|
||||
|
||||
Expected result:
|
||||
|
||||
- app launch from `/Applications` does not try to write config/data into the bundle
|
||||
|
||||
### 2. Add Darwin Runtime Binaries
|
||||
|
||||
Current runtime manifest has Windows and Linux only:
|
||||
|
||||
- `publish/runtime-manifest.json`
|
||||
|
||||
Required additions:
|
||||
|
||||
- `bin/darwin-arm64/xray`
|
||||
- `bin/darwin-arm64/sing-box`
|
||||
- optional `bin/darwin-amd64/xray`
|
||||
- optional `bin/darwin-amd64/sing-box`
|
||||
- manifest hash entries for the new targets
|
||||
|
||||
Status:
|
||||
|
||||
- implemented for both `darwin-arm64` and `darwin-amd64`
|
||||
- files are committed into the repository
|
||||
- runtime manifest verification now works for both Darwin targets
|
||||
|
||||
Related scripts to extend:
|
||||
|
||||
- `tools/runtime/sync-runtime.py`
|
||||
- `tools/runtime/update-runtime-manifest.py`
|
||||
- `tools/runtime/verify-runtime.sh`
|
||||
|
||||
### 3. Add macOS Publish Script
|
||||
|
||||
New file to add:
|
||||
|
||||
- `publish/mac/publish-mac.sh`
|
||||
|
||||
Recommended responsibilities:
|
||||
|
||||
1. verify host is macOS
|
||||
2. verify target arch (`arm64` first)
|
||||
3. install frontend dependencies
|
||||
4. build frontend
|
||||
5. run `wails build -platform darwin/arm64`
|
||||
6. place runtime binaries into the app bundle
|
||||
7. optionally archive to `.zip`
|
||||
8. optionally sign and notarize when environment variables are provided
|
||||
|
||||
Current scaffold status:
|
||||
|
||||
- implemented as an unsigned internal-build script
|
||||
- outputs `.app` plus `.zip`
|
||||
- requires a native macOS host
|
||||
- intentionally does not attempt notarization yet
|
||||
|
||||
### 4. Add macOS Runtime Placement Logic
|
||||
|
||||
The app currently resolves most paths through shared runtime helpers, which is good.
|
||||
|
||||
Files likely involved:
|
||||
|
||||
- `backend/app.go`
|
||||
- `backend/app_paths.go`
|
||||
- `backend/app_utils.go`
|
||||
- `backend/internal/browser/types.go`
|
||||
- `backend/internal/proxy/xray.go`
|
||||
- `backend/internal/proxy/singbox.go`
|
||||
- `main.go`
|
||||
|
||||
Goal:
|
||||
|
||||
- all writable files go to the user state root
|
||||
- helper binaries continue to resolve from the app bundle
|
||||
|
||||
### 5. Signing and Notarization
|
||||
|
||||
This is not required for a first internal test build, but is required for a serious public release.
|
||||
|
||||
Needed later:
|
||||
|
||||
- Apple Developer certificate
|
||||
- `codesign`
|
||||
- `notarytool`
|
||||
- entitlements if runtime behavior requires them
|
||||
|
||||
Typical flow:
|
||||
|
||||
1. sign helper binaries
|
||||
2. sign the `.app`
|
||||
3. zip or build dmg
|
||||
4. notarize
|
||||
5. staple
|
||||
|
||||
## Recommended Implementation Order
|
||||
|
||||
1. Deliver `darwin/arm64` internal test build only.
|
||||
2. Add macOS detached state root.
|
||||
3. Add Darwin runtime binaries and manifest support.
|
||||
4. Add `publish/mac/publish-mac.sh`.
|
||||
5. Verify launch from `/Applications`.
|
||||
6. Verify browser core placement under user state root.
|
||||
7. Verify proxy runtime launch on macOS.
|
||||
8. Add signing and notarization only after the unsigned build is stable.
|
||||
9. Decide whether `darwin/amd64` is worth supporting.
|
||||
Unsigned builds are not suitable for public distribution. A public macOS release still needs Developer ID signing, helper binary signing, notarization, and staple.
|
||||
|
||||
## Validation Checklist
|
||||
|
||||
The macOS work should not be considered complete until all items below are verified on a real Mac.
|
||||
|
||||
### Packaging
|
||||
|
||||
- build completes on native macOS
|
||||
- output `.app` exists
|
||||
- output `.zip` or `.dmg` exists
|
||||
- bundled helper binaries are executable
|
||||
|
||||
### First Launch
|
||||
|
||||
- app launches from Finder
|
||||
- app launches after copying to `/Applications`
|
||||
- output `.zip` exists
|
||||
- `Contents/MacOS/ant-chrome` is executable
|
||||
- bundled `xray` and `sing-box` are executable
|
||||
- app launches from Finder or `open`
|
||||
- first launch creates `~/Library/Application Support/ant-browser`
|
||||
- `config.yaml` is seeded correctly
|
||||
- database and `data/` are created under the user state root
|
||||
|
||||
### Browser Core
|
||||
|
||||
- manually placed browser core can be detected
|
||||
- browser core path persists in config or database
|
||||
- browser instance can actually start
|
||||
|
||||
### Proxy Runtime
|
||||
|
||||
- `xray` can be launched from the app bundle
|
||||
- `sing-box` can be launched from the app bundle
|
||||
- work directories are created under the user state root
|
||||
|
||||
### Exit Behavior
|
||||
|
||||
- window close works
|
||||
- explicit quit works
|
||||
- no stuck background process remains after quit
|
||||
|
||||
### Regression Safety
|
||||
|
||||
- Windows packaging still builds
|
||||
- Linux packaging still builds
|
||||
- Linux detached state behavior still works
|
||||
|
||||
## Difficulty Assessment
|
||||
|
||||
### Internal Test Build
|
||||
|
||||
Difficulty: medium
|
||||
|
||||
Main blockers:
|
||||
|
||||
- mac runtime binaries
|
||||
- detached writable state
|
||||
- mac packaging script
|
||||
|
||||
### Public Release Build
|
||||
|
||||
Difficulty: medium-high
|
||||
|
||||
Main blockers:
|
||||
|
||||
- signing
|
||||
- notarization
|
||||
- quarantine / Gatekeeper behavior
|
||||
- helper binary signing order
|
||||
|
||||
## Suggested First Deliverable
|
||||
|
||||
The safest first milestone is:
|
||||
|
||||
- macOS `arm64`
|
||||
- native build on a real Mac
|
||||
- unsigned `.app`
|
||||
- zipped artifact for internal testing
|
||||
- detached writable state under `~/Library/Application Support/ant-browser`
|
||||
- bundled `xray` and `sing-box`
|
||||
|
||||
Do not start with:
|
||||
|
||||
- universal binary
|
||||
- dmg beautification
|
||||
- public distribution
|
||||
- Intel support
|
||||
|
||||
Those can come after the app is proven stable on one Mac target first.
|
||||
|
||||
## Files Expected To Be Added Or Updated
|
||||
|
||||
Likely new files:
|
||||
|
||||
- `publish/mac/publish-mac.sh`
|
||||
- `publish/mac/README.md`
|
||||
|
||||
Likely updated files:
|
||||
|
||||
- `backend/internal/apppath/apppath.go`
|
||||
- `backend/internal/apppath/apppath_test.go`
|
||||
- `backend/runtime_paths.go`
|
||||
- `backend/app.go`
|
||||
- `main.go`
|
||||
- `publish/runtime-manifest.json`
|
||||
- `publish/runtime-sources.json`
|
||||
- `tools/runtime/sync-runtime.py`
|
||||
- `tools/runtime/update-runtime-manifest.py`
|
||||
- `tools/runtime/verify-runtime.sh`
|
||||
|
||||
## Decision Record
|
||||
|
||||
Current recommendation:
|
||||
|
||||
- do macOS `arm64` first
|
||||
- solve writable state before touching signing
|
||||
- keep Windows and Linux publish flows unchanged unless shared runtime code needs extension
|
||||
- treat public notarized distribution as Phase 2, not Phase 1
|
||||
- `config.yaml` is seeded with `--fingerprint-platform=mac`
|
||||
- SQLite database and `data/` are created under the user state root
|
||||
- browser core detection works for macOS `.app` cores
|
||||
- proxy runtime binaries can be launched from the app bundle
|
||||
|
||||
Reference in New Issue
Block a user