name: Windows Setup E2E # End-to-end fresh-install gate for Windows. Runs `./setup` on a clean # windows-latest checkout and asserts the build completes, binaries # resolve via find-browse, and the gstack-paths state root resolves # cleanly. Catches Bun shell-parser regressions in package.json's build # chain (#1538, #1537, #1530, #1457, #1561) before they reach users. # # Separate from windows-free-tests.yml because that one runs a curated # unit-test subset; this one exercises the install path itself. # # Runner: GitHub-hosted free windows-latest. ~3-5 min total. on: pull_request: branches: [main] paths: - 'package.json' - 'scripts/build.sh' - 'scripts/write-version-files.sh' - 'setup' - 'browse/src/cli.ts' - 'browse/src/find-browse.ts' - 'bin/gstack-paths' - '.github/workflows/windows-setup-e2e.yml' workflow_dispatch: concurrency: group: windows-setup-e2e-${{ github.head_ref }} cancel-in-progress: true jobs: windows-setup: runs-on: windows-latest timeout-minutes: 15 steps: - uses: actions/checkout@v4 - uses: oven-sh/setup-bun@v1 with: bun-version: latest - name: Configure git identity run: | git config --global user.email "windows-setup-e2e@gstack.test" git config --global user.name "Windows Setup E2E" git config --global init.defaultBranch main shell: bash - name: Install dependencies run: bun install --frozen-lockfile shell: bash - name: Run bun run build (the previously-broken path) # This is the regression gate. Bun's Windows shell parser rejected # multiple constructs the old inline build chain used; the wave # moved the build to scripts/build.sh. If this step fails on # Windows, the build chain regressed. run: bun run build shell: bash env: GSTACK_SKIP_PLAYWRIGHT: '1' - name: Verify binaries exist (with .exe extension on Windows) run: | set -e test -f browse/dist/browse.exe || test -f browse/dist/browse || (echo "MISSING: browse" && exit 1) test -f browse/dist/find-browse.exe || test -f browse/dist/find-browse || (echo "MISSING: find-browse" && exit 1) test -f design/dist/design.exe || test -f design/dist/design || (echo "MISSING: design" && exit 1) test -f bin/gstack-global-discover.exe || test -f bin/gstack-global-discover || (echo "MISSING: gstack-global-discover" && exit 1) echo "All binaries present" shell: bash - name: Verify find-browse resolves to the .exe variant run: | set -e OUT=$(bun browse/src/find-browse.ts 2>&1) || true echo "find-browse output: $OUT" # On Windows, find-browse should successfully resolve to a binary, # whether or not it has the .exe extension on disk. Empty output # or "not found" means the .exe extension resolver regressed. echo "$OUT" | grep -qE '(browse\.exe|browse)$' || (echo "find-browse failed to resolve binary on Windows" && exit 1) shell: bash - name: Verify gstack-paths state root resolves run: | set -e eval "$(bash bin/gstack-paths)" test -n "$GSTACK_STATE_ROOT" || (echo "GSTACK_STATE_ROOT empty" && exit 1) test -n "$PLAN_ROOT" || (echo "PLAN_ROOT empty" && exit 1) test -n "$TMP_ROOT" || (echo "TMP_ROOT empty" && exit 1) echo "GSTACK_STATE_ROOT=$GSTACK_STATE_ROOT" echo "PLAN_ROOT=$PLAN_ROOT" echo "TMP_ROOT=$TMP_ROOT" shell: bash