mirror of
https://github.com/garrytan/gstack.git
synced 2026-09-10 23:19:09 +02:00
bin/gstack-slug is a `#!/usr/bin/env bash` script with no file extension. Windows honors neither the shebang nor PATHEXT for an explicit path, so spawnSync fails ENOENT and resolveSlug returned its literal fallback, "unknown". Every decision on the machine was therefore filed under ~/.gstack/projects/unknown/ -- one bucket shared by every project -- while the bash-side Context Recovery preamble resolved the real slug, found no decisions.active.json there, and skipped through a bare `if [ -f ... ]` with no else. Nothing failed. Both decision bins (log and search) missed identically, so writes and searches stayed consistent with each other, and the only component that resolved correctly was silent by design. Measured on one machine: 62 decisions accumulated over 10 days and 170 skill runs, surfaced zero times. shell:true is not the fix here, unlike #1731 -- cmd.exe cannot run a bash script either. Nor is re-spawning through `bash`: on Windows that frequently resolves to WSL, whose $HOME and /mnt/c paths yield a different slug AND a different cache directory, trading one split store for another. Instead, port gstack-slug's own three steps (cache -> git remote -> basename), keeping its alphabet and its MSYS-form cache key so both paths agree. The fallback is win32-gated, so POSIX behaviour is byte-identical. Tests exercise the fallback on every platform (only the gating is win32-specific), so POSIX CI catches a regression that would otherwise surface only on a Windows user's disk, plus a static gate pinning the platform check.
132 lines
6.1 KiB
YAML
132 lines
6.1 KiB
YAML
name: Windows Free Tests
|
|
|
|
# Curated subset of the free test suite that runs on a paid faster Windows runner.
|
|
#
|
|
# Codex's v1.18.0.0 review flagged that the existing evals.yml workflow uses
|
|
# a Linux container, so a windows-latest matrix entry there isn't a drop-in.
|
|
# This workflow is non-container, runs the curated Windows-safe subset, plus
|
|
# targeted resolver tests that exercise the Bun.which-based claude binary
|
|
# resolution + the GSTACK_CLAUDE_BIN override path on Windows.
|
|
#
|
|
# Runner: GitHub-hosted free `windows-latest`. The whole rest of CI runs on
|
|
# Ubicloud (Linux), but Ubicloud doesn't ship Windows runners and we don't
|
|
# want to flip on GitHub's org-level larger-runner billing for just this one
|
|
# job. 4 cores, ~60s spin-up, $0. The wave-coverage tests this runs are
|
|
# small enough that total job time stays under 2 minutes.
|
|
#
|
|
# What this DOES NOT do (still out of scope, tracked as follow-up):
|
|
# - Run the full free suite on Windows. The 24 tests that hardcode /bin/sh,
|
|
# spawn('sh',...), or raw /tmp/ paths are excluded by scripts/test-free-shards.ts
|
|
# --windows-only. They need POSIX-bound surfaces to be ported off shell
|
|
# primitives before they can run on Windows.
|
|
# - Run Playwright/browser-backed tests. Browse server bring-up on Windows is
|
|
# a separate concern (PR #1238 windows-pty-bun-pty-fix is in flight).
|
|
|
|
on:
|
|
pull_request:
|
|
branches: [main]
|
|
workflow_dispatch:
|
|
|
|
concurrency:
|
|
group: windows-free-${{ github.event.pull_request.number || github.run_id }}
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
windows-free-tests:
|
|
# Ubicloud Windows runner (same provider as the Linux evals workflow).
|
|
# To revert: swap to `windows-latest` (GitHub's free 4-core Windows runner).
|
|
runs-on: windows-latest
|
|
timeout-minutes: 15
|
|
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- uses: oven-sh/setup-bun@v1
|
|
with:
|
|
bun-version: 1.3.13
|
|
|
|
# bun install was 35s of a 55s job, all network. Cache keyed on the
|
|
# lockfile; bun's install cache lives under ~/.bun/install/cache on
|
|
# every platform.
|
|
- uses: actions/cache@v4
|
|
with:
|
|
path: ~/.bun/install/cache
|
|
key: windows-bun-${{ hashFiles('bun.lock') }}
|
|
|
|
- name: Configure git identity (required by tests that init temp repos)
|
|
run: |
|
|
git config --global user.email "windows-ci@gstack.test"
|
|
git config --global user.name "Windows CI"
|
|
git config --global init.defaultBranch main
|
|
shell: bash
|
|
|
|
- name: Install dependencies
|
|
run: bun install --frozen-lockfile
|
|
|
|
- name: Build server-node.mjs (required by Windows browse path)
|
|
# browse/src/cli.ts module-level throws on Windows if server-node.mjs
|
|
# is missing — Bun can't drive Playwright's Chromium on Windows
|
|
# (oven-sh/bun#4253). The bundle must exist for any test that
|
|
# transitively loads cli.ts to even import. We build only the
|
|
# Node-compatible server bundle here; full `bun run build` would
|
|
# also compile every binary which is slow and unnecessary for tests.
|
|
run: bash browse/scripts/build-node-server.sh
|
|
shell: bash
|
|
|
|
- name: Generate host SKILL.md outputs (.agents, .factory)
|
|
# The golden-file regression tests in test/gen-skill-docs.test.ts read
|
|
# .agents/skills/gstack-ship/SKILL.md and .factory/skills/gstack-ship/
|
|
# SKILL.md. Both are gitignored — generated on demand by gen:skill-docs.
|
|
# On Mac/Linux CI the existing eval workflow regenerates these as part
|
|
# of its own pipeline; the windows-free-tests lane doesn't share that
|
|
# so it must regenerate explicitly.
|
|
run: bun run gen:skill-docs --host all
|
|
shell: bash
|
|
|
|
# The Windows job verifies the new portability work this PR delivers,
|
|
# not the entire free suite. After v1.20.0.0 ships, full-suite Windows
|
|
# parity is a P4 follow-up TODO that depends on porting many tests off
|
|
# POSIX-bound surfaces (raw /tmp paths, /bin/bash hardcodes, bash
|
|
# shebang spawns, mode-bit assertions, deleted v1.14 sidebar refs, etc).
|
|
#
|
|
# The curated subset enumeration in scripts/test-free-shards.ts is
|
|
# retained for future expansion — `bun run test:windows --list` gives
|
|
# contributors a starting point to grow Windows coverage incrementally.
|
|
#
|
|
# What we verify here is exactly the new code paths v1.20.0.0 ships:
|
|
# - bin/gstack-paths state-root resolution (test/gstack-paths.test.ts)
|
|
# - browse/src/claude-bin.ts Bun.which wrapper + override + arg-prefix
|
|
# resolution including the GSTACK_CLAUDE_BIN=wsl PATHEXT path
|
|
# (browse/test/claude-bin.test.ts)
|
|
# - scripts/test-free-shards.ts curation logic itself
|
|
# (test/test-free-shards.test.ts)
|
|
|
|
- name: Run curated Windows-safe suite
|
|
# Replaces the previous hand-listed 13-file subset, which drifted from
|
|
# the curation registry it was supposed to sample. The runner's
|
|
# --windows-only curation (scripts/test-free-shards.ts) is the single
|
|
# source of truth: POSIX-bound tests are excluded by pattern there, so
|
|
# growing/pruning Windows coverage is one list, not two. If a test is
|
|
# red here because it's genuinely POSIX-bound, add it to the curation
|
|
# exclusions — don't resurrect a hand list in this file.
|
|
env:
|
|
# Point os.tmpdir() at the runner temp so the shard logs land
|
|
# somewhere the artifact step below can glob.
|
|
TEMP: ${{ runner.temp }}
|
|
TMP: ${{ runner.temp }}
|
|
run: bun run test:windows
|
|
shell: bash
|
|
|
|
# Same diagnosability contract as free-tests.yml: a red lane must
|
|
# carry the WHY (the runner's quiet console names files, not causes).
|
|
# (#2561 was written against the old hand-listed subset; its two new
|
|
# test files are pure-TS and flow into the --windows-only curation
|
|
# automatically, so no per-file entry is needed here.)
|
|
- name: Upload shard logs on failure
|
|
if: failure()
|
|
uses: actions/upload-artifact@v4
|
|
with:
|
|
name: windows-free-test-shard-logs
|
|
path: ${{ runner.temp }}/gstack-free-test-*.log
|
|
if-no-files-found: ignore
|