diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6e6f34f..138bdf2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,13 +21,23 @@ jobs: mkdir -p internal/frontend/dist echo 'placeholder' > internal/frontend/dist/index.html - # VarDumper PHP parser placeholder (embedded via go:embed per-platform) + # VarDumper PHP parser placeholders (embedded via go:embed per-platform). + # Each GOOS/GOARCH has its own embed_*.go, so we need a stub for every + # target that CI compiles. mkdir -p modules/vardumper/bin echo 'placeholder' > modules/vardumper/bin/vardumper-parser-linux-amd64 + echo 'placeholder' > modules/vardumper/bin/vardumper-parser-windows-amd64.exe - name: Build run: go build ./cmd/buggregator + - name: Build (windows/amd64) + env: + GOOS: windows + GOARCH: amd64 + CGO_ENABLED: "0" + run: go build ./cmd/buggregator + - name: Vet run: go vet ./... diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index eb27307..9ebf925 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,13 +4,24 @@ on: push: tags: - 'v*' + # Manual trigger: lets you pick a frontend version without bumping the repo Variable. + workflow_dispatch: + inputs: + frontend_version: + description: 'Frontend release tag (overrides vars.FRONTEND_VERSION)' + required: false + default: '' permissions: contents: write packages: write env: - FRONTEND_VERSION: "1.32.0" + # Resolution order: + # 1) workflow_dispatch input (manual one-off) + # 2) repository Variable `FRONTEND_VERSION` (https://github.com/buggregator/server/settings/variables/actions) + # 3) hardcoded fallback so the workflow still works on forks without the Variable set. + FRONTEND_VERSION: ${{ inputs.frontend_version || vars.FRONTEND_VERSION || '1.32.0' }} PHP_VERSION: "8.4.19" jobs: @@ -86,8 +97,61 @@ jobs: name: buggregator-${{ matrix.goos }}-${{ matrix.goarch }} path: buggregator-${{ matrix.goos }}-${{ matrix.goarch }} - # TODO: Windows build disabled — box.phar cannot detect composer on Windows CI. - # See: https://github.com/box-project/box/issues/1097 + # Windows build. + # + # VarDumper is not available on Windows: static-php-cli does not ship a + # `micro.sfx` for Windows, so we can't bundle a standalone PHP runtime, and + # `box.phar` itself cannot reliably detect composer on the Windows runner + # (https://github.com/box-project/box/issues/1097). The Go server gates + # var-dump on `runtime.GOOS != "windows"` so the binary still boots — every + # other module (Sentry, SMTP, Monolog, Ray, Inspector, Profiler, HTTP-dump, + # SMS) works normally. The embedded vardumper binary is a stub byte so + # `go:embed bin/vardumper-parser-windows-amd64.exe` succeeds. + build-windows: + runs-on: ubuntu-latest + strategy: + matrix: + include: + - goos: windows + goarch: amd64 + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-go@v5 + with: + go-version-file: go.mod + + - name: Download frontend + run: | + mkdir -p internal/frontend/dist + ASSET_URL=$(curl -s "https://api.github.com/repos/buggregator/frontend/releases/tags/${FRONTEND_VERSION}" \ + | jq -r '.assets[0].url') + curl -sL -H "Accept: application/octet-stream" "$ASSET_URL" -o /tmp/frontend.zip + unzip -qo /tmp/frontend.zip -d internal/frontend/dist/ + + - name: Create VarDumper placeholder + run: | + mkdir -p modules/vardumper/bin + echo 'placeholder' > modules/vardumper/bin/vardumper-parser-${{ matrix.goos }}-${{ matrix.goarch }}.exe + + - name: Build + env: + GOOS: ${{ matrix.goos }} + GOARCH: ${{ matrix.goarch }} + CGO_ENABLED: "0" + run: | + VERSION=${GITHUB_REF_NAME#v} + # workflow_dispatch builds don't have a v* tag — fall back to "dev". + if [ -z "$VERSION" ] || [ "$VERSION" = "$GITHUB_REF_NAME" ]; then + VERSION="dev" + fi + go build -ldflags="-s -w -X main.version=${VERSION}" -o buggregator-${{ matrix.goos }}-${{ matrix.goarch }}.exe ./cmd/buggregator + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: buggregator-${{ matrix.goos }}-${{ matrix.goarch }} + path: buggregator-${{ matrix.goos }}-${{ matrix.goarch }}.exe docker: runs-on: ubuntu-latest @@ -144,12 +208,16 @@ jobs: platforms: linux/amd64,linux/arm64 build-args: | VERSION=${{ steps.meta.outputs.version }} + FRONTEND_VERSION=${{ env.FRONTEND_VERSION }} cache-from: type=gha cache-to: type=gha,mode=max release: + # Only attach binaries to the GitHub Release on a tag push; the manual + # workflow_dispatch path is for ad-hoc CI builds (artifacts only). + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/') runs-on: ubuntu-latest - needs: [build-unix] + needs: [build-unix, build-windows] steps: - name: Download all artifacts uses: actions/download-artifact@v4 diff --git a/Dockerfile b/Dockerfile index d445aa0..6c86c4e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,7 +25,7 @@ RUN ARCH=$(case ${TARGETARCH} in amd64) echo "x86_64";; arm64) echo "aarch64";; # Stage 2: Download frontend FROM alpine:3.20 AS frontend -ARG FRONTEND_VERSION=1.32.0 +ARG FRONTEND_VERSION=1.32.1 RUN apk add --no-cache curl unzip \ && mkdir -p /frontend \ && curl -sL "https://github.com/buggregator/frontend/releases/download/${FRONTEND_VERSION}/frontend-${FRONTEND_VERSION}.zip" -o /tmp/fe.zip \ diff --git a/cmd/buggregator/main.go b/cmd/buggregator/main.go index fb2e980..b7e7723 100644 --- a/cmd/buggregator/main.go +++ b/cmd/buggregator/main.go @@ -4,6 +4,7 @@ import ( "fmt" "log/slog" "os" + "runtime" "github.com/buggregator/go-buggregator/internal/app" mcpserver "github.com/buggregator/go-buggregator/internal/mcp" @@ -79,12 +80,22 @@ func main() { proxyMod := proxy.New(cfg.ProxyAddr) // Start VarDumper PHP parser (only if enabled). + // + // VarDumper bundles a standalone PHP runtime via static-php's micro.sfx, + // which has no Windows build. The embedded binary on Windows is a + // placeholder stub, so the parser would crash immediately — skip start-up + // entirely there and let the rest of the server run. TCPServers() returns + // nil when the parser isn't running, so the :9912 listener is also skipped. if enabled.IsEnabled("var-dump") { - if err := vardumperMod.StartPHP(); err != nil { - slog.Error("failed to start VarDumper PHP parser", "err", err) - os.Exit(1) + if runtime.GOOS == "windows" { + slog.Warn("VarDumper module is not supported on Windows; module disabled") + } else { + if err := vardumperMod.StartPHP(); err != nil { + slog.Error("failed to start VarDumper PHP parser", "err", err) + os.Exit(1) + } + defer vardumperMod.StopPHP() } - defer vardumperMod.StopPHP() } // Register enabled modules.