From 7b0badeddd9e844be0eff3f2c0335fe60aef9214 Mon Sep 17 00:00:00 2001 From: franklin Date: Fri, 22 May 2026 11:50:07 +0200 Subject: [PATCH] refactor: make menubar independent --- .github/workflows/release.yml | 50 +++++++++++++++++++ Makefile | 11 ++++ README.md | 8 +-- cmd/dockprox-menubar/Info.plist | 26 ++++++++++ .../dockprox-menubar/main.go | 28 +++++------ cmd/dockprox-menubar/main_other.go | 13 +++++ docs/.vitepress/config.mts | 1 - docs/guide/installation.md | 2 +- docs/guide/menubar.md | 23 +++------ docs/reference/cli/dockprox.md | 1 - docs/reference/cli/dockprox_menubar.md | 19 ------- internal/cli/menubar_other.go | 18 ------- internal/cli/root.go | 2 +- 13 files changed, 127 insertions(+), 75 deletions(-) create mode 100644 cmd/dockprox-menubar/Info.plist rename internal/cli/menubar_darwin.go => cmd/dockprox-menubar/main.go (66%) create mode 100644 cmd/dockprox-menubar/main_other.go delete mode 100644 docs/reference/cli/dockprox_menubar.md delete mode 100644 internal/cli/menubar_other.go diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5ba5c2a..4f0ea06 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -43,3 +43,53 @@ jobs: args: release --clean env: GITHUB_TOKEN: ${{ steps.app_token.outputs.token }} + + release-menubar: + needs: release + runs-on: macos-latest + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - uses: actions/setup-go@v6 + with: + check-latest: true + go-version-file: go.mod + + - id: app_token + uses: tibdex/github-app-token@v2 + with: + app_id: ${{ secrets.TOKEN_APP_ID }} + private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }} + + - name: Build .app bundles + env: + VERSION: ${{ github.ref_name }} + run: | + set -euo pipefail + V="${VERSION#v}" + mkdir -p dist + for ARCH in arm64 amd64; do + APP="dist/dockprox.app" + rm -rf "$APP" + mkdir -p "$APP/Contents/MacOS" "$APP/Contents/Resources" + sed "s/__VERSION__/${V}/g" cmd/dockprox-menubar/Info.plist > "$APP/Contents/Info.plist" + CARCH="${ARCH}" + [ "$ARCH" = "amd64" ] && CARCH="x86_64" + CGO_ENABLED=1 \ + CGO_CFLAGS="-arch ${CARCH}" \ + CGO_LDFLAGS="-arch ${CARCH}" \ + GOOS=darwin GOARCH="${ARCH}" \ + go build -tags=safe -trimpath \ + -ldflags="-s -w -X github.com/foomo/dockprox/internal/cli.version=${V} -X github.com/foomo/dockprox/internal/cli.commitHash=${{ github.sha }}" \ + -o "$APP/Contents/MacOS/dockprox-menubar" ./cmd/dockprox-menubar + tar -czf "dist/dockprox-menubar_${V}_darwin_${ARCH}.tar.gz" -C dist dockprox.app + done + + - name: Upload to release + env: + GH_TOKEN: ${{ steps.app_token.outputs.token }} + run: | + gh release upload "${{ github.ref_name }}" \ + dist/dockprox-menubar_*_darwin_*.tar.gz --clobber diff --git a/Makefile b/Makefile index 57fb3c5..40e619c 100644 --- a/Makefile +++ b/Makefile @@ -71,6 +71,17 @@ build: @rm -f bin/dockprox @go build -o bin/dockprox cmd/dockprox/dockprox.go +.PHONY: build.menubar +## Build macOS menubar app binary (darwin only) +build.menubar: +ifeq ($(shell uname),Darwin) + @echo "〉go build bin/dockprox-menubar" + @rm -f bin/dockprox-menubar + @go build -tags=safe -o bin/dockprox-menubar ./cmd/dockprox-menubar +else + $(error build.menubar requires macOS) +endif + .PHONY: build.debug ## Build binary in debug mode build.debug: diff --git a/README.md b/README.md index 95c0f42..6defb73 100644 --- a/README.md +++ b/README.md @@ -155,24 +155,24 @@ Requires Go 1.26+. ## macOS menu bar app -A native menu bar (tray) app ships as the `menubar` subcommand of the `dockprox` binary. It runs a dockprox proxy in-process and exposes Start / Stop / Restart / Reveal-config-in-Finder / Quit from the system tray. +A native menu bar (tray) app ships as a separate `dockprox-menubar` binary (macOS only, Wails-backed). It runs a dockprox proxy in-process and exposes Start / Stop / Restart / Reveal-config-in-Finder / Quit from the system tray. Build: ```shell -make build +make build.menubar ``` Run: ```shell -bin/dockprox menubar +bin/dockprox-menubar ``` Run from source: ```shell -go run -tags=safe ./cmd/dockprox menubar +go run -tags=safe ./cmd/dockprox-menubar ``` Config is resolved from `$XDG_CONFIG_HOME/dockprox/config.yaml` (or `~/.config/dockprox/config.yaml` if `XDG_CONFIG_HOME` is unset), falling back to `~/.dockprox.yaml`. If neither exists at launch, a default config is written to one of those locations (XDG when `$XDG_CONFIG_HOME` is set; otherwise the dotfile). diff --git a/cmd/dockprox-menubar/Info.plist b/cmd/dockprox-menubar/Info.plist new file mode 100644 index 0000000..d1747b3 --- /dev/null +++ b/cmd/dockprox-menubar/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleIdentifier + com.foomo.dockprox + CFBundleName + dockprox + CFBundleDisplayName + dockprox + CFBundleExecutable + dockprox-menubar + CFBundlePackageType + APPL + CFBundleVersion + __VERSION__ + CFBundleShortVersionString + __VERSION__ + LSUIElement + + LSMinimumSystemVersion + 11.0 + NSHighResolutionCapable + + + diff --git a/internal/cli/menubar_darwin.go b/cmd/dockprox-menubar/main.go similarity index 66% rename from internal/cli/menubar_darwin.go rename to cmd/dockprox-menubar/main.go index 02cd74b..f4f8c08 100644 --- a/internal/cli/menubar_darwin.go +++ b/cmd/dockprox-menubar/main.go @@ -1,36 +1,34 @@ //go:build darwin -package cli +// Command dockprox-menubar runs the macOS menu bar (tray) app that drives a +// dockprox proxy in-process. +package main import ( + "flag" "os" "os/signal" "syscall" "github.com/charmbracelet/log" "github.com/foomo/dockprox/internal/menubar" - "github.com/spf13/cobra" "github.com/wailsapp/wails/v3/pkg/application" "github.com/wailsapp/wails/v3/pkg/events" ) -func newMenubarCmd() *cobra.Command { - var cfgPath string +func main() { + cfgPath := flag.String("config", "", "YAML config file (default: auto-resolve)") - cmd := &cobra.Command{ - Use: "menubar", - Short: "Run the macOS menu bar app", - RunE: func(cmd *cobra.Command, _ []string) error { - return runMenubar(cmd, cfgPath) - }, - } - cmd.Flags().StringVar(&cfgPath, "config", "", "YAML config file (default: auto-resolve)") + flag.Parse() - return cmd + if err := run(*cfgPath); err != nil { + log.Error("menubar exited with error", "err", err) + os.Exit(1) + } } -func runMenubar(cmd *cobra.Command, cfgPath string) error { - logger := log.NewWithOptions(cmd.ErrOrStderr(), log.Options{ReportTimestamp: true}) +func run(cfgPath string) error { + logger := log.NewWithOptions(os.Stderr, log.Options{ReportTimestamp: true}) if cfgPath == "" { resolved, err := menubar.Resolve() diff --git a/cmd/dockprox-menubar/main_other.go b/cmd/dockprox-menubar/main_other.go new file mode 100644 index 0000000..4cad005 --- /dev/null +++ b/cmd/dockprox-menubar/main_other.go @@ -0,0 +1,13 @@ +//go:build !darwin + +package main + +import ( + "fmt" + "os" +) + +func main() { + fmt.Fprintln(os.Stderr, "dockprox-menubar is only supported on macOS") + os.Exit(1) +} diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index b75aec3..27c0b91 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -42,7 +42,6 @@ export default defineConfig({ items: [ { text: 'dockprox', link: '/reference/cli/dockprox' }, { text: 'dockprox serve', link: '/reference/cli/dockprox_serve' }, - { text: 'dockprox menubar', link: '/reference/cli/dockprox_menubar' }, { text: 'dockprox version', link: '/reference/cli/dockprox_version' }, ], }, diff --git a/docs/guide/installation.md b/docs/guide/installation.md index f158c4c..46151dc 100644 --- a/docs/guide/installation.md +++ b/docs/guide/installation.md @@ -28,4 +28,4 @@ Requires Go 1.26+. ## macOS menu bar app -The `dockprox` binary includes a macOS tray app — see [Menu bar app](./menubar.md). +A separate `dockprox-menubar` binary ships the macOS tray app — see [Menu bar app](./menubar.md). diff --git a/docs/guide/menubar.md b/docs/guide/menubar.md index d9ba829..ade50bf 100644 --- a/docs/guide/menubar.md +++ b/docs/guide/menubar.md @@ -1,30 +1,24 @@ # Menu bar app (macOS) -A native menu bar (tray) app ships as the `menubar` subcommand of the `dockprox` binary. It runs a `dockprox` proxy in-process and exposes Start / Stop / Restart / Reveal-config-in-Finder / Quit from the system tray. +A native menu bar (tray) app ships as a separate `dockprox-menubar` binary. It runs a `dockprox` proxy in-process and exposes Start / Stop / Restart / Reveal-config-in-Finder / Quit from the system tray. ::: info Platform -The menu bar app is **macOS only**. On other operating systems the `menubar` subcommand is registered but exits with an unsupported-platform error. +The menu bar app is **macOS only** (Wails-backed, requires cgo + macOS SDK). It is not part of the standard `dockprox` release archives — build it locally on a Mac. ::: -## Run +## Build & run -After [installing](./installation.md) `dockprox`: +From this repo on macOS: ```sh -dockprox menubar -``` - -Or build and run from this repo: - -```sh -make build -bin/dockprox menubar +make build.menubar +bin/dockprox-menubar ``` Or run from source: ```sh -go run -tags=safe ./cmd/dockprox menubar +go run -tags=safe ./cmd/dockprox-menubar ``` The proxy auto-starts when the app launches. The tray icon reflects the running / stopped state. @@ -32,7 +26,7 @@ The proxy auto-starts when the app launches. The tray icon reflects the running ## Flags ```sh -dockprox menubar [--config PATH] +dockprox-menubar [--config PATH] ``` | Flag | Description | @@ -68,5 +62,4 @@ Edit the resolved config file with any editor and use **Restart** to apply chang ## See also -- [`dockprox menubar`](../reference/cli/dockprox_menubar.md) CLI reference - [Configuration](./configuration.md) diff --git a/docs/reference/cli/dockprox.md b/docs/reference/cli/dockprox.md index 03041e7..3da09db 100644 --- a/docs/reference/cli/dockprox.md +++ b/docs/reference/cli/dockprox.md @@ -14,7 +14,6 @@ dockprox is a local HTTP(S) proxy that bypasses traffic by default and routes on ### SEE ALSO -* [dockprox menubar](dockprox_menubar.md) - Run the macOS menu bar app * [dockprox serve](dockprox_serve.md) - Run the proxy server * [dockprox version](dockprox_version.md) - Print version information diff --git a/docs/reference/cli/dockprox_menubar.md b/docs/reference/cli/dockprox_menubar.md deleted file mode 100644 index e9eeb1d..0000000 --- a/docs/reference/cli/dockprox_menubar.md +++ /dev/null @@ -1,19 +0,0 @@ -## dockprox menubar - -Run the macOS menu bar app - -``` -dockprox menubar [flags] -``` - -### Options - -``` - --config string YAML config file (default: auto-resolve) - -h, --help help for menubar -``` - -### SEE ALSO - -* [dockprox](dockprox.md) - Inverse Docker proxy with SOCKS5 support - diff --git a/internal/cli/menubar_other.go b/internal/cli/menubar_other.go deleted file mode 100644 index 5fe613a..0000000 --- a/internal/cli/menubar_other.go +++ /dev/null @@ -1,18 +0,0 @@ -//go:build !darwin - -package cli - -import ( - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -func newMenubarCmd() *cobra.Command { - return &cobra.Command{ - Use: "menubar", - Short: "Run the macOS menu bar app (macOS only)", - RunE: func(*cobra.Command, []string) error { - return errors.New("menubar is only supported on macOS") - }, - } -} diff --git a/internal/cli/root.go b/internal/cli/root.go index 6c2a3e8..054fd60 100644 --- a/internal/cli/root.go +++ b/internal/cli/root.go @@ -27,7 +27,7 @@ func NewRoot() *cobra.Command { SilenceErrors: true, SilenceUsage: true, } - root.AddCommand(newServeCmd(), newMenubarCmd(), newVersionCmd()) + root.AddCommand(newServeCmd(), newVersionCmd()) return root }