From 0becd6da716dbca1836a77dd823d4e84fd2a93ec Mon Sep 17 00:00:00 2001 From: akash-aman Date: Sun, 11 Oct 2026 09:06:36 +0530 Subject: [PATCH] ci: publish releases with GoReleaser on version tags - Pushing a v* tag runs vet and the race tests, then GoReleaser builds agent-browser-mcp for macOS, Linux and Windows (amd64 and arm64) and publishes the archives, checksums and a grouped changelog. - CI runs gofmt, vet, the race tests and a snapshot release build on every pull request and push to main. - The version comes from the tag (-X main.version), or from the module version Go stamps into the binary, instead of a hard-coded 2.0.0. - The README offers the release download before building from source, and says how to cut a release. --- .github/workflows/ci.yml | 26 ++++++++++++++++ .github/workflows/release.yml | 27 +++++++++++++++++ .gitignore | 3 ++ .goreleaser.yaml | 56 +++++++++++++++++++++++++++++++++++ README.md | 5 +++- main.go | 22 ++++++++++++-- 6 files changed, 135 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/release.yml create mode 100644 .goreleaser.yaml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..c66669a --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,26 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + +permissions: + contents: read + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - uses: actions/setup-go@v7 + with: + go-version-file: go.mod + - name: gofmt + run: test -z "$(gofmt -l .)" || { gofmt -l .; exit 1; } + - run: go vet ./... + - run: go test -race ./... + - uses: goreleaser/goreleaser-action@v7 + with: + version: "~> v2" + args: release --snapshot --clean --skip=publish diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..bcba6eb --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,27 @@ +name: Release + +on: + push: + tags: ["v*"] + +permissions: + contents: write + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + with: + fetch-depth: 0 # the changelog compares with the previous tag + - uses: actions/setup-go@v7 + with: + go-version-file: go.mod + - run: go vet ./... + - run: go test -race ./... + - uses: goreleaser/goreleaser-action@v7 + with: + version: "~> v2" + args: release --clean + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 7aaba5c..18ff2f9 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,6 @@ Thumbs.db # Go vendor/ + +# Release builds (goreleaser) +dist/ diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000..d972dd5 --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,56 @@ +# Builds the release binaries when a v* tag is pushed (.github/workflows/release.yml). +# Try it locally: goreleaser release --snapshot --clean +version: 2 + +project_name: agent-browser-mcp + +before: + hooks: + - go mod tidy -diff + +builds: + - binary: agent-browser-mcp + env: + - CGO_ENABLED=0 + goos: [darwin, linux, windows] + goarch: [amd64, arm64] + flags: + - -trimpath + ldflags: + - -s -w -X main.version={{ .Version }} + mod_timestamp: "{{ .CommitTimestamp }}" + +archives: + - formats: [tar.gz] + format_overrides: + - goos: windows + formats: [zip] + files: + - README.md + - LICENSE + +checksum: + name_template: checksums.txt + +changelog: + use: github + sort: asc + groups: + - title: Features + regexp: '^.*?feat(\(.+\))??!?:.+$' + order: 0 + - title: Fixes + regexp: '^.*?fix(\(.+\))??!?:.+$' + order: 1 + - title: Other changes + order: 999 + filters: + exclude: + - "^Merge " + +release: + prerelease: auto + header: | + Download the archive for your system, unpack it, and add the `agent-browser-mcp` binary to your MCP client (see the [Quick start](https://github.com/xcode-studio/agentbrowser-mcp#-quick-start)). It needs the [agent-browser](https://github.com/vercel-labs/agent-browser) CLI 0.38.0 or newer. + + On macOS, a binary downloaded with a browser is quarantined; clear it once with `xattr -d com.apple.quarantine agent-browser-mcp`. diff --git a/README.md b/README.md index dca04ad..d13678b 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,9 @@ Use Claude in Chrome for tasks in your own browser and quick checks of a page. U agent-browser install ``` -2. Build the server (Go 1.26+): +2. Download the server for your system from [Releases](https://github.com/xcode-studio/agentbrowser-mcp/releases) and unpack it. On macOS, a binary downloaded with a browser is quarantined; clear it once with `xattr -d com.apple.quarantine agent-browser-mcp`. + + Or build it (Go 1.26+): ```bash git clone https://github.com/xcode-studio/agentbrowser-mcp.git @@ -301,6 +303,7 @@ go build -o agent-browser-mcp . && go run docs/demo/main.go # re-record the de - **Fakes:** unit tests run every tool against a fake agent-browser that records its arguments, and a fake Chrome that records protocol calls. - **Guards:** coverage tests fail if a tool or enum value has no test case. Budget tests keep `tools/list` under 48 KB and the instructions under Claude Code's 2,048-character limit. - **Lighthouse:** set `LIGHTHOUSE_PATH=$(which lighthouse)` to include the Lighthouse audit in the integration run. +- **Releases:** push a tag such as `v2.0.1`. GitHub Actions runs the tests, builds macOS, Linux and Windows binaries (amd64 and arm64) with [GoReleaser](https://goreleaser.com), and publishes them with a changelog. `goreleaser release --snapshot --clean` builds the same archives locally into `dist/`. ## 🤝 Contributing diff --git a/main.go b/main.go index 6a4d9be..d548bc3 100644 --- a/main.go +++ b/main.go @@ -8,6 +8,8 @@ import ( "fmt" "os" "os/signal" + "runtime/debug" + "strings" "sync" "syscall" @@ -18,9 +20,23 @@ import ( mcpsrv "github.com/xcode-studio/agentbrowser-mcp/internal/mcp" ) -const version = "2.0.0" +// version is set by release builds (-X main.version=...). Without it, the +// module version Go stamps into the binary is used: the tag for go install, +// or a pseudo-version for go build in a clone. +var version = "" + +func buildVersion() string { + if version != "" { + return version + } + if bi, ok := debug.ReadBuildInfo(); ok && bi.Main.Version != "" && bi.Main.Version != "(devel)" { + return strings.TrimPrefix(bi.Main.Version, "v") + } + return "dev" +} func main() { + ver := buildVersion() cfg, err := config.Load(os.Args[1:]) if err != nil { fmt.Fprintln(os.Stderr, "agent-browser-mcp: configuration error:", err) @@ -28,9 +44,9 @@ func main() { } mgr := browser.NewManager(cfg) - s, shutdown := mcpsrv.NewServer(version, cfg, mgr) + s, shutdown := mcpsrv.NewServer(ver, cfg, mgr) - fmt.Fprintf(os.Stderr, "agent-browser-mcp %s: listening on stdio; %s\n", version, mgr.CheckVersion(context.Background())) + fmt.Fprintf(os.Stderr, "agent-browser-mcp %s: listening on stdio; %s\n", ver, mgr.CheckVersion(context.Background())) stop := sync.OnceFunc(func() { shutdown(context.Background()) }) // A client stops a stdio server with SIGINT, then SIGTERM and SIGKILL // within half a second (Claude Code on reconnect). ServeStdio first waits